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)
62 Port::Port (const XMLNode
& node
, jack_client_t
* jack_client
)
63 : _currently_in_cycle (false)
64 , _nframes_this_cycle (0)
65 , _jack_client (jack_client
)
67 , _last_read_index (0)
74 Descriptor
desc (node
);
76 init (desc
.tag
, desc
.flags
);
82 Port::init (string
const & name
, Flags flags
)
84 _ok
= false; /* derived class must set to true if constructor
93 _parser
= new Parser (*this);
95 for (int i
= 0; i
< 16; i
++) {
96 _channel
[i
] = new Channel (i
, *this);
97 _channel
[i
]->connect_signals ();
100 if (!create_port ()) {
104 MakeConnections
.connect_same_thread (connect_connection
, boost::bind (&Port::make_connections
, this));
105 JackHalted
.connect_same_thread (halt_connection
, boost::bind (&Port::jack_halted
, this));
111 for (int i
= 0; i
< 16; i
++) {
116 if (_jack_client
&& _jack_port
) {
117 jack_port_unregister (_jack_client
, _jack_port
);
124 Port::parse (framecnt_t timestamp
)
128 /* NOTE: parsing is done (if at all) by initiating a read from
129 the port. Each port implementation calls on the parser
130 once it has data ready.
133 _parser
->set_timestamp (timestamp
);
137 // cerr << "+++ READ ON " << name() << endl;
139 int nread
= read (buf
, sizeof (buf
));
141 // cerr << "-- READ (" << nread << " ON " << name() << endl;
144 if ((size_t) nread
< sizeof (buf
)) {
149 } else if (nread
== 0) {
151 } else if (errno
== EAGAIN
) {
154 fatal
<< "Error reading from MIDI port " << name() << endmsg
;
160 /** Send a clock tick message.
161 * \return true on success.
164 Port::clock (timestamp_t timestamp
)
166 static byte clockmsg
= 0xf8;
168 if (sends_output()) {
169 return midimsg (&clockmsg
, 1, timestamp
);
176 Port::cycle_start (pframes_t nframes
)
180 _currently_in_cycle
= true;
181 _nframes_this_cycle
= nframes
;
183 assert(_nframes_this_cycle
== nframes
);
184 _last_read_index
= 0;
185 _last_write_timestamp
= 0;
187 if (sends_output()) {
188 void *buffer
= jack_port_get_buffer (_jack_port
, nframes
);
189 jack_midi_clear_buffer (buffer
);
193 if (receives_input()) {
194 void* jack_buffer
= jack_port_get_buffer(_jack_port
, nframes
);
195 const pframes_t event_count
= jack_midi_get_event_count(jack_buffer
);
197 jack_midi_event_t ev
;
198 timestamp_t cycle_start_frame
= jack_last_frame_time (_jack_client
);
200 for (pframes_t i
= 0; i
< event_count
; ++i
) {
201 jack_midi_event_get (&ev
, jack_buffer
, i
);
202 input_fifo
.write (cycle_start_frame
+ ev
.time
, (Evoral::EventType
) 0, ev
.size
, ev
.buffer
);
214 if (sends_output()) {
215 flush (jack_port_get_buffer (_jack_port
, _nframes_this_cycle
));
218 _currently_in_cycle
= false;
219 _nframes_this_cycle
= 0;
222 std::ostream
& MIDI::operator << ( std::ostream
& os
, const MIDI::Port
& port
)
225 os
<< "MIDI::Port { ";
226 os
<< "name: " << port
.name();
228 os
<< "ok: " << port
.ok();
234 Port::Descriptor::Descriptor (const XMLNode
& node
)
236 const XMLProperty
*prop
;
237 bool have_tag
= false;
238 bool have_mode
= false;
240 if ((prop
= node
.property ("tag")) != 0) {
245 if ((prop
= node
.property ("mode")) != 0) {
247 if (strings_equal_ignore_case (prop
->value(), "output") || strings_equal_ignore_case (prop
->value(), "out")) {
249 } else if (strings_equal_ignore_case (prop
->value(), "input") || strings_equal_ignore_case (prop
->value(), "in")) {
256 if (!have_tag
|| !have_mode
) {
257 throw failed_constructor();
269 Port::write(byte
* msg
, size_t msglen
, timestamp_t timestamp
)
273 if (!sends_output()) {
277 if (!is_process_thread()) {
279 Glib::Mutex::Lock
lm (output_fifo_lock
);
280 RingBuffer
< Evoral::Event
<double> >::rw_vector vec
= { { 0, 0 }, { 0, 0} };
282 output_fifo
.get_write_vector (&vec
);
284 if (vec
.len
[0] + vec
.len
[1] < 1) {
285 error
<< "no space in FIFO for non-process thread MIDI write" << endmsg
;
290 if (!vec
.buf
[0]->owns_buffer()) {
291 vec
.buf
[0]->set_buffer (0, 0, true);
293 vec
.buf
[0]->set (msg
, msglen
, timestamp
);
295 if (!vec
.buf
[1]->owns_buffer()) {
296 vec
.buf
[1]->set_buffer (0, 0, true);
298 vec
.buf
[1]->set (msg
, msglen
, timestamp
);
301 output_fifo
.increment_write_idx (1);
307 // XXX This had to be temporarily commented out to make export work again
308 if (!(timestamp
< _nframes_this_cycle
)) {
309 std::cerr
<< "assertion timestamp < _nframes_this_cycle failed!" << std::endl
;
312 if (_currently_in_cycle
) {
313 if (timestamp
== 0) {
314 timestamp
= _last_write_timestamp
;
317 if (jack_midi_event_write (jack_port_get_buffer (_jack_port
, _nframes_this_cycle
),
318 timestamp
, msg
, msglen
) == 0) {
320 _last_write_timestamp
= timestamp
;
324 cerr
<< "write of " << msglen
<< " failed, port holds "
325 << jack_midi_get_event_count (jack_port_get_buffer (_jack_port
, _nframes_this_cycle
))
329 cerr
<< "write to JACK midi port failed: not currently in a process cycle." << endl
;
333 if (ret
> 0 && _parser
) {
334 // ardour doesn't care about this and neither should your app, probably
335 // output_parser->raw_preparse (*output_parser, msg, ret);
336 for (int i
= 0; i
< ret
; i
++) {
337 _parser
->scanner (msg
[i
]);
339 // ardour doesn't care about this and neither should your app, probably
340 // output_parser->raw_postparse (*output_parser, msg, ret);
347 Port::flush (void* jack_port_buffer
)
349 RingBuffer
< Evoral::Event
<double> >::rw_vector vec
= { { 0, 0 }, { 0, 0 } };
352 output_fifo
.get_read_vector (&vec
);
354 if (vec
.len
[0] + vec
.len
[1]) {
355 // cerr << "Flush " << vec.len[0] + vec.len[1] << " events from non-process FIFO\n";
359 Evoral::Event
<double>* evp
= vec
.buf
[0];
361 for (size_t n
= 0; n
< vec
.len
[0]; ++n
, ++evp
) {
362 jack_midi_event_write (jack_port_buffer
,
363 (timestamp_t
) evp
->time(), evp
->buffer(), evp
->size());
368 Evoral::Event
<double>* evp
= vec
.buf
[1];
370 for (size_t n
= 0; n
< vec
.len
[1]; ++n
, ++evp
) {
371 jack_midi_event_write (jack_port_buffer
,
372 (timestamp_t
) evp
->time(), evp
->buffer(), evp
->size());
376 if ((written
= vec
.len
[0] + vec
.len
[1]) != 0) {
377 output_fifo
.increment_read_idx (written
);
382 Port::read (byte
*, size_t)
384 if (!receives_input()) {
389 Evoral::EventType type
;
391 byte buffer
[input_fifo
.capacity()];
393 while (input_fifo
.read (&time
, &type
, &size
, buffer
)) {
394 _parser
->set_timestamp (time
);
395 for (uint32_t i
= 0; i
< size
; ++i
) {
396 _parser
->scanner (buffer
[i
]);
406 _jack_port
= jack_port_register(_jack_client
, _tagname
.c_str(), JACK_DEFAULT_MIDI_TYPE
, _flags
, 0);
407 return _jack_port
== 0 ? -1 : 0;
411 Port::get_state () const
413 XMLNode
* root
= new XMLNode (state_node_name
);
414 root
->add_property ("tag", _tagname
);
416 if (_flags
== IsInput
) {
417 root
->add_property ("mode", "input");
419 root
->add_property ("mode", "output");
423 byte device_inquiry
[6];
425 device_inquiry
[0] = 0xf0;
426 device_inquiry
[0] = 0x7e;
427 device_inquiry
[0] = 0x7f;
428 device_inquiry
[0] = 0x06;
429 device_inquiry
[0] = 0x02;
430 device_inquiry
[0] = 0xf7;
432 write (device_inquiry
, sizeof (device_inquiry
), 0);
437 const char** jc
= jack_port_get_connections (_jack_port
);
438 string connection_string
;
440 for (int i
= 0; jc
[i
]; ++i
) {
442 connection_string
+= ',';
444 connection_string
+= jc
[i
];
449 if (!connection_string
.empty()) {
450 root
->add_property ("connections", connection_string
);
453 if (!_connections
.empty()) {
454 root
->add_property ("connections", _connections
);
462 Port::set_state (const XMLNode
& node
)
464 const XMLProperty
* prop
;
466 if ((prop
= node
.property ("tag")) == 0 || prop
->value() != _tagname
) {
470 if ((prop
= node
.property ("connections")) != 0 && _jack_port
) {
471 _connections
= prop
->value ();
476 Port::make_connections ()
478 if (!_connections
.empty()) {
479 vector
<string
> ports
;
480 split (_connections
, ports
, ',');
481 for (vector
<string
>::iterator x
= ports
.begin(); x
!= ports
.end(); ++x
) {
483 if (receives_input()) {
484 jack_connect (_jack_client
, (*x
).c_str(), jack_port_name (_jack_port
));
486 jack_connect (_jack_client
, jack_port_name (_jack_port
), (*x
).c_str());
488 /* ignore failures */
493 connect_connection
.disconnect ();
497 Port::set_process_thread (pthread_t thr
)
499 _process_thread
= thr
;
503 Port::is_process_thread()
505 return (pthread_self() == _process_thread
);
509 Port::reestablish (jack_client_t
* jack
)
512 int const r
= create_port ();
515 PBD::error
<< "could not reregister ports for " << name() << endmsg
;