mirror of
https://github.com/Ardour/ardour.git
synced 2026-01-07 14:15:46 +01:00
Beginnings of writing to the LCD strip display. Some other tweaks and output thing, mostly related to alsa/sequencer weirdness.
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@2144 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
5c8830f952
commit
bfb5ddedab
12 changed files with 157 additions and 14 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 & );
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 );
|
||||
|
||||
|
|
|
|||
|
|
@ -123,4 +123,3 @@ void Strip::add( Control & control )
|
|||
throw MackieControlException( os.str() );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue