26 #include "JackCoreMidiOutputPort.h"
27 #include "JackMidiUtil.h"
32 JackCoreMidiOutputPort::JackCoreMidiOutputPort(
double time_ratio,
35 JackCoreMidiPort(time_ratio)
37 read_queue =
new JackMidiBufferReadQueue();
38 std::auto_ptr<JackMidiBufferReadQueue> read_queue_ptr(read_queue);
39 thread_queue =
new JackMidiAsyncQueue(max_bytes, max_messages);
40 std::auto_ptr<JackMidiAsyncQueue> thread_queue_ptr(thread_queue);
41 thread =
new JackThread(
this);
42 std::auto_ptr<JackThread> thread_ptr(thread);
43 snprintf(semaphore_name,
sizeof(semaphore_name),
"coremidi_%p",
this);
44 thread_queue_semaphore = sem_open(semaphore_name, O_CREAT, 0777, 0);
45 if (thread_queue_semaphore == (sem_t *) SEM_FAILED) {
46 throw std::runtime_error(strerror(errno));
48 advance_schedule_time = 0;
50 thread_queue_ptr.release();
51 read_queue_ptr.release();
54 JackCoreMidiOutputPort::~JackCoreMidiOutputPort()
57 sem_close(thread_queue_semaphore);
58 sem_unlink(semaphore_name);
64 JackCoreMidiOutputPort::Execute()
67 MIDIPacketList *packet_list = (MIDIPacketList *) packet_buffer;
69 MIDIPacket *packet = MIDIPacketListInit(packet_list);
72 event = GetCoreMidiEvent(
true);
74 jack_midi_data_t *data =
event->buffer;
75 jack_nframes_t send_frame =
event->time;
76 jack_time_t send_time =
77 GetTimeFromFrames(send_frame) - advance_schedule_time;
78 size_t size =
event->size;
79 MIDITimeStamp timestamp = GetTimeStampFromFrames(send_frame);
80 packet = MIDIPacketListAdd(packet_list, PACKET_BUFFER_SIZE, packet,
81 timestamp, size, data);
83 while (GetMicroSeconds() < send_time) {
84 event = GetCoreMidiEvent(
false);
88 packet = MIDIPacketListAdd(packet_list,
sizeof(packet_buffer),
90 GetTimeStampFromFrames(event->time),
91 event->size, event->buffer);
96 SendPacketList(packet_list);
101 size_t bytes_sent = 0;
103 packet = MIDIPacketListInit(packet_list);
105 size_t num_bytes = 0;
106 for (; bytes_sent < size; bytes_sent += num_bytes) {
107 size_t num_bytes = size - bytes_sent;
113 if (num_bytes > 256) {
116 packet = MIDIPacketListAdd(packet_list,
117 sizeof(packet_buffer), packet,
118 timestamp, num_bytes,
124 if (! SendPacketList(packet_list)) {
129 }
while (bytes_sent < size);
137 JackCoreMidiOutputPort::GetCoreMidiEvent(
bool block)
140 if (sem_trywait(thread_queue_semaphore)) {
141 if (errno != EAGAIN) {
142 jack_error(
"JackCoreMidiOutputPort::Execute - sem_trywait: %s",
148 while (sem_wait(thread_queue_semaphore)) {
149 if (errno != EINTR) {
150 jack_error(
"JackCoreMidiOutputPort::Execute - sem_wait: %s",
160 JackCoreMidiOutputPort::GetTimeStampFromFrames(jack_nframes_t frames)
162 return GetTimeFromFrames(frames) / time_ratio;
168 set_threaded_log_function();
172 UInt64 computation = 250 * 1000;
173 UInt64 constraint = 500 * 1000;
174 thread->SetParams(period, computation, constraint);
176 if (thread->AcquireSelfRealTime()) {
177 jack_error(
"JackCoreMidiOutputPort::Init - could not acquire realtime "
178 "scheduling. Continuing anyway.");
184 JackCoreMidiOutputPort::Initialize(
const char *alias_name,
185 const char *client_name,
186 const char *driver_name,
int index,
187 MIDIEndpointRef endpoint,
188 SInt32 advance_schedule_time)
190 JackCoreMidiPort::Initialize(alias_name, client_name, driver_name, index,
192 assert(advance_schedule_time >= 0);
193 this->advance_schedule_time = advance_schedule_time;
197 JackCoreMidiOutputPort::ProcessJack(JackMidiBuffer *port_buffer,
198 jack_nframes_t frames)
204 case JackMidiWriteQueue::BUFFER_FULL:
205 jack_error(
"JackCoreMidiOutputPort::ProcessJack - The thread "
206 "queue buffer is full. Dropping event.");
208 case JackMidiWriteQueue::BUFFER_TOO_SMALL:
209 jack_error(
"JackCoreMidiOutputPort::ProcessJack - The thread "
210 "queue couldn't enqueue a %d-byte event. Dropping "
211 "event.", event->size);
214 if (sem_post(thread_queue_semaphore)) {
215 jack_error(
"JackCoreMidiOutputPort::ProcessJack - unexpected "
216 "error while posting to thread queue semaphore: %s",
224 JackCoreMidiOutputPort::Start()
226 bool result = thread->GetStatus() != JackThread::kIdle;
228 result = ! thread->StartSync();
230 jack_error(
"JackCoreMidiOutputPort::Start - failed to start MIDI "
231 "processing thread.");
238 JackCoreMidiOutputPort::Stop()
240 bool result = thread->GetStatus() == JackThread::kIdle;
242 result = ! thread->Kill();
244 jack_error(
"JackCoreMidiOutputPort::Stop - failed to stop MIDI "
245 "processing thread.");