Jack2  1.9.13
JackALSARawMidiInputPort.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 "JackALSARawMidiInputPort.h"
24 #include "JackMidiUtil.h"
25 #include "JackError.h"
26 
28 
29 JackALSARawMidiInputPort::JackALSARawMidiInputPort(const char* client_name,
30  snd_rawmidi_info_t *info,
31  size_t index,
32  size_t max_bytes,
33  size_t max_messages):
34  JackALSARawMidiPort(client_name, info, index, POLLIN)
35 {
36  alsa_event = 0;
37  jack_event = 0;
38  receive_queue = new JackALSARawMidiReceiveQueue(rawmidi, max_bytes);
39  std::unique_ptr<JackALSARawMidiReceiveQueue> receive_ptr(receive_queue);
40  thread_queue = new JackMidiAsyncQueue(max_bytes, max_messages);
41  std::unique_ptr<JackMidiAsyncQueue> thread_ptr(thread_queue);
42  write_queue = new JackMidiBufferWriteQueue();
43  std::unique_ptr<JackMidiBufferWriteQueue> write_ptr(write_queue);
44  raw_queue = new JackMidiRawInputWriteQueue(thread_queue, max_bytes,
45  max_messages);
46  write_ptr.release();
47  thread_ptr.release();
48  receive_ptr.release();
49 }
50 
51 JackALSARawMidiInputPort::~JackALSARawMidiInputPort()
52 {
53  delete raw_queue;
54  delete receive_queue;
55  delete thread_queue;
56  delete write_queue;
57 }
58 
59 bool
60 JackALSARawMidiInputPort::ProcessJack(JackMidiBuffer *port_buffer,
61  jack_nframes_t frames)
62 {
63  write_queue->ResetMidiBuffer(port_buffer, frames);
64  bool dequeued = false;
65  if (! jack_event) {
66  goto dequeue_event;
67  }
68  for (;;) {
69  switch (write_queue->EnqueueEvent(jack_event, frames)) {
70  case JackMidiWriteQueue::BUFFER_TOO_SMALL:
71  jack_error("JackALSARawMidiInputPort::ProcessJack - The write "
72  "queue couldn't enqueue a %d-byte event. Dropping "
73  "event.", jack_event->size);
74  // Fallthrough on purpose.
75  case JackMidiWriteQueue::OK:
76  break;
77  default:
78  goto trigger_queue_event;
79  }
80  dequeue_event:
81  jack_event = thread_queue->DequeueEvent();
82  if (! jack_event) {
83  break;
84  }
85  dequeued = true;
86  }
87  trigger_queue_event:
88  return dequeued ? TriggerQueueEvent() : true;
89 }
90 
91 bool
92 JackALSARawMidiInputPort::ProcessPollEvents(jack_nframes_t current_frame)
93 {
94  if (GetQueuePollEvent() == -1) {
95  return false;
96  }
97  int io_event = GetIOPollEvent();
98  switch (io_event) {
99  case -1:
100  return false;
101  case 1:
102  alsa_event = receive_queue->DequeueEvent();
103  }
104  if (alsa_event) {
105  size_t size = alsa_event->size;
106  size_t space = raw_queue->GetAvailableSpace();
107  bool enough_room = space >= size;
108  if (enough_room) {
109  assert(raw_queue->EnqueueEvent(current_frame, size,
110  alsa_event->buffer) ==
111  JackMidiWriteQueue::OK);
112  alsa_event = 0;
113  } else if (space) {
114  assert(raw_queue->EnqueueEvent(current_frame, space,
115  alsa_event->buffer) ==
116  JackMidiWriteQueue::OK);
117  alsa_event->buffer += space;
118  alsa_event->size -= space;
119  }
120  SetIOEventsEnabled(enough_room);
121  }
122  raw_queue->Process();
123  return true;
124 }
jack_midi_data_t * buffer
Definition: JackMidiPort.h:37
EnqueueResult EnqueueEvent(jack_nframes_t time, size_t size, jack_midi_data_t *buffer)
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:92
jack_nframes_t Process(jack_nframes_t boundary_frame=0)
EnqueueResult EnqueueEvent(jack_nframes_t time, size_t size, jack_midi_data_t *buffer)
void ResetMidiBuffer(JackMidiBuffer *buffer, jack_nframes_t frames)
virtual jack_midi_event_t * DequeueEvent()