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