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"
25 using namespace Mackie;
28 const char * MackieControlProtocol::default_port_name = "mcu";
30 bool MackieControlProtocol::probe()
32 if ( MIDI::Manager::instance()->port( default_port_name ) == 0 )
34 info << "Mackie: No MIDI port called " << default_port_name << endmsg;
43 void * MackieControlProtocol::monitor_work()
45 register_thread (X_("MCU"));
47 pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, 0);
48 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
50 // read from midi ports
58 catch ( exception & e ) {
59 cout << "MackieControlProtocol::poll_ports caught exception: " << e.what() << endl;
60 _ports_changed = true;
64 // poll for session data that needs to go to the unit
67 catch ( exception & e )
69 cout << "caught exception in MackieControlProtocol::monitor_work " << e.what() << endl;
73 // TODO ports and pfd and nfds should be in a separate class
81 void MackieControlProtocol::update_ports()
84 cout << "MackieControlProtocol::update_ports" << endl;
88 Glib::Mutex::Lock ul( update_mutex );
89 // yes, this is a double-test locking paradigm, or whatever it's called
90 // because we don't *always* need to acquire the lock for the first test
92 cout << "MackieControlProtocol::update_ports lock acquired" << endl;
96 // create new pollfd structures
98 pfd = new pollfd[_ports.size()];
100 cout << "pfd: " << pfd << endl;
103 for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
105 // add the port any handler
106 (*it)->connect_any();
108 cout << "adding pollfd for port " << (*it)->port().name() << " to pollfd " << nfds << endl;
110 pfd[nfds].fd = (*it)->port().selectable();
111 pfd[nfds].events = POLLIN|POLLHUP|POLLERR;
114 _ports_changed = false;
117 cout << "MackieControlProtocol::update_ports signal" << endl;
119 update_cond.signal();
122 cout << "MackieControlProtocol::update_ports finish" << endl;
126 void MackieControlProtocol::read_ports()
128 /* now read any data on the ports */
129 Glib::Mutex::Lock lock( update_mutex );
130 for ( int p = 0; p < nfds; ++p )
132 // this will cause handle_midi_any in the MackiePort to be triggered
133 // for alsa/raw ports
134 // alsa/sequencer ports trigger the midi parser off poll
135 if ( (pfd[p].revents & POLLIN) > 0 )
137 // avoid deadlocking?
138 // doesn't seem to make a difference
146 bool MackieControlProtocol::poll_ports()
148 int timeout = 10; // milliseconds
149 int no_ports_sleep = 1000; // milliseconds
151 Glib::Mutex::Lock lock( update_mutex );
152 // if there are no ports
157 cout << "poll_ports no ports" << endl;
159 usleep( no_ports_sleep * 1000 );
163 int retval = ::poll( pfd, nfds, timeout );
166 // gdb at work, perhaps
167 if ( errno != EINTR )
169 error << string_compose(_("Mackie MIDI thread poll failed (%1)"), strerror( errno ) ) << endmsg;
177 void MackieControlProtocol::handle_port_inactive( SurfacePort * port )
179 // port gone away. So stop polling it ASAP
181 // delete the port instance
182 Glib::Mutex::Lock lock( update_mutex );
183 MackiePorts::iterator it = find( _ports.begin(), _ports.end(), port );
184 if ( it != _ports.end() )
190 _ports_changed = true;
193 // TODO all the rebuilding of surfaces and so on
196 void MackieControlProtocol::handle_port_active (SurfacePort *)
198 // no need to re-add port because it was already added
199 // during the init phase. So just update the local surface
200 // representation and send the representation to
201 // all existing ports
203 // TODO update bank size
205 // TODO rebuild surface, to have new units
207 // finally update session state to the surface
208 // TODO but this is also done in set_active, and
209 // in fact update_surface won't execute unless
211 cout << "update_surface in handle_port_active" << endl;
217 void MackieControlProtocol::handle_port_init (Mackie::SurfacePort *)
220 cout << "MackieControlProtocol::handle_port_init" << endl;
222 _ports_changed = true;
225 cout << "MackieControlProtocol::handle_port_init finish" << endl;