src/JackHandler.h
author František Kučera <franta-hg@frantovo.cz>
Wed, 30 Sep 2020 20:54:39 +0200
branchv_0
changeset 4 65dfbf0494a3
parent 3 baa8055c5b10
child 5 6be3464ccb2b
permissions -rw-r--r--
pass MIDI messages through the ring buffer (queue) from one thread to another
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     1
/**
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     2
 * Relational pipes
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     3
 * Copyright © 2018 František Kučera (Frantovo.cz, GlobalCode.info)
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     4
 *
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     5
 * This program is free software: you can redistribute it and/or modify
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     6
 * it under the terms of the GNU General Public License as published by
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     7
 * the Free Software Foundation, version 3 of the License.
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     8
 *
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
     9
 * This program is distributed in the hope that it will be useful,
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    12
 * GNU General Public License for more details.
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    13
 *
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    14
 * You should have received a copy of the GNU General Public License
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    15
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    16
 */
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    17
#pragma once
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    18
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    19
#include <memory>
3
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
    20
#include <atomic>
0
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    21
#include <string>
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    22
#include <vector>
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    23
#include <iostream>
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    24
#include <sstream>
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    25
#include <locale>
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    26
#include <codecvt>
1
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    27
#include <sys/mman.h>
3
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
    28
#include <signal.h>
4
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
    29
#include <unistd.h>
1
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    30
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    31
#include <jack/jack.h>
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    32
#include <jack/midiport.h>
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    33
#include <jack/ringbuffer.h>
0
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    34
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    35
#include <relpipe/common/type/typedefs.h>
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    36
#include <relpipe/reader/TypeId.h>
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    37
#include <relpipe/reader/handlers/RelationalReaderStringHandler.h>
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    38
#include <relpipe/reader/handlers/AttributeMetadata.h>
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    39
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    40
#include "Configuration.h"
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    41
#include "JackException.h"
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    42
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    43
namespace relpipe {
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    44
namespace out {
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    45
namespace jack {
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    46
3
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
    47
int dequeueMessages(jack_nframes_t frames, void* arg);
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
    48
0
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    49
class JackHandler : public relpipe::reader::handlers::RelationalReaderStringHandler {
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    50
private:
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    51
	Configuration& configuration;
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    52
	std::wstring_convert<std::codecvt_utf8<wchar_t>> convertor; // TODO: local system encoding
1
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    53
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    54
	jack_client_t* jackClient = nullptr;
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    55
	jack_port_t* jackPort = nullptr;
3
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
    56
	jack_ringbuffer_t* ringBuffer = nullptr;
4
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
    57
	pthread_mutex_t messageThreadLock = PTHREAD_MUTEX_INITIALIZER;
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
    58
	pthread_cond_t dataReady = PTHREAD_COND_INITIALIZER;
3
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
    59
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
    60
	std::atomic<bool> continueProcessing{true};
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
    61
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
    62
	const int RING_BUFFER_SIZE = 100;
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
    63
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
    64
	struct MidiMessage {
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
    65
		uint8_t buffer[4096];
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
    66
		uint32_t size;
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
    67
		uint32_t time;
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
    68
	};
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
    69
4
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
    70
	/**
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
    71
	 * The message being prepared before enqueing in the ringBuffer.
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
    72
	 * Not the message dequeued from the ringBuffer (different thread).
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
    73
	 */
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
    74
	MidiMessage currentMidiMessage;
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
    75
	size_t currentAttributeCount = 0;
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
    76
	size_t currentAttributeIndex = 0;
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
    77
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
    78
0
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    79
public:
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    80
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    81
	JackHandler(Configuration& configuration) : configuration(configuration) {
1
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    82
		// Initialize JACK connection:
2
01553c2ffa1d configurable JACK client name
František Kučera <franta-hg@frantovo.cz>
parents: 1
diff changeset
    83
		std::string clientName = convertor.to_bytes(configuration.jackClientName);
1
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    84
		jackClient = jack_client_open(clientName.c_str(), JackNullOption, nullptr);
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    85
		if (jackClient == nullptr) throw JackException(L"Could not create JACK client.");
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    86
3
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
    87
		ringBuffer = jack_ringbuffer_create(RING_BUFFER_SIZE * sizeof (MidiMessage));
1
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    88
3
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
    89
		jack_set_process_callback(jackClient, relpipe::out::jack::dequeueMessages, this);
1
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    90
		// TODO: report also other events (connections etc.)
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    91
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    92
		jackPort = jack_port_register(jackClient, "output", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    93
		if (jackPort == nullptr) throw JackException(L"Could not register port.");
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    94
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    95
		if (mlockall(MCL_CURRENT | MCL_FUTURE)) fwprintf(stderr, L"Warning: Can not lock memory.\n");
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    96
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    97
		int jackError = jack_activate(jackClient);
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
    98
		if (jackError) throw JackException(L"Could not activate client.");
0
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
    99
	}
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   100
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   101
	void startRelation(const relpipe::common::type::StringX name, std::vector<relpipe::reader::handlers::AttributeMetadata> attributes) override {
3
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   102
		// TODO: validate metadata and prepare attribute mappings (names and types are important, order does not matter)
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   103
4
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   104
		currentAttributeCount = attributes.size();
0
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   105
	}
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   106
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   107
	void attribute(const relpipe::common::type::StringX& value) override {
3
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   108
		// TODO: append to current message + if this is last attribute, put whole message to the ring buffer
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   109
		// TODO: if (continueProcessing) {} ?
4
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   110
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   111
		if (currentAttributeIndex < currentAttributeCount) {
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   112
			// memcpy(currentMidiMessage.buffer, ….buffer, ….size);
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   113
			// currentMidiMessage.size = …;
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   114
			// currentMidiMessage.time = …;
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   115
			currentAttributeIndex++;
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   116
		} else {
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   117
			if (jack_ringbuffer_write_space(ringBuffer) >= sizeof (MidiMessage)) {
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   118
				jack_ringbuffer_write(ringBuffer, (const char *) &currentMidiMessage, sizeof (MidiMessage));
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   119
			} else {
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   120
				fwprintf(stderr, L"Error: ring buffer is full → skipping event.\n");
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   121
			}
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   122
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   123
			if (pthread_mutex_trylock(&messageThreadLock) == 0) {
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   124
				pthread_cond_signal(&dataReady);
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   125
				pthread_mutex_unlock(&messageThreadLock);
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   126
			}
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   127
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   128
			currentMidiMessage = MidiMessage();
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   129
			currentAttributeIndex = 0;
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   130
		}
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   131
0
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   132
	}
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   133
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   134
	void endOfPipe() {
3
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   135
		// TODO: send optional (configurable) MIDI events
4
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   136
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   137
		// Wait until the ring buffer is empty
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   138
		while (continueProcessing && jack_ringbuffer_read_space(ringBuffer)) usleep(1000);
3
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   139
	}
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   140
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   141
	int dequeueMessages(jack_nframes_t frames) {
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   142
4
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   143
		std::cout << "dequeueMessages(" << frames << ")" << std::endl; // TODO: remove debug message
3
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   144
4
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   145
		// Process messages from the ring buffer queue:
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   146
		pthread_mutex_lock(&messageThreadLock);
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   147
		while (continueProcessing) { // TODO: is continueProcessing needed?
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   148
			const size_t queuedMessages = jack_ringbuffer_read_space(ringBuffer) / sizeof (MidiMessage);
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   149
			for (size_t i = 0; i < queuedMessages; ++i) {
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   150
				MidiMessage m;
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   151
				jack_ringbuffer_read(ringBuffer, (char*) &m, sizeof (MidiMessage));
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   152
				// TODO: send events from the ring buffer to JACK + correct timing
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   153
				std::cout << "will process MidiMessage: " << &m << "" << std::endl; // TODO: remove debug message
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   154
			}
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   155
			pthread_cond_wait(&dataReady, &messageThreadLock);
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   156
		}
65dfbf0494a3 pass MIDI messages through the ring buffer (queue) from one thread to another
František Kučera <franta-hg@frantovo.cz>
parents: 3
diff changeset
   157
		pthread_mutex_unlock(&messageThreadLock);
3
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   158
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   159
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   160
		return 0;
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   161
	}
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   162
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   163
	void finish(int sig) {
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   164
		continueProcessing = false;
0
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   165
	}
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   166
1
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   167
	virtual ~JackHandler() {
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   168
		// Close JACK connection:
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   169
		jack_deactivate(jackClient);
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   170
		jack_client_close(jackClient);
3
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   171
		jack_ringbuffer_free(ringBuffer);
1
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   172
	}
7f3ab657dc50 link to the JACK library, connect to the JACK daemon
František Kučera <franta-hg@frantovo.cz>
parents: 0
diff changeset
   173
0
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   174
};
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   175
3
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   176
int dequeueMessages(jack_nframes_t frames, void* arg) {
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   177
	JackHandler* instance = (JackHandler*) arg;
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   178
	return instance->dequeueMessages(frames);
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   179
}
baa8055c5b10 ring buffer, JACK callback skeleton, signal handler
František Kučera <franta-hg@frantovo.cz>
parents: 2
diff changeset
   180
0
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   181
}
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   182
}
3bc3b33ccb02 project skeleton
František Kučera <franta-hg@frantovo.cz>
parents:
diff changeset
   183
}