Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Osc support (2nd try) #514

Draft
wants to merge 20 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 12 additions & 1 deletion common/JackAPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1094,9 +1094,20 @@ LIB_EXPORT jack_port_t* jack_port_register(jack_client_t* ext_client, const char
} else if ((port_name == NULL) || (port_type == NULL)) {
jack_error("jack_port_register called with a NULL port name or a NULL port_type");
return NULL;
}

if (strcmp(port_type, JACK_DEFAULT_AUDIO_TYPE) == 0) {
// Don't change anything
} else if (strcmp(port_type, JACK_DEFAULT_MESSAGE_TYPE) == 0) {
// Don't change anything
} else if (strcmp(port_type, JACK_DEFAULT_MIDI_TYPE) == 0) {
// Rename the old port type
port_type = JACK_DEFAULT_MESSAGE_TYPE;
} else {
return (jack_port_t *)((uintptr_t)client->PortRegister(port_name, port_type, flags, buffer_size));
jack_info("jack_port_register called with a non-default port_type: '%s'.", port_type);
}

return (jack_port_t *)((uintptr_t)client->PortRegister(port_name, port_type, flags, buffer_size));
}

LIB_EXPORT int jack_port_unregister(jack_client_t* ext_client, jack_port_t* port)
Expand Down
160 changes: 160 additions & 0 deletions common/JackEventAPI.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*
Copyright (C) 2007 Dmitry Baikov
Original JACK MIDI implementation Copyright (C) 2004 Ian Esten

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

*/

#include "JackError.h"
#include "JackEventPort.h"
#include <errno.h>
#include <string.h>

#ifdef __cplusplus
extern "C"
{
#endif

LIB_EXPORT uint32_t jack_event_get_count(void* port_buffer);

LIB_EXPORT int jack_event_get(jack_event_t* event,
piegamesde marked this conversation as resolved.
Show resolved Hide resolved
void* port_buffer, uint32_t event_index);

LIB_EXPORT void jack_event_clear_buffer(void* port_buffer);

LIB_EXPORT void jack_event_reset_buffer(void* port_buffer);

LIB_EXPORT size_t jack_event_max_size(void* port_buffer);

LIB_EXPORT jack_event_data_t* jack_event_reserve(void* port_buffer,
jack_nframes_t time, size_t data_size);

LIB_EXPORT int jack_event_write(void* port_buffer,
jack_nframes_t time, const jack_event_data_t* data, size_t data_size);

LIB_EXPORT jack_nframes_t jack_event_get_lost_count(void* port_buffer);

#ifdef __cplusplus
}
#endif

using namespace Jack;

LIB_EXPORT
uint32_t jack_event_get_count(void* port_buffer)
{
JackEventBuffer *buf = (JackEventBuffer*)port_buffer;
if (!buf || !buf->IsValid()) {
return 0;
}
return buf->event_count;
}

LIB_EXPORT
int jack_event_get(jack_event_t *event, void* port_buffer, uint32_t event_index)
{
JackEventBuffer *buf = (JackEventBuffer*)port_buffer;
if (!buf || !buf->IsValid()) {
return -EINVAL;
}
if (event_index >= buf->event_count) {
return -ENOBUFS;
}
JackEvent* ev = &buf->events[event_index];
event->time = ev->time;
event->size = ev->size;
event->buffer = ev->GetData(buf);
return 0;
}

LIB_EXPORT
void jack_event_clear_buffer(void* port_buffer)
{
JackEventBuffer *buf = (JackEventBuffer*)port_buffer;
if (buf && buf->IsValid()) {
buf->Reset(buf->nframes);
}
}

LIB_EXPORT
void jack_event_reset_buffer(void* port_buffer)
{
EventBufferInit(port_buffer, BUFFER_SIZE_MAX, BUFFER_SIZE_MAX);
}

LIB_EXPORT
size_t jack_event_max_size(void* port_buffer)
{
JackEventBuffer *buf = (JackEventBuffer*)port_buffer;
if (buf && buf->IsValid()) {
return buf->MaxEventSize();
}
return 0;
}

LIB_EXPORT
jack_event_data_t* jack_event_reserve(void* port_buffer, jack_nframes_t time, size_t data_size)
{
JackEventBuffer *buf = (JackEventBuffer*)port_buffer;
if (! buf) {
jack_error("jack_event_reserve: port buffer is set to NULL");
return 0;
}
if (! buf->IsValid()) {
jack_error("jack_event_reserve: port buffer is invalid");
return 0;
}
if (time >= buf->nframes) {
jack_error("jack_event_reserve: time parameter is out of range "
"(%lu >= %lu)", time, buf->nframes);
return 0;
}
if (buf->event_count && (buf->events[buf->event_count - 1].time > time)) {
jack_error("jack_event_reserve: time parameter is earlier than "
"last reserved event");
return 0;
}
return buf->ReserveEvent(time, data_size);
}

LIB_EXPORT
int jack_event_write(void* port_buffer,
jack_nframes_t time, const jack_event_data_t* data, size_t data_size)
{
JackEventBuffer *buf = (JackEventBuffer*)port_buffer;
if (!buf || !buf->IsValid()) {
return -EINVAL;
}
if (time >= buf->nframes || (buf->event_count && buf->events[buf->event_count - 1].time > time)) {
return -EINVAL;
}
jack_event_data_t* dest = buf->ReserveEvent(time, data_size);
if (!dest) {
return -ENOBUFS;
}
memcpy(dest, data, data_size);
return 0;
}

LIB_EXPORT
uint32_t jack_event_get_lost_count(void* port_buffer)
{
JackEventBuffer *buf = (JackEventBuffer*)port_buffer;
if (buf && buf->IsValid()) {
return buf->lost_events;
}
return 0;
}
32 changes: 16 additions & 16 deletions common/JackMidiAsyncQueue.cpp → common/JackEventAsyncQueue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

#include <new>

#include "JackMidiAsyncQueue.h"
#include "JackEventAsyncQueue.h"

using Jack::JackMidiAsyncQueue;
using Jack::JackEventAsyncQueue;

JackMidiAsyncQueue::JackMidiAsyncQueue(size_t max_bytes, size_t max_messages)
JackEventAsyncQueue::JackEventAsyncQueue(size_t max_bytes, size_t max_messages)
{
data_buffer = new jack_midi_data_t[max_bytes];
byte_ring = jack_ringbuffer_create((max_bytes * sizeof(jack_midi_data_t)) +
data_buffer = new jack_event_data_t[max_bytes];
byte_ring = jack_ringbuffer_create((max_bytes * sizeof(jack_event_data_t)) +
1);
if (byte_ring) {
info_ring = jack_ringbuffer_create((max_messages * INFO_SIZE) + 1);
Expand All @@ -42,17 +42,17 @@ JackMidiAsyncQueue::JackMidiAsyncQueue(size_t max_bytes, size_t max_messages)
throw std::bad_alloc();
}

JackMidiAsyncQueue::~JackMidiAsyncQueue()
JackEventAsyncQueue::~JackEventAsyncQueue()
{
jack_ringbuffer_free(byte_ring);
jack_ringbuffer_free(info_ring);
delete[] data_buffer;
}

jack_midi_event_t *
JackMidiAsyncQueue::DequeueEvent()
jack_event_t *
JackEventAsyncQueue::DequeueEvent()
{
jack_midi_event_t *event = 0;
jack_event_t *event = 0;
if (jack_ringbuffer_read_space(info_ring) >= INFO_SIZE) {
size_t size;
event = &dequeue_event;
Expand All @@ -61,35 +61,35 @@ JackMidiAsyncQueue::DequeueEvent()
jack_ringbuffer_read(info_ring, (char *) &size,
sizeof(size_t));
jack_ringbuffer_read(byte_ring, (char *) data_buffer,
size * sizeof(jack_midi_data_t));
size * sizeof(jack_event_data_t));
event->buffer = data_buffer;
event->size = size;
}
return event;
}

Jack::JackMidiWriteQueue::EnqueueResult
JackMidiAsyncQueue::EnqueueEvent(jack_nframes_t time, size_t size,
jack_midi_data_t *buffer)
Jack::JackEventWriteQueue::EnqueueResult
JackEventAsyncQueue::EnqueueEvent(jack_nframes_t time, size_t size,
jack_event_data_t *buffer)
{
if (size > max_bytes) {
return BUFFER_TOO_SMALL;
}
if (! ((jack_ringbuffer_write_space(info_ring) >= INFO_SIZE) &&
(jack_ringbuffer_write_space(byte_ring) >=
(size * sizeof(jack_midi_data_t))))) {
(size * sizeof(jack_event_data_t))))) {
return BUFFER_FULL;
}
jack_ringbuffer_write(byte_ring, (const char *) buffer,
size * sizeof(jack_midi_data_t));
size * sizeof(jack_event_data_t));
jack_ringbuffer_write(info_ring, (const char *) (&time),
sizeof(jack_nframes_t));
jack_ringbuffer_write(info_ring, (const char *) (&size), sizeof(size_t));
return OK;
}

size_t
JackMidiAsyncQueue::GetAvailableSpace()
JackEventAsyncQueue::GetAvailableSpace()
{
return jack_ringbuffer_write_space(info_ring) < INFO_SIZE ? 0 :
max_bytes - jack_ringbuffer_read_space(byte_ring);
Expand Down
46 changes: 23 additions & 23 deletions common/JackMidiAsyncQueue.h → common/JackEventAsyncQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,72 +17,72 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

*/

#ifndef __JackMidiAsyncQueue__
#define __JackMidiAsyncQueue__
#ifndef __JackEventAsyncQueue__
#define __JackEventAsyncQueue__

#include "JackMidiPort.h"
#include "JackMidiReadQueue.h"
#include "JackMidiWriteQueue.h"
#include "JackEventPort.h"
#include "JackEventReadQueue.h"
#include "JackEventWriteQueue.h"
#include "ringbuffer.h"

namespace Jack {

/**
* This is a MIDI message queue designed to allow one thread to pass MIDI
* This is a event message queue designed to allow one thread to pass event
* messages to another thread (though it can also be used to buffer events
* internally). This is especially useful if the MIDI API you're
* internally). This is especially useful if the event API you're
* attempting to interface with doesn't provide the ability to schedule
* MIDI events ahead of time and/or has blocking send/receive calls, as it
* events ahead of time and/or has blocking send/receive calls, as it
* allows a separate thread to handle input/output while the JACK process
* thread copies events from a MIDI buffer to this queue, or vice versa.
* thread copies events from a buffer to this queue, or vice versa.
*/

class SERVER_EXPORT JackMidiAsyncQueue:
public JackMidiReadQueue, public JackMidiWriteQueue {
class SERVER_EXPORT JackEventAsyncQueue:
public JackEventReadQueue, public JackEventWriteQueue {

private:

static const size_t INFO_SIZE =
sizeof(jack_nframes_t) + sizeof(size_t);

jack_ringbuffer_t *byte_ring;
jack_midi_data_t *data_buffer;
jack_midi_event_t dequeue_event;
jack_event_data_t *data_buffer;
jack_event_t dequeue_event;
jack_ringbuffer_t *info_ring;
size_t max_bytes;

public:

using JackMidiWriteQueue::EnqueueEvent;
using JackEventWriteQueue::EnqueueEvent;

/**
* Creates a new asynchronous MIDI message queue. The queue can store
* up to `max_messages` MIDI messages and up to `max_bytes` of MIDI
* Creates a new asynchronous event message queue. The queue can store
* up to `max_messages` messages and up to `max_bytes` of
* data before it starts rejecting messages.
*/

JackMidiAsyncQueue(size_t max_bytes=4096, size_t max_messages=1024);
JackEventAsyncQueue(size_t max_bytes=4096, size_t max_messages=1024);

virtual
~JackMidiAsyncQueue();
~JackEventAsyncQueue();

/**
* Dequeues and returns a MIDI event. Returns '0' if there are no MIDI
* events available. This method may be overridden.
* Dequeues and returns an event. Returns '0' if there are none
* available. This method may be overridden.
*/

virtual jack_midi_event_t *
virtual jack_event_t *
DequeueEvent();

/**
* Enqueues the MIDI event specified by the arguments. The return
* Enqueues the event specified by the arguments. The return
* value indicates whether or not the event was successfully enqueued.
* This method may be overridden.
*/

virtual EnqueueResult
EnqueueEvent(jack_nframes_t time, size_t size,
jack_midi_data_t *buffer);
jack_event_data_t *buffer);

/**
* Returns the maximum size event that can be enqueued right *now*.
Expand Down