Jack2 1.9.12

JackALSARawMidiOutputPort.cpp
1 /*
2 Copyright (C) 2011 Devin Anderson
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <cassert>
21 #include <memory>
22
23 #include "JackALSARawMidiOutputPort.h"
24 #include "JackError.h"
25
26 using Jack::JackALSARawMidiOutputPort;
27
28 JackALSARawMidiOutputPort::JackALSARawMidiOutputPort(snd_rawmidi_info_t *info,
29 size_t index,
30 size_t max_bytes_per_poll,
31 size_t max_bytes,
32 size_t max_messages):
33 JackALSARawMidiPort(info, index, POLLOUT)
34 {
35 alsa_event = 0;
36 read_queue = new JackMidiBufferReadQueue();
37 std::auto_ptr<JackMidiBufferReadQueue> read_ptr(read_queue);
38 send_queue = new JackALSARawMidiSendQueue(rawmidi, max_bytes_per_poll);
39 std::auto_ptr<JackALSARawMidiSendQueue> send_ptr(send_queue);
40 thread_queue = new JackMidiAsyncQueue(max_bytes, max_messages);
41 std::auto_ptr<JackMidiAsyncQueue> thread_ptr(thread_queue);
42 raw_queue = new JackMidiRawOutputWriteQueue(send_queue, max_bytes,
43 max_messages, max_messages);
44 thread_ptr.release();
45 send_ptr.release();
46 read_ptr.release();
47 }
48
49 JackALSARawMidiOutputPort::~JackALSARawMidiOutputPort()
50 {
51 delete raw_queue;
52 delete read_queue;
53 delete send_queue;
54 delete thread_queue;
55 }
56
57 bool
58 JackALSARawMidiOutputPort::ProcessJack(JackMidiBuffer *port_buffer,
59 jack_nframes_t frames)
60 {
61 read_queue->ResetMidiBuffer(port_buffer);
62 bool enqueued = false;
63 for (jack_midi_event_t *event = read_queue->DequeueEvent(); event;
64 event = read_queue->DequeueEvent()) {
65 switch (thread_queue->EnqueueEvent(event, frames)) {
66 case JackMidiWriteQueue::BUFFER_FULL:
67 jack_error("JackALSARawMidiOutputPort::ProcessJack - The thread "
68 "queue doesn't have enough room to enqueue a %d-byte "
69 "event. Dropping event.", event->size);
70 continue;
71 case JackMidiWriteQueue::BUFFER_TOO_SMALL:
72 jack_error("JackALSARawMidiOutputPort::ProcessJack - The thread "
73 "queue is too small to enqueue a %d-byte event. "
74 "Dropping event.", event->size);
75 continue;
76 default:
77 enqueued = true;
78 }
79 }
80 return enqueued ? TriggerQueueEvent() : true;
81 }
82
83 bool
84 JackALSARawMidiOutputPort::ProcessPollEvents(bool handle_output, bool timeout,
85 jack_nframes_t *frame)
86 {
87 int io_event;
88 int queue_event;
89 send_queue->ResetPollByteCount();
90 if (! handle_output) {
91 assert(timeout);
92 goto process_raw_queue;
93 }
94 io_event = GetIOPollEvent();
95 if (io_event == -1) {
96 return false;
97 }
98 queue_event = GetQueuePollEvent();
99 if (queue_event == -1) {
100 return false;
101 }
102 if (io_event || timeout) {
103 process_raw_queue:
104 // We call the 'Process' event early because there are events waiting
105 // to be processed that either need to be sent now, or before now.
106 raw_queue->Process();
107 } else if (! queue_event) {
108 return true;
109 }
110 if (! alsa_event) {
111 alsa_event = thread_queue->DequeueEvent();
112 }
113 for (; alsa_event; alsa_event = thread_queue->DequeueEvent()) {
114 switch (raw_queue->EnqueueEvent(alsa_event)) {
115 case JackMidiWriteQueue::BUFFER_TOO_SMALL:
116 jack_error("JackALSARawMidiOutputPort::ProcessQueues - The raw "
117 "output queue couldn't enqueue a %d-byte event. "
118 "Dropping event.", alsa_event->size);
119 // Fallthrough on purpose.
120 case JackMidiWriteQueue::OK:
121 continue;
122 default:
123 ;
124 }
125
126 // Try to free up some space by processing events early.
127 *frame = raw_queue->Process();
128
129 switch (raw_queue->EnqueueEvent(alsa_event)) {
130 case JackMidiWriteQueue::BUFFER_FULL:
131 goto set_io_events;
132 case JackMidiWriteQueue::BUFFER_TOO_SMALL:
133 // This shouldn't happen.
134 assert(false);
135 default:
136 ;
137 }
138 }
139 *frame = raw_queue->Process();
140 set_io_events:
141 bool blocked = send_queue->IsBlocked();
142 SetIOEventsEnabled(blocked);
143 if (blocked) {
144 *frame = 0;
145 }
146 return true;
147 }
Jack::JackMidiBufferReadQueue::DequeueEvent
jack_midi_event_t * DequeueEvent()
Definition: JackMidiBufferReadQueue.cpp:33
Jack::JackMidiBufferReadQueue::ResetMidiBuffer
void ResetMidiBuffer(JackMidiBuffer *buffer)
Definition: JackMidiBufferReadQueue.cpp:48
jack_error
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:92
jack_midi_event_t::size
size_t size
Definition: JackMidiPort.h:36
jack_midi_event_t
Definition: JackMidiPort.h:33
Jack::JackMidiRawOutputWriteQueue::EnqueueEvent
EnqueueResult EnqueueEvent(jack_nframes_t time, size_t size, jack_midi_data_t *buffer)
Definition: JackMidiRawOutputWriteQueue.cpp:73
Jack::JackMidiRawOutputWriteQueue::Process
jack_nframes_t Process(jack_nframes_t boundary_frame=0)
Definition: JackMidiRawOutputWriteQueue.cpp:92
Jack::JackMidiAsyncQueue::DequeueEvent
virtual jack_midi_event_t * DequeueEvent()
Definition: JackMidiAsyncQueue.cpp:53
Jack::JackALSARawMidiOutputPort
Definition: JackALSARawMidiOutputPort.h:31
Jack::JackMidiAsyncQueue::EnqueueEvent
virtual EnqueueResult EnqueueEvent(jack_nframes_t time, size_t size, jack_midi_data_t *buffer)
Definition: JackMidiAsyncQueue.cpp:72