26 #include "JackCoreMidiOutputPort.h"
27 #include "JackMidiUtil.h"
29 #include "JackError.h"
33 JackCoreMidiOutputPort::JackCoreMidiOutputPort(
double time_ratio,
36 JackCoreMidiPort(time_ratio)
38 read_queue =
new JackMidiBufferReadQueue();
39 std::auto_ptr<JackMidiBufferReadQueue> read_queue_ptr(read_queue);
40 thread_queue =
new JackMidiAsyncQueue(max_bytes, max_messages);
41 std::auto_ptr<JackMidiAsyncQueue> thread_queue_ptr(thread_queue);
42 thread =
new JackThread(
this);
43 std::auto_ptr<JackThread> thread_ptr(thread);
44 snprintf(semaphore_name,
sizeof(semaphore_name),
"coremidi_%p",
this);
45 thread_queue_semaphore = sem_open(semaphore_name, O_CREAT, 0777, 0);
46 if (thread_queue_semaphore == (sem_t *) SEM_FAILED) {
47 throw std::runtime_error(strerror(errno));
49 advance_schedule_time = 0;
51 thread_queue_ptr.release();
52 read_queue_ptr.release();
55 JackCoreMidiOutputPort::~JackCoreMidiOutputPort()
58 sem_close(thread_queue_semaphore);
59 sem_unlink(semaphore_name);
65 JackCoreMidiOutputPort::Execute()
68 MIDIPacketList *packet_list = (MIDIPacketList *) packet_buffer;
70 MIDIPacket *packet = MIDIPacketListInit(packet_list);
73 event = GetCoreMidiEvent(
true);
75 jack_midi_data_t *data =
event->buffer;
76 jack_nframes_t send_frame =
event->time;
77 jack_time_t send_time =
78 GetTimeFromFrames(send_frame) - advance_schedule_time;
79 size_t size =
event->size;
80 MIDITimeStamp timestamp = GetTimeStampFromFrames(send_frame);
81 packet = MIDIPacketListAdd(packet_list, PACKET_BUFFER_SIZE, packet,
82 timestamp, size, data);
85 if (GetMicroSeconds() >= send_time) {
89 event = GetCoreMidiEvent(
false);
93 packet = MIDIPacketListAdd(packet_list,
sizeof(packet_buffer),
95 GetTimeStampFromFrames(event->time),
96 event->size, event->buffer);
98 SendPacketList(packet_list);
103 size_t bytes_sent = 0;
105 packet = MIDIPacketListInit(packet_list);
107 size_t num_bytes = 0;
108 for (; bytes_sent < size; bytes_sent += num_bytes) {
109 size_t num_bytes = size - bytes_sent;
115 if (num_bytes > 256) {
118 packet = MIDIPacketListAdd(packet_list,
119 sizeof(packet_buffer), packet,
120 timestamp, num_bytes,
126 if (! SendPacketList(packet_list)) {
131 }
while (bytes_sent < size);
139 JackCoreMidiOutputPort::GetCoreMidiEvent(
bool block)
142 if (sem_trywait(thread_queue_semaphore)) {
143 if (errno != EAGAIN) {
144 jack_error(
"JackCoreMidiOutputPort::Execute - sem_trywait: %s",
150 while (sem_wait(thread_queue_semaphore)) {
151 if (errno != EINTR) {
152 jack_error(
"JackCoreMidiOutputPort::Execute - sem_wait: %s",
162 JackCoreMidiOutputPort::GetTimeStampFromFrames(jack_nframes_t frames)
164 return GetTimeFromFrames(frames) / time_ratio;
170 set_threaded_log_function();
174 UInt64 computation = 250 * 1000;
175 UInt64 constraint = 500 * 1000;
176 thread->SetParams(period, computation, constraint);
178 if (thread->AcquireSelfRealTime()) {
179 jack_error(
"JackCoreMidiOutputPort::Init - could not acquire realtime "
180 "scheduling. Continuing anyway.");
186 JackCoreMidiOutputPort::Initialize(
const char *alias_name,
187 const char *client_name,
188 const char *driver_name,
int index,
189 MIDIEndpointRef endpoint,
190 SInt32 advance_schedule_time)
192 JackCoreMidiPort::Initialize(alias_name, client_name, driver_name, index,
194 assert(advance_schedule_time >= 0);
195 this->advance_schedule_time = advance_schedule_time;
199 JackCoreMidiOutputPort::ProcessJack(JackMidiBuffer *port_buffer,
200 jack_nframes_t frames)
206 case JackMidiWriteQueue::BUFFER_FULL:
207 jack_error(
"JackCoreMidiOutputPort::ProcessJack - The thread "
208 "queue buffer is full. Dropping event.");
210 case JackMidiWriteQueue::BUFFER_TOO_SMALL:
211 jack_error(
"JackCoreMidiOutputPort::ProcessJack - The thread "
212 "queue couldn't enqueue a %d-byte event. Dropping "
213 "event.", event->size);
216 if (sem_post(thread_queue_semaphore)) {
217 jack_error(
"JackCoreMidiOutputPort::ProcessJack - unexpected "
218 "error while posting to thread queue semaphore: %s",
226 JackCoreMidiOutputPort::Start()
228 bool result = thread->GetStatus() != JackThread::kIdle;
230 result = ! thread->StartSync();
232 jack_error(
"JackCoreMidiOutputPort::Start - failed to start MIDI "
233 "processing thread.");
240 JackCoreMidiOutputPort::Stop()
242 bool result = thread->GetStatus() == JackThread::kIdle;
244 result = ! thread->Kill();
246 jack_error(
"JackCoreMidiOutputPort::Stop - failed to stop MIDI "
247 "processing thread.");
jack_midi_event_t * DequeueEvent()
void ResetMidiBuffer(JackMidiBuffer *buffer)
SERVER_EXPORT void jack_error(const char *fmt,...)
virtual jack_midi_event_t * DequeueEvent()
virtual EnqueueResult EnqueueEvent(jack_nframes_t time, size_t size, jack_midi_data_t *buffer)