457ff1c358f03827fe7cf8f5d80a9e688e618329
[ardour.git] / libs / midi++2 / port.cc
1 /*
2     Copyright (C) 1998 Paul Barton-Davis
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     $Id$
19 */
20 #include <iostream>
21 #include <cstdio>
22 #include <fcntl.h>
23 #include <errno.h>
24
25 #include <jack/jack.h>
26 #include <jack/midiport.h>
27
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"
33
34 #include "midi++/types.h"
35 #include "midi++/port.h"
36 #include "midi++/channel.h"
37
38 using namespace MIDI;
39 using namespace std;
40 using namespace PBD;
41
42 size_t Port::nports = 0;
43 pthread_t Port::_process_thread;
44 Signal0<void> Port::JackHalted;
45 Signal0<void> Port::MakeConnections;
46
47 Port::Port (const XMLNode& node, jack_client_t* jack_client)
48         : _currently_in_cycle (false)
49         , _nframes_this_cycle (0)
50         , _jack_client (jack_client)
51         , _jack_input_port (0)
52         , _jack_output_port (0)
53         , _last_read_index (0)
54         , output_fifo (512)
55         , input_fifo (1024)
56 {
57         Descriptor desc (node);
58
59         _ok = false;  /* derived class must set to true if constructor
60                          succeeds.
61                       */
62
63         input_parser = 0;
64         output_parser = 0;
65
66         _tagname = desc.tag;
67         _mode = desc.mode;
68
69         if (_mode == O_RDONLY || _mode == O_RDWR) {
70                 input_parser = new Parser (*this);
71         } else {
72                 input_parser = 0;
73         }
74
75         if (_mode == O_WRONLY || _mode == O_RDWR) {
76                 output_parser = new Parser (*this);
77         } else {
78                 output_parser = 0;
79         }
80
81         for (int i = 0; i < 16; i++) {
82                 _channel[i] =  new Channel (i, *this);
83
84                 if (input_parser) {
85                         _channel[i]->connect_input_signals ();
86                 }
87
88                 if (output_parser) {
89                         _channel[i]->connect_output_signals ();
90                 }
91         }
92
93         if (!create_ports (node)) {
94                 _ok = true;
95         }
96
97         MakeConnections.connect_same_thread (connect_connection, boost::bind (&Port::make_connections, this));
98         JackHalted.connect_same_thread (halt_connection, boost::bind (&Port::jack_halted, this));
99
100         set_state (node);
101 }
102
103
104 Port::~Port ()
105 {
106         for (int i = 0; i < 16; i++) {
107                 delete _channel[i];
108         }
109
110         if (_jack_input_port) {
111                 if (_jack_client) {
112                         jack_port_unregister (_jack_client, _jack_input_port);
113                 }
114                 _jack_input_port = 0;
115         }
116
117         if (_jack_output_port) {
118                 if (_jack_client) {
119                         jack_port_unregister (_jack_client, _jack_input_port);
120                 }
121                 _jack_input_port = 0;
122         }
123 }
124
125 void
126 Port::parse (nframes_t timestamp)
127 {
128         byte buf[512];
129
130         /* NOTE: parsing is done (if at all) by initiating a read from 
131            the port. Each port implementation calls on the parser
132            once it has data ready.
133         */
134         
135         if (input_parser) {
136                 input_parser->set_timestamp (timestamp);
137         }
138
139         while (1) {
140                 
141                 // cerr << "+++ READ ON " << name() << endl;
142
143                 int nread = read (buf, sizeof (buf));
144
145                 // cerr << "-- READ (" << nread << " ON " << name() << endl;
146                 
147                 if (nread > 0) {
148                         if ((size_t) nread < sizeof (buf)) {
149                                 break;
150                         } else {
151                                 continue;
152                         }
153                 } else if (nread == 0) {
154                         break;
155                 } else if (errno == EAGAIN) {
156                         break;
157                 } else {
158                         fatal << "Error reading from MIDI port " << name() << endmsg;
159                         /*NOTREACHED*/
160                 }
161         }
162 }
163
164 /** Send a clock tick message.
165  * \return true on success.
166  */
167 bool
168 Port::clock (timestamp_t timestamp)
169 {
170         static byte clockmsg = 0xf8;
171         
172         if (_mode != O_RDONLY) {
173                 return midimsg (&clockmsg, 1, timestamp);
174         }
175         
176         return false;
177 }
178
179 void
180 Port::cycle_start (nframes_t nframes)
181 {
182         _currently_in_cycle = true;
183         _nframes_this_cycle = nframes;
184
185         assert(_nframes_this_cycle == nframes);
186         _last_read_index = 0;
187         _last_write_timestamp = 0;
188
189         if (_jack_output_port != 0) {
190                 // output
191                 void *buffer = jack_port_get_buffer (_jack_output_port, nframes);
192                 jack_midi_clear_buffer (buffer);
193                 flush (buffer); 
194         }
195         
196         if (_jack_input_port != 0) {
197                 // input
198                 void* jack_buffer = jack_port_get_buffer(_jack_input_port, nframes);
199                 const nframes_t event_count = jack_midi_get_event_count(jack_buffer);
200
201                 jack_midi_event_t ev;
202                 timestamp_t cycle_start_frame = jack_last_frame_time (_jack_client);
203
204                 for (nframes_t i = 0; i < event_count; ++i) {
205                         jack_midi_event_get (&ev, jack_buffer, i);
206                         input_fifo.write (cycle_start_frame + ev.time, (Evoral::EventType) 0, ev.size, ev.buffer);
207                 }       
208                 
209                 if (event_count) {
210                         xthread.wakeup ();
211                 }
212         }
213 }
214
215 void
216 Port::cycle_end ()
217 {
218         if (_jack_output_port != 0) {
219                 flush (jack_port_get_buffer (_jack_output_port, _nframes_this_cycle));
220         }
221
222         _currently_in_cycle = false;
223         _nframes_this_cycle = 0;
224 }
225
226 std::ostream & MIDI::operator << ( std::ostream & os, const MIDI::Port & port )
227 {
228         using namespace std;
229         os << "MIDI::Port { ";
230         os << "name: " << port.name();
231         os << "; ";
232         os << "mode: " << port.mode();
233         os << "; ";
234         os << "ok: " << port.ok();
235         os << "; ";
236         os << " }";
237         return os;
238 }
239
240 Port::Descriptor::Descriptor (const XMLNode& node)
241 {
242         const XMLProperty *prop;
243         bool have_tag = false;
244         bool have_mode = false;
245
246         if ((prop = node.property ("tag")) != 0) {
247                 tag = prop->value();
248                 have_tag = true;
249         }
250
251         if ((prop = node.property ("mode")) != 0) {
252
253                 mode = O_RDWR;
254
255                 if (strings_equal_ignore_case (prop->value(), "output") || strings_equal_ignore_case (prop->value(), "out")) {
256                         mode = O_WRONLY;
257                 } else if (strings_equal_ignore_case (prop->value(), "input") || strings_equal_ignore_case (prop->value(), "in")) {
258                         mode = O_RDONLY;
259                 }
260
261                 have_mode = true;
262         }
263
264         if (!have_tag || !have_mode) {
265                 throw failed_constructor();
266         }
267 }
268
269 void
270 Port::jack_halted ()
271 {
272         _jack_client = 0;
273         _jack_input_port = 0;
274         _jack_output_port = 0;
275 }
276
277 int
278 Port::write(byte * msg, size_t msglen, timestamp_t timestamp)
279 {
280         int ret = 0;
281
282         if (!_jack_output_port) {
283                 return ret;
284         }
285         
286         if (!is_process_thread()) {
287
288                 Glib::Mutex::Lock lm (output_fifo_lock);
289                 RingBuffer< Evoral::Event<double> >::rw_vector vec = { { 0, 0 }, { 0, 0} };
290                 
291                 output_fifo.get_write_vector (&vec);
292
293                 if (vec.len[0] + vec.len[1] < 1) {
294                         error << "no space in FIFO for non-process thread MIDI write" << endmsg;
295                         return 0;
296                 }
297
298                 if (vec.len[0]) {
299                         if (!vec.buf[0]->owns_buffer()) {
300                                 vec.buf[0]->set_buffer (0, 0, true);
301                         }
302                         vec.buf[0]->set (msg, msglen, timestamp);
303                 } else {
304                         if (!vec.buf[1]->owns_buffer()) {
305                                 vec.buf[1]->set_buffer (0, 0, true);
306                         }
307                         vec.buf[1]->set (msg, msglen, timestamp);
308                 }
309
310                 output_fifo.increment_write_idx (1);
311                 
312                 ret = msglen;
313
314         } else {
315
316                 // XXX This had to be temporarily commented out to make export work again
317                 if (!(timestamp < _nframes_this_cycle)) {
318                         std::cerr << "assertion timestamp < _nframes_this_cycle failed!" << std::endl;
319                 }
320
321                 if (_currently_in_cycle) {
322                         if (timestamp == 0) {
323                                 timestamp = _last_write_timestamp;
324                         } 
325
326                         if (jack_midi_event_write (jack_port_get_buffer (_jack_output_port, _nframes_this_cycle), 
327                                                 timestamp, msg, msglen) == 0) {
328                                 ret = msglen;
329                                 _last_write_timestamp = timestamp;
330
331                         } else {
332                                 ret = 0;
333                                 cerr << "write of " << msglen << " failed, port holds "
334                                         << jack_midi_get_event_count (jack_port_get_buffer (_jack_output_port, _nframes_this_cycle))
335                                         << endl;
336                         }
337                 } else {
338                         cerr << "write to JACK midi port failed: not currently in a process cycle." << endl;
339                 }
340         }
341
342         if (ret > 0 && output_parser) {
343                 // ardour doesn't care about this and neither should your app, probably
344                 // output_parser->raw_preparse (*output_parser, msg, ret);
345                 for (int i = 0; i < ret; i++) {
346                         output_parser->scanner (msg[i]);
347                 }
348                 // ardour doesn't care about this and neither should your app, probably
349                 // output_parser->raw_postparse (*output_parser, msg, ret);
350         }       
351
352         return ret;
353 }
354
355 void
356 Port::flush (void* jack_port_buffer)
357 {
358         RingBuffer< Evoral::Event<double> >::rw_vector vec = { { 0, 0 }, { 0, 0 } };
359         size_t written;
360
361         output_fifo.get_read_vector (&vec);
362
363         if (vec.len[0] + vec.len[1]) {
364                 // cerr << "Flush " << vec.len[0] + vec.len[1] << " events from non-process FIFO\n";
365         }
366
367         if (vec.len[0]) {
368                 Evoral::Event<double>* evp = vec.buf[0];
369                 
370                 for (size_t n = 0; n < vec.len[0]; ++n, ++evp) {
371                         jack_midi_event_write (jack_port_buffer,
372                                                (timestamp_t) evp->time(), evp->buffer(), evp->size());
373                 }
374         }
375         
376         if (vec.len[1]) {
377                 Evoral::Event<double>* evp = vec.buf[1];
378
379                 for (size_t n = 0; n < vec.len[1]; ++n, ++evp) {
380                         jack_midi_event_write (jack_port_buffer,
381                                                (timestamp_t) evp->time(), evp->buffer(), evp->size());
382                 }
383         }
384         
385         if ((written = vec.len[0] + vec.len[1]) != 0) {
386                 output_fifo.increment_read_idx (written);
387         }
388 }
389
390 int
391 Port::read (byte *, size_t)
392 {
393         timestamp_t time;
394         Evoral::EventType type;
395         uint32_t size;
396         byte buffer[input_fifo.capacity()];
397
398         while (input_fifo.read (&time, &type, &size, buffer)) {
399                 if (input_parser) {
400                         input_parser->set_timestamp (time);
401                         for (uint32_t i = 0; i < size; ++i) {
402                                 input_parser->scanner (buffer[i]);
403                         }
404                 }
405         }
406
407         return 0;
408 }
409
410 int
411 Port::create_ports(const XMLNode& node)
412 {
413         Descriptor desc (node);
414
415         assert(!_jack_input_port);
416         assert(!_jack_output_port);
417         
418         if (desc.mode == O_RDWR || desc.mode == O_WRONLY) {
419                 _jack_output_port_name = string(desc.tag).append ("_out");
420         }
421
422         if (desc.mode == O_RDWR || desc.mode == O_RDONLY) {
423                 _jack_input_port_name = string(desc.tag).append ("_in");
424         }
425
426         return create_ports ();
427 }
428
429 int
430 Port::create_ports ()
431 {
432         bool ret = true;
433
434         jack_nframes_t nframes = jack_get_buffer_size(_jack_client);
435
436         if (!_jack_output_port_name.empty()) {
437                 _jack_output_port = jack_port_register(_jack_client, _jack_output_port_name.c_str(),
438                                                        JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
439                 if (_jack_output_port) {
440                         jack_midi_clear_buffer(jack_port_get_buffer(_jack_output_port, nframes));
441                 }
442                 ret = ret && (_jack_output_port != NULL);
443         }
444         
445         if (!_jack_input_port_name.empty()) {
446                 _jack_input_port = jack_port_register(_jack_client, _jack_input_port_name.c_str(),
447                                                       JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
448                 if (_jack_input_port) {
449                         jack_midi_clear_buffer(jack_port_get_buffer(_jack_input_port, nframes));
450                 }
451                 ret = ret && (_jack_input_port != NULL);
452         }
453
454         return ret ? 0 : -1;
455 }
456
457 XMLNode& 
458 Port::get_state () const
459 {
460         XMLNode* root = new XMLNode ("MIDI-port");
461         root->add_property ("tag", _tagname);
462
463         if (_mode == O_RDONLY) {
464                 root->add_property ("mode", "input");
465         } else if (_mode == O_WRONLY) {
466                 root->add_property ("mode", "output");
467         } else {
468                 root->add_property ("mode", "duplex");
469         }
470         
471 #if 0
472         byte device_inquiry[6];
473
474         device_inquiry[0] = 0xf0;
475         device_inquiry[0] = 0x7e;
476         device_inquiry[0] = 0x7f;
477         device_inquiry[0] = 0x06;
478         device_inquiry[0] = 0x02;
479         device_inquiry[0] = 0xf7;
480         
481         write (device_inquiry, sizeof (device_inquiry), 0);
482 #endif
483
484         if (_jack_output_port) {
485                 
486                 const char** jc = jack_port_get_connections (_jack_output_port);
487                 string connection_string;
488                 if (jc) {
489                         for (int i = 0; jc[i]; ++i) {
490                                 if (i > 0) {
491                                         connection_string += ',';
492                                 }
493                                 connection_string += jc[i];
494                         }
495                         free (jc);
496                 }
497                 
498                 if (!connection_string.empty()) {
499                         root->add_property ("outbound", connection_string);
500                 }
501         } else {
502                 if (!_outbound_connections.empty()) {
503                         root->add_property ("outbound", _outbound_connections);
504                 }
505         }
506
507         if (_jack_input_port) {
508
509                 const char** jc = jack_port_get_connections (_jack_input_port);
510                 string connection_string;
511                 if (jc) {
512                         for (int i = 0; jc[i]; ++i) {
513                                 if (i > 0) {
514                                         connection_string += ',';
515                                 }
516                                 connection_string += jc[i];
517                         }
518                         free (jc);
519                 }
520
521                 if (!connection_string.empty()) {
522                         root->add_property ("inbound", connection_string);
523                 }
524         } else {
525                 if (!_inbound_connections.empty()) {
526                         root->add_property ("inbound", _inbound_connections);
527                 }
528         }
529
530         return *root;
531 }
532
533 void
534 Port::set_state (const XMLNode& node)
535 {
536         const XMLProperty* prop;
537
538         if ((prop = node.property ("inbound")) != 0 && _jack_input_port) {
539                 _inbound_connections = prop->value ();
540         }
541
542         if ((prop = node.property ("outbound")) != 0 && _jack_output_port) {
543                 _outbound_connections = prop->value();
544         }
545 }
546
547 void
548 Port::make_connections ()
549 {
550         if (!_inbound_connections.empty()) {
551                 vector<string> ports;
552                 split (_inbound_connections, ports, ',');
553                 for (vector<string>::iterator x = ports.begin(); x != ports.end(); ++x) {
554                         if (_jack_client) {
555                                 jack_connect (_jack_client, (*x).c_str(), jack_port_name (_jack_input_port));
556                                 /* ignore failures */
557                         }
558                 }
559         }
560
561         if (!_outbound_connections.empty()) {
562                 vector<string> ports;
563                 split (_outbound_connections, ports, ',');
564                 for (vector<string>::iterator x = ports.begin(); x != ports.end(); ++x) {
565                         if (_jack_client) {
566                                 jack_connect (_jack_client, jack_port_name (_jack_output_port), (*x).c_str());
567                                 /* ignore failures */
568                         }
569                 }
570         }
571         connect_connection.disconnect ();
572 }
573
574 void
575 Port::set_process_thread (pthread_t thr)
576 {
577         _process_thread = thr;
578 }
579
580 bool
581 Port::is_process_thread()
582 {
583         return (pthread_self() == _process_thread);
584 }
585
586 void
587 Port::reestablish (void* jack)
588 {
589         _jack_client = static_cast<jack_client_t*> (jack);
590         int const r = create_ports ();
591
592         if (r) {
593                 PBD::error << "could not reregister ports for " << name() << endmsg;
594         }
595 }
596
597 void
598 Port::reconnect ()
599 {
600         make_connections ();
601 }