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