127 lines
4.2 KiB
C++
127 lines
4.2 KiB
C++
/*
|
|
Copyright (C) 2011 Devin Anderson
|
|
Copyright (c) 2023 Nedko Arnaudov
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 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 General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*/
|
|
|
|
#include <cassert>
|
|
#include <memory>
|
|
|
|
#include "JackALSARawMidiInputPort.h"
|
|
#include "JackMidiUtil.h"
|
|
#include "JackError.h"
|
|
|
|
using Jack::JackALSARawMidiInputPort;
|
|
|
|
JackALSARawMidiInputPort::JackALSARawMidiInputPort(const char* client_name,
|
|
const char * cardname,
|
|
snd_rawmidi_info_t *info,
|
|
size_t index,
|
|
size_t max_bytes,
|
|
size_t max_messages):
|
|
JackALSARawMidiPort(client_name, cardname, info, index, POLLIN)
|
|
{
|
|
alsa_event = 0;
|
|
jack_event = 0;
|
|
receive_queue = new JackALSARawMidiReceiveQueue(rawmidi, max_bytes);
|
|
std::unique_ptr<JackALSARawMidiReceiveQueue> receive_ptr(receive_queue);
|
|
thread_queue = new JackMidiAsyncQueue(max_bytes, max_messages);
|
|
std::unique_ptr<JackMidiAsyncQueue> thread_ptr(thread_queue);
|
|
write_queue = new JackMidiBufferWriteQueue();
|
|
std::unique_ptr<JackMidiBufferWriteQueue> write_ptr(write_queue);
|
|
raw_queue = new JackMidiRawInputWriteQueue(thread_queue, max_bytes,
|
|
max_messages);
|
|
write_ptr.release();
|
|
thread_ptr.release();
|
|
receive_ptr.release();
|
|
}
|
|
|
|
JackALSARawMidiInputPort::~JackALSARawMidiInputPort()
|
|
{
|
|
delete raw_queue;
|
|
delete receive_queue;
|
|
delete thread_queue;
|
|
delete write_queue;
|
|
}
|
|
|
|
bool
|
|
JackALSARawMidiInputPort::ProcessJack(JackMidiBuffer *port_buffer,
|
|
jack_nframes_t frames)
|
|
{
|
|
write_queue->ResetMidiBuffer(port_buffer, frames);
|
|
bool dequeued = false;
|
|
if (! jack_event) {
|
|
goto dequeue_event;
|
|
}
|
|
for (;;) {
|
|
switch (write_queue->EnqueueEvent(jack_event, frames)) {
|
|
case JackMidiWriteQueue::BUFFER_TOO_SMALL:
|
|
jack_error("JackALSARawMidiInputPort::ProcessJack - The write "
|
|
"queue couldn't enqueue a %d-byte event. Dropping "
|
|
"event.", jack_event->size);
|
|
// Fallthrough on purpose.
|
|
case JackMidiWriteQueue::OK:
|
|
break;
|
|
default:
|
|
goto trigger_queue_event;
|
|
}
|
|
dequeue_event:
|
|
jack_event = thread_queue->DequeueEvent();
|
|
if (! jack_event) {
|
|
break;
|
|
}
|
|
dequeued = true;
|
|
}
|
|
trigger_queue_event:
|
|
return dequeued ? TriggerQueueEvent() : true;
|
|
}
|
|
|
|
bool
|
|
JackALSARawMidiInputPort::ProcessPollEvents(jack_nframes_t current_frame)
|
|
{
|
|
if (GetQueuePollEvent() == -1) {
|
|
return false;
|
|
}
|
|
int io_event = GetIOPollEvent();
|
|
switch (io_event) {
|
|
case -1:
|
|
return false;
|
|
case 1:
|
|
alsa_event = receive_queue->DequeueEvent();
|
|
}
|
|
if (alsa_event) {
|
|
size_t size = alsa_event->size;
|
|
size_t space = raw_queue->GetAvailableSpace();
|
|
bool enough_room = space >= size;
|
|
if (enough_room) {
|
|
assert(raw_queue->EnqueueEvent(current_frame, size,
|
|
alsa_event->buffer) ==
|
|
JackMidiWriteQueue::OK);
|
|
alsa_event = 0;
|
|
} else if (space) {
|
|
assert(raw_queue->EnqueueEvent(current_frame, space,
|
|
alsa_event->buffer) ==
|
|
JackMidiWriteQueue::OK);
|
|
alsa_event->buffer += space;
|
|
alsa_event->size -= space;
|
|
}
|
|
SetIOEventsEnabled(enough_room);
|
|
}
|
|
raw_queue->Process();
|
|
return true;
|
|
}
|