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