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 // What does ThreadCreatedWithRequestSize do?
38 PBD::ThreadCreated (pthread_self(), X_("Mackie"));
40 pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, 0);
41 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
43 // read from midi ports
51 catch ( exception & e ) {
52 cout << "MackieControlProtocol::poll_ports caught exception: " << e.what() << endl;
53 _ports_changed = true;
57 // poll for automation data from the routes
60 catch ( exception & e )
62 cout << "caught exception in MackieControlProtocol::monitor_work " << e.what() << endl;
65 // provide a cancellation point
69 // these never get called because of cancellation point above
70 cout << "MackieControlProtocol::poll_ports exiting" << endl;
77 void MackieControlProtocol::update_ports()
81 Glib::Mutex::Lock ul( update_mutex );
82 // yes, this is a double-test locking paradigm, or whatever it's called
83 // because we don't *always* need to acquire the lock for the first test
86 // create new pollfd structures
87 if ( pfd != 0 ) delete[] pfd;
88 // TODO This might be a memory leak. How does thread cancellation cleanup work?
89 pfd = new pollfd[_ports.size()];
92 for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
94 cout << "adding port " << (*it)->port().name() << " to pollfd" << endl;
95 pfd[nfds].fd = (*it)->port().selectable();
96 pfd[nfds].events = POLLIN|POLLHUP|POLLERR;
99 _ports_changed = false;
101 update_cond.signal();
105 void MackieControlProtocol::read_ports()
107 /* now read any data on the ports */
108 Glib::Mutex::Lock lock( update_mutex );
109 for ( int p = 0; p < nfds; ++p )
111 // this will cause handle_midi_any in the MackiePort to be triggered
112 if ( pfd[p].revents & POLLIN > 0 )
114 // avoid deadlocking?
115 // doesn't seem to make a difference
123 bool MackieControlProtocol::poll_ports()
125 int timeout = 10; // milliseconds
126 int no_ports_sleep = 1000; // milliseconds
128 Glib::Mutex::Lock lock( update_mutex );
129 // if there are no ports
133 cout << "poll_ports no ports" << endl;
134 usleep( no_ports_sleep * 1000 );
138 int retval = poll( pfd, nfds, timeout );
141 // gdb at work, perhaps
142 if ( errno != EINTR )
144 error << string_compose(_("Mackie MIDI thread poll failed (%1)"), strerror( errno ) ) << endmsg;
152 void MackieControlProtocol::handle_port_inactive( SurfacePort * port )
154 // port gone away. So stop polling it ASAP
156 // delete the port instance
157 Glib::Mutex::Lock lock( update_mutex );
158 MackiePorts::iterator it = find( _ports.begin(), _ports.end(), port );
159 if ( it != _ports.end() )
165 _ports_changed = true;
168 // TODO all the rebuilding of surfaces and so on
171 void MackieControlProtocol::handle_port_active( SurfacePort * port )
173 // no need to re-add port because it was already added
174 // during the init phase. So just update the local surface
175 // representation and send the representation to
176 // all existing ports
178 // TODO update bank size
180 // TODO rebuild surface, to have new units
182 // finally update session state to the surface
183 // TODO but this is also done in set_active, and
184 // in fact update_surface won't execute unless
186 cout << "update_surface in handle_port_active" << endl;
190 void MackieControlProtocol::handle_port_init( Mackie::SurfacePort * sport )
192 cout << "MackieControlProtocol::handle_port_init" << endl;
193 _ports_changed = true;