Beginnings of writing to the LCD strip display. Some other tweaks and output thing...
authorJohn Anderson <ardour@semiosix.com>
Wed, 18 Jul 2007 19:09:33 +0000 (19:09 +0000)
committerJohn Anderson <ardour@semiosix.com>
Wed, 18 Jul 2007 19:09:33 +0000 (19:09 +0000)
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@2144 d708f5d6-7413-0410-9779-e7cbd77b26cf

12 files changed:
libs/surfaces/mackie/TODO
libs/surfaces/mackie/controls.h
libs/surfaces/mackie/mackie_control_protocol.cc
libs/surfaces/mackie/mackie_control_protocol_poll.cc
libs/surfaces/mackie/mackie_midi_builder.cc
libs/surfaces/mackie/mackie_midi_builder.h
libs/surfaces/mackie/mackie_port.cc
libs/surfaces/mackie/mackie_port.h
libs/surfaces/mackie/midi_byte_array.cc
libs/surfaces/mackie/midi_byte_array.h
libs/surfaces/mackie/surface.cc
libs/surfaces/mackie/surface_port.cc

index a9cb1b987870369135deb12220aa881ef88db2c3..f552c4a74c0f63d3e84fa3fad6a26b17db26cf51 100644 (file)
@@ -1,3 +1,5 @@
+* alsa/sequencer ports unstable
+* crash when mmc port set to mcu
 * how long can UI signal callbacks take to execute? What happens if they block?
   where ENSURE_CORRECT_THREAD is a macro that is modelled on ENSURE_GUI_THREAD
   if the handler is not called in the "correct thread", it will use a pseudo-RT-safe-enough technique to get the correct thread to recall "handler" later on, and return.
index 129fe070c62e4f2d6fe1cea9dc3e4eafdbd7e42b..ed9e8b79fbfe09554381b89cde1a0a08b2909640 100644 (file)
@@ -83,6 +83,9 @@ class Fader;
 class Strip : public Group
 {
 public:
+       /**
+               \param is the index of the strip. 0-based.
+       */
        Strip( const std::string & name, int index );
        
        virtual bool is_strip() const
@@ -92,10 +95,11 @@ public:
        
        virtual void add( Control & control );
        
-       /// This is the index of the strip
+       /// This is the index of the strip. zero-based.
        int index() const { return _index; }
        
        /// This is for Surface only
+       /// index is zero-based
        void index( int rhs ) { _index = rhs; }
        
        Button & solo();
index dac287a758cf9d0ebf0f732fc1852c5c037518db..4a9121bb7189062d6e204a0b38e98207c6f994fc 100644 (file)
@@ -38,6 +38,7 @@
 #include <pbd/pthread_utils.h>
 #include <pbd/error.h>
 #include <pbd/memento_command.h>
+#include <pbd/convert.h>
 
 #include <ardour/route.h>
 #include <ardour/session.h>
@@ -366,7 +367,7 @@ void MackieControlProtocol::zero_all()
        }
 }
 
-int MackieControlProtocol::set_active (bool yn)
+int MackieControlProtocol::set_active( bool yn )
 {
        if ( yn != _active )
        {
@@ -563,6 +564,10 @@ void MackieControlProtocol::connect_session_signals()
 
 void MackieControlProtocol::add_port( MIDI::Port & midi_port, int number )
 {
+#ifdef DEBUG
+               cout << "add port " << midi_port.name() << ", " << midi_port.device() << endl;
+#endif
+
        MackiePort * sport = new MackiePort( *this, midi_port, number );
        _ports.push_back( sport );
 
@@ -998,7 +1003,30 @@ void MackieControlProtocol::notify_name_changed( void *, RouteSignal * route_sig
 {
        try
        {
-               // TODO implement MackieControlProtocol::notify_name_changed
+               Strip & strip = route_signal->strip();
+               if ( !strip.is_master() )
+               {
+                       string line1;
+                       string line2;
+                       string fullname = route_signal->route().name();
+                       
+                       if ( fullname.length() <= 6 )
+                       {
+                               line1 = fullname;
+                       }
+                       else
+                       {
+                               line1 = PBD::short_version( fullname, 6 );
+                               line2 = fullname.substr( fullname.length() - 6, 6 );
+                       }
+                       
+                       route_signal->port().write_sysex(
+                               builder.strip_display( strip.index(), 0, line1 )
+                       );
+                       route_signal->port().write_sysex(
+                               builder.strip_display( strip.index(), 1, line2 )
+                       );
+               }
        }
        catch( exception & e )
        {
@@ -1012,7 +1040,6 @@ void MackieControlProtocol::notify_panner_changed( RouteSignal * route_signal )
        {
                Pot & pot = route_signal->strip().vpot();
                const Panner & panner = route_signal->route().panner();
-               cout << "panner from ardour" << panner.size() << " " << boolalpha << panner.linked() << endl;
                if ( panner.size() == 1 || ( panner.size() == 2 && panner.linked() ) )
                {
                        float pos;
index 951fb75a5095dbcb8e1784b4c67dd00a29de7300..6ae2da071e3ebac05f4bfb1b44ad2340e5ce2af2 100644 (file)
@@ -29,7 +29,15 @@ const char * MackieControlProtocol::default_port_name = "mcu";
 
 bool MackieControlProtocol::probe()
 {
-       return MIDI::Manager::instance()->port( default_port_name ) != 0;
+       if ( MIDI::Manager::instance()->port( default_port_name ) == 0 )
+       {
+               error << "No port called mcu. Add it to ardour.rc." << endmsg;
+               return false;
+       }
+       else
+       {
+               return true;
+       }
 }
 
 void * MackieControlProtocol::monitor_work()
@@ -47,6 +55,8 @@ void * MackieControlProtocol::monitor_work()
                {
                        if ( poll_ports() )
                        {
+       cout << "--------------------------------------" << endl;
+       cout << "MackieControlProtocol::read_ports _ports: " << _ports.size() << ", nfds: " << nfds << endl;
                                try { read_ports(); }
                                catch ( exception & e ) {
                                        cout << "MackieControlProtocol::poll_ports caught exception: " << e.what() << endl;
@@ -82,14 +92,14 @@ void MackieControlProtocol::update_ports()
                {
                        // create new pollfd structures
                        if ( pfd != 0 ) delete[] pfd;
-                       // TODO This might be a memory leak. How does thread cancellation cleanup work?
                        pfd = new pollfd[_ports.size()];
                        nfds = 0;
-
                        for( MackiePorts::iterator it = _ports.begin(); it != _ports.end(); ++it )
                        {
+                               // add the port any handler
+                               (*it)->connect_any();
 #ifdef DEBUG
-                               cout << "adding port " << (*it)->port().name() << " to pollfd" << endl;
+                               cout << "adding pollfd for port " << (*it)->port().name() << " to pollfd" << endl;
 #endif
                                pfd[nfds].fd = (*it)->port().selectable();
                                pfd[nfds].events = POLLIN|POLLHUP|POLLERR;
@@ -108,6 +118,8 @@ void MackieControlProtocol::read_ports()
        for ( int p = 0; p < nfds; ++p )
        {
                // this will cause handle_midi_any in the MackiePort to be triggered
+               // for alsa/raw ports
+               // alsa/sequencer ports trigger the midi parser off poll
                if ( pfd[p].revents & POLLIN > 0 )
                {
                        // avoid deadlocking?
@@ -129,12 +141,14 @@ bool MackieControlProtocol::poll_ports()
        if ( nfds < 1 )
        {
                lock.release();
-               //cout << "poll_ports no ports" << endl;
+#ifdef DEBUG
+               cout << "poll_ports no ports" << endl;
+#endif
                usleep( no_ports_sleep * 1000 );
                return false;
        }
 
-       int retval = poll( pfd, nfds, timeout );
+       int retval = ::poll( pfd, nfds, timeout );
        if ( retval < 0 )
        {
                // gdb at work, perhaps
index 3d07ff94bff06f2246b7b122a6892eac7ef9aa65..a02126d059b15b4c0d337eefdf421b73fafe268a 100644 (file)
@@ -171,3 +171,40 @@ MidiByteArray MackieMidiBuilder::two_char_display( unsigned int value, const std
        os << setfill('0') << setw(2) << value % 100;
        return two_char_display( os.str() );
 }
+
+MidiByteArray MackieMidiBuilder::strip_display( unsigned int strip_index, unsigned int line_number, const std::string & line )
+{
+       if ( line_number > 1 )
+       {
+               throw runtime_error( "line_number must be 0 or 1" );
+       }
+       
+       if ( strip_index > 7 )
+       {
+               throw runtime_error( "strip_index must be between 0 and 7" );
+       }
+       
+       cout << "MackieMidiBuilder::strip_display index: " << strip_index << ", line " << line_number << ": " << line << endl;
+       
+       MidiByteArray retval;
+       // code for display
+       retval << 0x12;
+       // offset (0 to 0x37 first line, 0x38 to 0x6f for second line )
+       retval << ( strip_index * 7 + ( line_number * 0x38 ) );
+       retval << line;
+       if ( strip_index != 7 )
+       {
+               retval << ' ';
+       }
+       
+       cout << "MackieMidiBuilder::strip_display midi: " << retval << endl;
+       return retval;
+}
+       
+MidiByteArray MackieMidiBuilder::all_strips_display( std::vector<std::string> & lines1, std::vector<std::string> & lines2 )
+{
+       MidiByteArray retval;
+       retval << 0x12 << 0;
+       retval << "Not working yet";
+       return retval;
+}
index c71c7180418c80ecd38fd991db00a98a04ba9094..d039fb43d10aac6556acec90a4778e322cac028b 100644 (file)
@@ -73,6 +73,13 @@ public:
        MidiByteArray two_char_display( const std::string & msg, const std::string & dots = "  " );
        MidiByteArray two_char_display( unsigned int value, const std::string & dots = "  " );
        
+       /// for displaying a particular strip name
+       /// index is zero-based
+       MidiByteArray strip_display( unsigned int strip_index, unsigned int line_number, const std::string & line );
+       
+       /// for generating all strip names
+       MidiByteArray all_strips_display( std::vector<std::string> & lines1, std::vector<std::string> & lines2 );
+       
 protected:
        static MIDI::byte calculate_pot_value( midi_pot_mode mode, const ControlState & );
 };
index 9bcee638fbc854c0eab9fde55be64dbd7f9c6dec..26c3612a8665cc5d0293c28512e871615770f0d5 100644 (file)
@@ -296,13 +296,38 @@ void MackiePort::finalise_init( bool yn )
                active_event();
                
                // start handling messages from controls
-               _any = port().input()->any.connect( ( mem_fun (*this, &MackiePort::handle_midi_any) ) );
+               connect_any();
        }
        _initialising = false;
        init_cond.signal();
        init_mutex.unlock();
 }
 
+void MackiePort::connect_any()
+{
+/*
+       Doesn't work because there isn't and == operator for slots
+       MIDI::Signal::slot_list_type slots = port().input()->any.slots();
+       
+       if ( find( slots.begin(), slots.end(), mem_fun( *this, &MackiePort::handle_midi_any ) ) == slots.end() )
+*/
+       // but this will break if midi tracing is turned on
+       if ( port().input()->any.empty() )
+       {
+#ifdef DEBUG
+               cout << "connect input parser " << port().input() << " to handle_midi_any" << endl;
+#endif
+               _any = port().input()->any.connect( mem_fun( *this, &MackiePort::handle_midi_any ) );
+#ifdef DEBUG
+               cout << "input parser any connections: " << port().input()->any.size() << endl;
+#endif
+       }
+       else
+       {
+               cout << "MackiePort::connect_any already connected" << endl;
+       }
+}
+
 bool MackiePort::wait_for_init()
 {
        Glib::Mutex::Lock lock( init_mutex );
@@ -346,6 +371,9 @@ void MackiePort::handle_midi_sysex (MIDI::Parser & parser, MIDI::byte * raw_byte
 void MackiePort::handle_midi_any (MIDI::Parser & parser, MIDI::byte * raw_bytes, size_t count )
 {
        MidiByteArray bytes( count, raw_bytes );
+#ifdef DEBUG
+       cout << "MackiePort::handle_midi_any " << bytes << endl;
+#endif
        try
        {
                // ignore sysex messages
@@ -394,6 +422,9 @@ void MackiePort::handle_midi_any (MIDI::Parser & parser, MIDI::byte * raw_bytes,
        }
        catch( MackieControlException & e )
        {
-               //cout << bytes << ' ' << e.what() << endl;
+               cout << bytes << ' ' << e.what() << endl;
        }
+#ifdef DEBUG
+       cout << "finished MackiePort::handle_midi_any " << bytes << endl;
+#endif
 }
index 2ad5cf61548e10056ae389567525c3e260419f72..0a705e65f367fb84b8d547ee5894ab22a959a46e 100644 (file)
@@ -71,6 +71,10 @@ public:
        
        emulation_t emulation() const { return _emulation; }
        
+       /// Connect the any signal from the parser to handle_midi_any
+       /// unless it's already connected
+       void connect_any();
+       
 protected:
        /**
                The initialisation sequence is fairly complex. First a lock is acquired
index 192af6a1ce3fe5f086b6815888ed8786eca1bae6..1c27c82be1c1e3f1cc6224f31e59ded21dead893 100644 (file)
@@ -24,6 +24,7 @@
 #include <algorithm>
 #include <cstdarg>
 #include <iomanip>
+#include <stdexcept>
 
 using namespace std;
 
@@ -96,3 +97,12 @@ ostream & operator << ( ostream & os, const MidiByteArray & mba )
        os << "]";
        return os;
 }
+
+MidiByteArray & operator << ( MidiByteArray & mba, const std::string & st )
+{
+       for ( string::const_iterator it = st.begin(); it != st.end(); ++it )
+       {
+               mba << *it;
+       }
+       return mba;
+}
index e77ece1b88a6e8d96c16b53f49ea8e0d0175442d..7176367189d3c391eed4320be02111fb06a3dcaf 100644 (file)
@@ -67,6 +67,9 @@ public:
 /// append the given byte to the end of the array
 MidiByteArray & operator << ( MidiByteArray & mba, const MIDI::byte & b );
 
+/// append the given string to the end of the array
+MidiByteArray & operator << ( MidiByteArray & mba, const std::string & );
+
 /// append the given array to the end of this array
 MidiByteArray & operator << ( MidiByteArray & mba, const MidiByteArray & barr );
 
index bcf6071f150a0080ecdb348f8ca40d8ac37ce7c9..7c77e862859d8c28fdecaf8960eccfe89f0d41c3 100644 (file)
@@ -123,4 +123,3 @@ void Strip::add( Control & control )
                throw MackieControlException( os.str() );
        }
 }
-
index e74ae93841491cf79b69f51ed9f37ae8181b7670..cba4c2c4945605df38fbb5a08a42a53df3699aac 100644 (file)
@@ -67,6 +67,7 @@ MidiByteArray SurfacePort::read()
        if ( !active() ) return retval;
        
        // return nothing read if the lock isn't acquired
+#if 0
        Glib::RecMutex::Lock lock( _rwlock, Glib::TRY_LOCK );
                
        if ( !lock.locked() )
@@ -77,6 +78,7 @@ MidiByteArray SurfacePort::read()
        
        // check active again - destructor sequence
        if ( !active() ) return retval;
+#endif
        
        // read port and copy to return value
        int nread = port().read( buf, sizeof (buf) );
@@ -85,6 +87,9 @@ MidiByteArray SurfacePort::read()
                retval.copy( nread, buf );
                if ((size_t) nread == sizeof (buf))
                {
+#ifdef DEBUG
+                       cout << "SurfacePort::read recursive" << endl;
+#endif
                        retval << read();
                }
        }
@@ -136,7 +141,7 @@ void SurfacePort::write( const MidiByteArray & mba )
                }
        }
 #ifdef DEBUG
-       if ( mba[0] == 0xf0 ) cout << "SurfacePort::write " << count << endl;
+       cout << "SurfacePort::wrote " << count << endl;
 #endif
 }