2 Copyright (C) 1998 Paul Barton-Davis
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.
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.
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.
25 #include <jack/jack.h>
26 #include <jack/midiport.h>
28 #include "pbd/xml++.h"
29 #include "pbd/error.h"
30 #include "pbd/failed_constructor.h"
31 #include "pbd/convert.h"
32 #include "pbd/strsplit.h"
34 #include "midi++/types.h"
35 #include "midi++/port.h"
36 #include "midi++/channel.h"
42 pthread_t
Port::_process_thread
;
43 Signal0
<void> Port::JackHalted
;
44 Signal0
<void> Port::MakeConnections
;
45 string
Port::state_node_name
= "MIDI-port";
47 Port::Port (string
const & name
, Flags flags
, jack_client_t
* jack_client
)
48 : _currently_in_cycle (false)
49 , _nframes_this_cycle (0)
50 , _jack_client (jack_client
)
52 , _last_read_index (0)
61 Port::Port (const XMLNode
& node
, jack_client_t
* jack_client
)
62 : _currently_in_cycle (false)
63 , _nframes_this_cycle (0)
64 , _jack_client (jack_client
)
66 , _last_read_index (0)
72 Descriptor
desc (node
);
74 init (desc
.tag
, desc
.flags
);
80 Port::init (string
const & name
, Flags flags
)
82 _ok
= false; /* derived class must set to true if constructor
91 _parser
= new Parser (*this);
93 for (int i
= 0; i
< 16; i
++) {
94 _channel
[i
] = new Channel (i
, *this);
95 _channel
[i
]->connect_signals ();
98 if (!create_port ()) {
102 MakeConnections
.connect_same_thread (connect_connection
, boost::bind (&Port::make_connections
, this));
103 JackHalted
.connect_same_thread (halt_connection
, boost::bind (&Port::jack_halted
, this));
109 for (int i
= 0; i
< 16; i
++) {
114 if (_jack_client
&& _jack_port
) {
115 jack_port_unregister (_jack_client
, _jack_port
);
122 Port::parse (nframes_t timestamp
)
126 /* NOTE: parsing is done (if at all) by initiating a read from
127 the port. Each port implementation calls on the parser
128 once it has data ready.
131 _parser
->set_timestamp (timestamp
);
135 // cerr << "+++ READ ON " << name() << endl;
137 int nread
= read (buf
, sizeof (buf
));
139 // cerr << "-- READ (" << nread << " ON " << name() << endl;
142 if ((size_t) nread
< sizeof (buf
)) {
147 } else if (nread
== 0) {
149 } else if (errno
== EAGAIN
) {
152 fatal
<< "Error reading from MIDI port " << name() << endmsg
;
158 /** Send a clock tick message.
159 * \return true on success.
162 Port::clock (timestamp_t timestamp
)
164 static byte clockmsg
= 0xf8;
166 if (sends_output()) {
167 return midimsg (&clockmsg
, 1, timestamp
);
174 Port::cycle_start (nframes_t nframes
)
178 _currently_in_cycle
= true;
179 _nframes_this_cycle
= nframes
;
181 assert(_nframes_this_cycle
== nframes
);
182 _last_read_index
= 0;
183 _last_write_timestamp
= 0;
185 if (sends_output()) {
186 void *buffer
= jack_port_get_buffer (_jack_port
, nframes
);
187 jack_midi_clear_buffer (buffer
);
191 if (receives_input()) {
192 void* jack_buffer
= jack_port_get_buffer(_jack_port
, nframes
);
193 const nframes_t event_count
= jack_midi_get_event_count(jack_buffer
);
195 jack_midi_event_t ev
;
196 timestamp_t cycle_start_frame
= jack_last_frame_time (_jack_client
);
198 for (nframes_t i
= 0; i
< event_count
; ++i
) {
199 jack_midi_event_get (&ev
, jack_buffer
, i
);
200 input_fifo
.write (cycle_start_frame
+ ev
.time
, (Evoral::EventType
) 0, ev
.size
, ev
.buffer
);
212 if (sends_output()) {
213 flush (jack_port_get_buffer (_jack_port
, _nframes_this_cycle
));
216 _currently_in_cycle
= false;
217 _nframes_this_cycle
= 0;
220 std::ostream
& MIDI::operator << ( std::ostream
& os
, const MIDI::Port
& port
)
223 os
<< "MIDI::Port { ";
224 os
<< "name: " << port
.name();
226 os
<< "ok: " << port
.ok();
232 Port::Descriptor::Descriptor (const XMLNode
& node
)
234 const XMLProperty
*prop
;
235 bool have_tag
= false;
236 bool have_mode
= false;
238 if ((prop
= node
.property ("tag")) != 0) {
243 if ((prop
= node
.property ("mode")) != 0) {
245 if (strings_equal_ignore_case (prop
->value(), "output") || strings_equal_ignore_case (prop
->value(), "out")) {
247 } else if (strings_equal_ignore_case (prop
->value(), "input") || strings_equal_ignore_case (prop
->value(), "in")) {
254 if (!have_tag
|| !have_mode
) {
255 throw failed_constructor();
267 Port::write(byte
* msg
, size_t msglen
, timestamp_t timestamp
)
271 if (!sends_output()) {
275 if (!is_process_thread()) {
277 Glib::Mutex::Lock
lm (output_fifo_lock
);
278 RingBuffer
< Evoral::Event
<double> >::rw_vector vec
= { { 0, 0 }, { 0, 0} };
280 output_fifo
.get_write_vector (&vec
);
282 if (vec
.len
[0] + vec
.len
[1] < 1) {
283 error
<< "no space in FIFO for non-process thread MIDI write" << endmsg
;
288 if (!vec
.buf
[0]->owns_buffer()) {
289 vec
.buf
[0]->set_buffer (0, 0, true);
291 vec
.buf
[0]->set (msg
, msglen
, timestamp
);
293 if (!vec
.buf
[1]->owns_buffer()) {
294 vec
.buf
[1]->set_buffer (0, 0, true);
296 vec
.buf
[1]->set (msg
, msglen
, timestamp
);
299 output_fifo
.increment_write_idx (1);
305 // XXX This had to be temporarily commented out to make export work again
306 if (!(timestamp
< _nframes_this_cycle
)) {
307 std::cerr
<< "assertion timestamp < _nframes_this_cycle failed!" << std::endl
;
310 if (_currently_in_cycle
) {
311 if (timestamp
== 0) {
312 timestamp
= _last_write_timestamp
;
315 if (jack_midi_event_write (jack_port_get_buffer (_jack_port
, _nframes_this_cycle
),
316 timestamp
, msg
, msglen
) == 0) {
318 _last_write_timestamp
= timestamp
;
322 cerr
<< "write of " << msglen
<< " failed, port holds "
323 << jack_midi_get_event_count (jack_port_get_buffer (_jack_port
, _nframes_this_cycle
))
327 cerr
<< "write to JACK midi port failed: not currently in a process cycle." << endl
;
331 if (ret
> 0 && _parser
) {
332 // ardour doesn't care about this and neither should your app, probably
333 // output_parser->raw_preparse (*output_parser, msg, ret);
334 for (int i
= 0; i
< ret
; i
++) {
335 _parser
->scanner (msg
[i
]);
337 // ardour doesn't care about this and neither should your app, probably
338 // output_parser->raw_postparse (*output_parser, msg, ret);
345 Port::flush (void* jack_port_buffer
)
347 RingBuffer
< Evoral::Event
<double> >::rw_vector vec
= { { 0, 0 }, { 0, 0 } };
350 output_fifo
.get_read_vector (&vec
);
352 if (vec
.len
[0] + vec
.len
[1]) {
353 // cerr << "Flush " << vec.len[0] + vec.len[1] << " events from non-process FIFO\n";
357 Evoral::Event
<double>* evp
= vec
.buf
[0];
359 for (size_t n
= 0; n
< vec
.len
[0]; ++n
, ++evp
) {
360 jack_midi_event_write (jack_port_buffer
,
361 (timestamp_t
) evp
->time(), evp
->buffer(), evp
->size());
366 Evoral::Event
<double>* evp
= vec
.buf
[1];
368 for (size_t n
= 0; n
< vec
.len
[1]; ++n
, ++evp
) {
369 jack_midi_event_write (jack_port_buffer
,
370 (timestamp_t
) evp
->time(), evp
->buffer(), evp
->size());
374 if ((written
= vec
.len
[0] + vec
.len
[1]) != 0) {
375 output_fifo
.increment_read_idx (written
);
380 Port::read (byte
*, size_t)
382 if (!receives_input()) {
387 Evoral::EventType type
;
389 byte buffer
[input_fifo
.capacity()];
391 while (input_fifo
.read (&time
, &type
, &size
, buffer
)) {
392 _parser
->set_timestamp (time
);
393 for (uint32_t i
= 0; i
< size
; ++i
) {
394 _parser
->scanner (buffer
[i
]);
404 _jack_port
= jack_port_register(_jack_client
, _tagname
.c_str(), JACK_DEFAULT_MIDI_TYPE
, _flags
, 0);
405 return _jack_port
== 0 ? -1 : 0;
409 Port::get_state () const
411 XMLNode
* root
= new XMLNode (state_node_name
);
412 root
->add_property ("tag", _tagname
);
414 if (_flags
== IsInput
) {
415 root
->add_property ("mode", "input");
417 root
->add_property ("mode", "output");
421 byte device_inquiry
[6];
423 device_inquiry
[0] = 0xf0;
424 device_inquiry
[0] = 0x7e;
425 device_inquiry
[0] = 0x7f;
426 device_inquiry
[0] = 0x06;
427 device_inquiry
[0] = 0x02;
428 device_inquiry
[0] = 0xf7;
430 write (device_inquiry
, sizeof (device_inquiry
), 0);
435 const char** jc
= jack_port_get_connections (_jack_port
);
436 string connection_string
;
438 for (int i
= 0; jc
[i
]; ++i
) {
440 connection_string
+= ',';
442 connection_string
+= jc
[i
];
447 if (!connection_string
.empty()) {
448 root
->add_property ("connections", connection_string
);
451 if (!_connections
.empty()) {
452 root
->add_property ("connections", _connections
);
460 Port::set_state (const XMLNode
& node
)
462 const XMLProperty
* prop
;
464 if ((prop
= node
.property ("tag")) == 0 || prop
->value() != _tagname
) {
468 if ((prop
= node
.property ("connections")) != 0 && _jack_port
) {
469 _connections
= prop
->value ();
474 Port::make_connections ()
476 if (!_connections
.empty()) {
477 vector
<string
> ports
;
478 split (_connections
, ports
, ',');
479 for (vector
<string
>::iterator x
= ports
.begin(); x
!= ports
.end(); ++x
) {
481 if (receives_input()) {
482 jack_connect (_jack_client
, (*x
).c_str(), jack_port_name (_jack_port
));
484 jack_connect (_jack_client
, jack_port_name (_jack_port
), (*x
).c_str());
486 /* ignore failures */
491 connect_connection
.disconnect ();
495 Port::set_process_thread (pthread_t thr
)
497 _process_thread
= thr
;
501 Port::is_process_thread()
503 return (pthread_self() == _process_thread
);
507 Port::reestablish (jack_client_t
* jack
)
510 int const r
= create_port ();
513 PBD::error
<< "could not reregister ports for " << name() << endmsg
;