1 #include "mackie_control_protocol.h"
3 #include "midi_byte_array.h"
4 #include "surface_port.h"
6 #include <pbd/pthread_utils.h>
9 #include <midi++/types.h>
10 #include <midi++/port.h>
11 #include <midi++/manager.h>
12 #include <midi++/port_request.h>
25 using namespace Mackie;
28 const char * MackieControlProtocol::default_port_name = "mcu";
30 bool MackieControlProtocol::probe()
32 return MIDI::Manager::instance()->port( default_port_name ) != 0;
35 void * MackieControlProtocol::monitor_work()
37 cout << "MackieControlProtocol::monitor_work" << endl;
38 // What does ThreadCreatedWithRequestSize do?
39 PBD::ThreadCreated (pthread_self(), X_("Mackie"));
42 // it seems to do the "block" on poll less often
43 // with this code disabled
44 struct sched_param rtparam;
45 memset (&rtparam, 0, sizeof (rtparam));
46 rtparam.sched_priority = 9; /* XXX should be relative to audio (JACK) thread */
49 if ((err = pthread_setschedparam (pthread_self(), SCHED_FIFO, &rtparam)) != 0) {
50 // do we care? not particularly.
51 PBD::info << string_compose (_("%1: thread not running with realtime scheduling (%2)"), name(), strerror( errno )) << endmsg;
55 pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, 0);
56 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
58 // read from midi ports
59 cout << "start poll cycle" << endl;
66 catch ( exception & e ) {
67 cout << "MackieControlProtocol::poll_ports caught exception: " << e.what() << endl;
68 _ports_changed = true;
72 // provide a cancellation point
76 // these never get called
77 cout << "MackieControlProtocol::poll_ports exiting" << endl;
84 void MackieControlProtocol::update_ports()
86 // create pollfd structures if necessary
89 Glib::Mutex::Lock ul( update_mutex );
90 // yes, this is a double-test locking paradigm, or whatever it's called
91 // because we don't *always* need to acquire the lock for the first test
94 cout << "MackieControlProtocol::update_ports updating" << endl;
95 if ( pfd != 0 ) delete[] pfd;
96 // TODO This might be a memory leak. How does thread cancellation cleanup work?
97 pfd = new pollfd[_ports.size()];
100 for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
102 cout << "adding port " << (*it)->port().name() << " to pollfd" << endl;
103 pfd[nfds].fd = (*it)->port().selectable();
104 pfd[nfds].events = POLLIN|POLLHUP|POLLERR;
107 _ports_changed = false;
109 cout << "MackieControlProtocol::update_ports signalling" << endl;
110 update_cond.signal();
111 cout << "MackieControlProtocol::update_ports finished" << endl;
115 void MackieControlProtocol::read_ports()
117 /* now read any data on the ports */
118 Glib::Mutex::Lock lock( update_mutex );
119 for ( int p = 0; p < nfds; ++p )
121 // this will cause handle_midi_any in the MackiePort to be triggered
122 if ( pfd[p].revents & POLLIN > 0 )
131 bool MackieControlProtocol::poll_ports()
133 int timeout = 10; // milliseconds
134 int no_ports_sleep = 1000; // milliseconds
136 Glib::Mutex::Lock lock( update_mutex );
137 // if there are no ports
141 cout << "poll_ports no ports" << endl;
142 usleep( no_ports_sleep * 1000 );
146 int retval = poll( pfd, nfds, timeout );
149 // gdb at work, perhaps
150 if ( errno != EINTR )
152 error << string_compose(_("Mackie MIDI thread poll failed (%1)"), strerror( errno ) ) << endmsg;
160 void MackieControlProtocol::handle_port_changed( SurfacePort * port, bool active )
162 cout << "MackieControlProtocol::handle_port_changed port: " << *port << " active: " << active << endl;
163 if ( active == false )
165 // port gone away. So stop polling it ASAP
167 // delete the port instance
168 Glib::Mutex::Lock lock( update_mutex );
169 MackiePorts::iterator it = find( _ports.begin(), _ports.end(), port );
170 if ( it != _ports.end() )
176 _ports_changed = true;
181 _ports_changed = true;
186 // TODO update bank size
192 void MackieControlProtocol::handle_port_init( Mackie::SurfacePort * sport )
194 cout << "MackieControlProtocol::handle_port_init" << endl;
195 _ports_changed = true;
197 cout << "MackieControlProtocol::handle_port_init finished" << endl;