diff options
author | David Robillard <d@drobilla.net> | 2006-06-08 23:46:42 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2006-06-08 23:46:42 +0000 |
commit | 74dd5bd7060b337964d5ea5a3d419c26a62c10a6 (patch) | |
tree | 8a1ece4e1c6eb2b3a09c149b8b2afc71f70a024c /libs/midi++2 | |
parent | 0c1b9afc634d098ac6029acb3508d25823d0fc14 (diff) |
Committed filthy mess of a working copy solely for moving between machines.
Nothing to see here, move along now...
git-svn-id: svn://localhost/trunk/ardour2midi@575 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/midi++2')
-rw-r--r-- | libs/midi++2/SConscript | 14 | ||||
-rw-r--r-- | libs/midi++2/alsa_sequencer_midiport.cc | 4 | ||||
-rw-r--r-- | libs/midi++2/coremidi_midiport.cc | 2 | ||||
-rw-r--r-- | libs/midi++2/fd_midiport.cc | 2 | ||||
-rw-r--r-- | libs/midi++2/midi++/alsa_rawmidi.h | 3 | ||||
-rw-r--r-- | libs/midi++2/midi++/alsa_sequencer.h | 5 | ||||
-rw-r--r-- | libs/midi++2/midi++/channel.h | 111 | ||||
-rw-r--r-- | libs/midi++2/midi++/controllable.h | 2 | ||||
-rw-r--r-- | libs/midi++2/midi++/coremidi_midiport.h | 50 | ||||
-rw-r--r-- | libs/midi++2/midi++/factory.h | 2 | ||||
-rw-r--r-- | libs/midi++2/midi++/fd_midiport.h | 8 | ||||
-rw-r--r-- | libs/midi++2/midi++/manager.h | 33 | ||||
-rw-r--r-- | libs/midi++2/midi++/nullmidi.h | 5 | ||||
-rw-r--r-- | libs/midi++2/midi++/port.h | 115 | ||||
-rw-r--r-- | libs/midi++2/midi++/types.h | 4 | ||||
-rw-r--r-- | libs/midi++2/midichannel.cc | 108 | ||||
-rw-r--r-- | libs/midi++2/midicontrollable.cc | 4 | ||||
-rw-r--r-- | libs/midi++2/midifactory.cc | 15 | ||||
-rw-r--r-- | libs/midi++2/midimanager.cc | 124 | ||||
-rw-r--r-- | libs/midi++2/midiport.cc | 39 | ||||
-rw-r--r-- | libs/midi++2/port_request.cc | 7 |
21 files changed, 299 insertions, 358 deletions
diff --git a/libs/midi++2/SConscript b/libs/midi++2/SConscript index 7c3267a6c7..5230bfc391 100644 --- a/libs/midi++2/SConscript +++ b/libs/midi++2/SConscript @@ -30,18 +30,24 @@ version.cc """) sysdep_sources = Split (""" +jack_midiport.cc alsa_sequencer_midiport.cc coremidi_midiport.cc """) -if env['SYSMIDI'] == 'CoreMIDI': +if env['SYSMIDI'] == 'JACK MIDI': + sysdep_src = [ 'jack_midiport.cc' ] + midi2.Append (CCFLAGS="-DWITH_JACK_MIDI") +elif env['SYSMIDI'] == 'ALSA Sequencer': + sysdep_src = [ 'alsa_sequencer_midiport.cc' ] + midi2.Append (CCFLAGS="-DWITH_ALSA") +elif env['SYSMIDI'] == 'CoreMIDI': sysdep_src = [ 'coremidi_midiport.cc' ] midi2.Append (CCFLAGS="-DWITH_COREMIDI") midi2.Append (LINKFLAGS="-framework CoreMIDI") midi2.Append (LINKFLAGS="-framework CoreFoundation") -else: - sysdep_src = [ 'alsa_sequencer_midiport.cc' ] - midi2.Append (CCFLAGS="-DWITH_ALSA") + + midi2.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE") midi2.Append(CCFLAGS="-DLIBSIGC_DISABLE_DEPRECATED") diff --git a/libs/midi++2/alsa_sequencer_midiport.cc b/libs/midi++2/alsa_sequencer_midiport.cc index fca6707efd..1a758b275d 100644 --- a/libs/midi++2/alsa_sequencer_midiport.cc +++ b/libs/midi++2/alsa_sequencer_midiport.cc @@ -79,7 +79,7 @@ int ALSA_SequencerMidiPort::selectable () const return -1; } -int ALSA_SequencerMidiPort::write (byte *msg, size_t msglen) +int ALSA_SequencerMidiPort::write (byte *msg, size_t msglen, timestamp_t timestamp) { TR_FN (); int R; @@ -118,7 +118,7 @@ int ALSA_SequencerMidiPort::write (byte *msg, size_t msglen) return totwritten; } -int ALSA_SequencerMidiPort::read (byte *buf, size_t max) +int ALSA_SequencerMidiPort::read (byte *buf, size_t max, timestamp_t timestamp) { TR_FN(); int err; diff --git a/libs/midi++2/coremidi_midiport.cc b/libs/midi++2/coremidi_midiport.cc index 8d1d927b7b..2cd98239ec 100644 --- a/libs/midi++2/coremidi_midiport.cc +++ b/libs/midi++2/coremidi_midiport.cc @@ -56,7 +56,7 @@ void CoreMidi_MidiPort::Close () if (midi_client) MIDIClientDispose(midi_client); } -int CoreMidi_MidiPort::write (byte *msg, size_t msglen) +int CoreMidi_MidiPort::write (byte *msg, size_t msglen, timestamp_t timestamp) { OSStatus err; MIDIPacketList* pktlist = (MIDIPacketList*)midi_buffer; diff --git a/libs/midi++2/fd_midiport.cc b/libs/midi++2/fd_midiport.cc index 2ced63c259..ef387e7c49 100644 --- a/libs/midi++2/fd_midiport.cc +++ b/libs/midi++2/fd_midiport.cc @@ -151,7 +151,7 @@ FD_MidiPort::do_slow_write (byte *msg, unsigned int msglen) } int -FD_MidiPort::read (byte* buf, size_t max) +FD_MidiPort::read (byte* buf, size_t max, timestamp_t timestamp) { int nread; diff --git a/libs/midi++2/midi++/alsa_rawmidi.h b/libs/midi++2/midi++/alsa_rawmidi.h index 655b673174..f6c17541c2 100644 --- a/libs/midi++2/midi++/alsa_rawmidi.h +++ b/libs/midi++2/midi++/alsa_rawmidi.h @@ -29,6 +29,8 @@ #include <midi++/port.h> #include <midi++/fd_midiport.h> +namespace MIDI { + class ALSA_RawMidiPort : public MIDI::FD_MidiPort { @@ -38,6 +40,7 @@ class ALSA_RawMidiPort : public MIDI::FD_MidiPort virtual ~ALSA_RawMidiPort () {} }; +} // namespace MIDI #endif // __alsa_rawmidi_h__ diff --git a/libs/midi++2/midi++/alsa_sequencer.h b/libs/midi++2/midi++/alsa_sequencer.h index 8ddb2a7dd7..cb02ed961c 100644 --- a/libs/midi++2/midi++/alsa_sequencer.h +++ b/libs/midi++2/midi++/alsa_sequencer.h @@ -44,9 +44,8 @@ class ALSA_SequencerMidiPort : public Port protected: /* Direct I/O */ - - int write (byte *msg, size_t msglen); - int read (byte *buf, size_t max); + int write (byte *msg, size_t msglen, timestamp_t timestamp); + int read (byte *buf, size_t max, timestamp_t timestamp); private: snd_seq_t *seq; diff --git a/libs/midi++2/midi++/channel.h b/libs/midi++2/midi++/channel.h index f534f7e6da..0d24bf8bbe 100644 --- a/libs/midi++2/midi++/channel.h +++ b/libs/midi++2/midi++/channel.h @@ -32,17 +32,22 @@ namespace MIDI { class Port; +/** Stateful MIDI channel class. + * + * This remembers various useful information about the current 'state' of a + * MIDI channel (eg current pitch bend value). + */ class Channel : public sigc::trackable { public: Channel (byte channel_number, Port &); - Port &midi_port() { return port; } - byte channel() { return channel_number; } - byte program() { return program_number; } - byte bank() { return bank_number; } - byte pressure () { return chanpress; } - byte poly_pressure (byte n) { return polypress[n]; } + Port &midi_port() { return _port; } + byte channel() { return _channel_number; } + byte program() { return _program_number; } + byte bank() { return _bank_number; } + byte pressure () { return _chanpress; } + byte poly_pressure (byte n) { return _polypress[n]; } byte last_note_on () { return _last_note_on; @@ -58,53 +63,52 @@ class Channel : public sigc::trackable { } pitchbend_t pitchbend () { - return pitch_bend; + return _pitch_bend; } controller_value_t controller_value (byte n) { - return controller_val[n%128]; + return _controller_val[n%128]; } controller_value_t *controller_addr (byte n) { - return &controller_val[n%128]; + return &_controller_val[n%128]; } void set_controller (byte n, byte val) { - controller_val[n%128] = val; + _controller_val[n%128] = val; } - bool channel_msg (byte id, byte val1, byte val2); - - bool all_notes_off () { - return channel_msg (MIDI::controller, 123, 0); + bool channel_msg (byte id, byte val1, byte val2, timestamp_t timestamp); + bool all_notes_off (timestamp_t timestamp) { + return channel_msg (MIDI::controller, 123, 0, timestamp); } - bool control (byte id, byte value) { - return channel_msg (MIDI::controller, id, value); + bool control (byte id, byte value, timestamp_t timestamp) { + return channel_msg (MIDI::controller, id, value, timestamp); } - bool note_on (byte note, byte velocity) { - return channel_msg (MIDI::on, note, velocity); + bool note_on (byte note, byte velocity, timestamp_t timestamp) { + return channel_msg (MIDI::on, note, velocity, timestamp); } - bool note_off (byte note, byte velocity) { - return channel_msg (MIDI::off, note, velocity); + bool note_off (byte note, byte velocity, timestamp_t timestamp) { + return channel_msg (MIDI::off, note, velocity, timestamp); } - bool aftertouch (byte value) { - return channel_msg (MIDI::chanpress, value, 0); + bool aftertouch (byte value, timestamp_t timestamp) { + return channel_msg (MIDI::chanpress, value, 0, timestamp); } - bool poly_aftertouch (byte note, byte value) { - return channel_msg (MIDI::polypress, note, value); + bool poly_aftertouch (byte note, byte value, timestamp_t timestamp) { + return channel_msg (MIDI::polypress, note, value, timestamp); } - bool program_change (byte value) { - return channel_msg (MIDI::program, value, 0); + bool program_change (byte value, timestamp_t timestamp) { + return channel_msg (MIDI::program, value, 0, timestamp); } - bool pitchbend (byte msb, byte lsb) { - return channel_msg (MIDI::pitchbend, lsb, msb); + bool pitchbend (byte msb, byte lsb, timestamp_t timestamp) { + return channel_msg (MIDI::pitchbend, lsb, msb, timestamp); } protected: @@ -113,34 +117,33 @@ class Channel : public sigc::trackable { void connect_output_signals (); private: - Port &port; + Port & _port; /* Current channel values */ - - byte channel_number; - byte bank_number; - byte program_number; - byte rpn_msb; - byte rpn_lsb; - byte nrpn_msb; - byte nrpn_lsb; - byte chanpress; - byte polypress[128]; - bool controller_14bit[128]; - controller_value_t controller_val[128]; - byte controller_msb[128]; - byte controller_lsb[128]; - byte _last_note_on; - byte _last_on_velocity; - byte _last_note_off; - byte _last_off_velocity; - pitchbend_t pitch_bend; - bool _omni; - bool _poly; - bool _mono; - size_t _notes_on; - - void reset (bool notes_off = true); + byte _channel_number; + byte _bank_number; + byte _program_number; + byte _rpn_msb; + byte _rpn_lsb; + byte _nrpn_msb; + byte _nrpn_lsb; + byte _chanpress; + byte _polypress[128]; + bool _controller_14bit[128]; + controller_value_t _controller_val[128]; + byte _controller_msb[128]; + byte _controller_lsb[128]; + byte _last_note_on; + byte _last_on_velocity; + byte _last_note_off; + byte _last_off_velocity; + pitchbend_t _pitch_bend; + bool _omni; + bool _poly; + bool _mono; + size_t _notes_on; + + void reset (timestamp_t timestamp, nframes_t nframes, bool notes_off = true); void process_note_off (Parser &, EventTwoBytes *); void process_note_on (Parser &, EventTwoBytes *); diff --git a/libs/midi++2/midi++/controllable.h b/libs/midi++2/midi++/controllable.h index 3fa108bb46..44249cfa4f 100644 --- a/libs/midi++2/midi++/controllable.h +++ b/libs/midi++2/midi++/controllable.h @@ -60,7 +60,7 @@ class Controllable : public sigc::trackable std::string control_description() const { return _control_description; } - void send_midi_feedback (float); + void send_midi_feedback (float val, timestamp_t timestamp); private: bool bistate; diff --git a/libs/midi++2/midi++/coremidi_midiport.h b/libs/midi++2/midi++/coremidi_midiport.h index e02a225784..046b170bce 100644 --- a/libs/midi++2/midi++/coremidi_midiport.h +++ b/libs/midi++2/midi++/coremidi_midiport.h @@ -32,35 +32,35 @@ namespace MIDI { - class CoreMidi_MidiPort:public Port { - public: - CoreMidi_MidiPort(PortRequest & req); - virtual ~ CoreMidi_MidiPort(); +class CoreMidi_MidiPort:public Port { + public: + CoreMidi_MidiPort(PortRequest & req); + virtual ~ CoreMidi_MidiPort(); - virtual int selectable() const { - return -1; - } - protected: - /* Direct I/O */ - int write(byte * msg, size_t msglen); - int read(byte * buf, size_t max) { - return 0; - } /* CoreMidi callback */ - static void read_proc(const MIDIPacketList * pktlist, - void *refCon, void *connRefCon); + virtual int selectable() const { + return -1; + } + protected: + /* Direct I/O */ + int write (byte *msg, size_t msglen, timestamp_t timestamp); + int read (byte *buf, size_t max, timestamp_t timestamp); - private: - byte midi_buffer[1024]; - MIDIClientRef midi_client; - MIDIEndpointRef midi_destination; - MIDIEndpointRef midi_source; + /* CoreMidi callback */ + static void read_proc(const MIDIPacketList * pktlist, + void *refCon, void *connRefCon); - int Open(PortRequest & req); - void Close(); - static MIDITimeStamp MIDIGetCurrentHostTime(); + private: + byte midi_buffer[1024]; + MIDIClientRef midi_client; + MIDIEndpointRef midi_destination; + MIDIEndpointRef midi_source; - bool firstrecv; - }; + int Open(PortRequest & req); + void Close(); + static MIDITimeStamp MIDIGetCurrentHostTime(); + + bool firstrecv; +}; }; /* namespace MIDI */ diff --git a/libs/midi++2/midi++/factory.h b/libs/midi++2/midi++/factory.h index 1543f68cdc..3fa57b6676 100644 --- a/libs/midi++2/midi++/factory.h +++ b/libs/midi++2/midi++/factory.h @@ -29,7 +29,7 @@ namespace MIDI { class PortFactory { public: - Port *create_port (PortRequest &req); + Port *create_port (PortRequest &req, void* data); static void add_port_request (std::vector<PortRequest *> &reqs, const std::string &reqstr); diff --git a/libs/midi++2/midi++/fd_midiport.h b/libs/midi++2/midi++/fd_midiport.h index 853af9d7b4..e84dc47794 100644 --- a/libs/midi++2/midi++/fd_midiport.h +++ b/libs/midi++2/midi++/fd_midiport.h @@ -53,7 +53,10 @@ class FD_MidiPort : public Port int _fd; virtual void open (PortRequest &req); - virtual int write (byte *msg, size_t msglen) { + /* Direct I/O */ + + virtual int write (byte *msg, size_t msglen, + timestamp_t timestamp) { int nwritten; if ((_mode & O_ACCMODE) == O_RDONLY) { @@ -80,7 +83,8 @@ class FD_MidiPort : public Port return nwritten; } - virtual int read (byte *buf, size_t max); + virtual int read (byte *buf, size_t max, + timestamp_t timestamp); private: static std::string *midi_dirpath; diff --git a/libs/midi++2/midi++/manager.h b/libs/midi++2/midi++/manager.h index 4889aad8c9..ddf5c0f8cd 100644 --- a/libs/midi++2/midi++/manager.h +++ b/libs/midi++2/midi++/manager.h @@ -29,10 +29,27 @@ namespace MIDI { +/** Creates, stores, and manages system MIDI ports. + */ class Manager { public: ~Manager (); + void set_api_data(void* data) { api_data = data; } + + /** Signal the start of an audio cycle. + * This MUST be called before any reading/writing for this cycle. + * Realtime safe. + */ + void cycle_start(nframes_t nframes); + + /** Signal the end of an audio cycle. + * This signifies that the cycle began with @ref cycle_start has ended. + * This MUST be called at the end of each cycle. + * Realtime safe. + */ + void cycle_end(); + Port *add_port (PortRequest &); int remove_port (std::string port); @@ -41,20 +58,6 @@ class Manager { size_t nports () { return ports_by_device.size(); } - /* defaults for clients who are not picky */ - - Port *inputPort; - Port *outputPort; - channel_t inputChannelNumber; - channel_t outputChannelNumber; - - int set_input_port (size_t port); - int set_input_port (std::string); - int set_output_port (size_t port); - int set_output_port (std::string); - int set_input_channel (channel_t); - int set_output_channel (channel_t); - int foreach_port (int (*func)(const Port &, size_t n, void *), void *arg); @@ -80,6 +83,8 @@ class Manager { PortMap ports_by_device; /* canonical */ PortMap ports_by_tag; /* may contain duplicate Ports */ + void *api_data; + void close_ports (); }; diff --git a/libs/midi++2/midi++/nullmidi.h b/libs/midi++2/midi++/nullmidi.h index a94b1015b0..04c7d438bf 100644 --- a/libs/midi++2/midi++/nullmidi.h +++ b/libs/midi++2/midi++/nullmidi.h @@ -46,11 +46,12 @@ class Null_MidiPort : public Port virtual ~Null_MidiPort () {}; - virtual int write (byte *msg, size_t msglen) { + /* Direct I/O */ + int write (byte *msg, size_t msglen, timestamp_t timestamp) { return msglen; } - virtual int read (byte *buf, size_t max) { + int read (byte *buf, size_t max, timestamp_t timestamp) { return 0; } diff --git a/libs/midi++2/midi++/port.h b/libs/midi++2/midi++/port.h index 442cc4e5ed..919afb3755 100644 --- a/libs/midi++2/midi++/port.h +++ b/libs/midi++2/midi++/port.h @@ -37,6 +37,7 @@ class Port : public sigc::trackable { public: enum Type { Unknown, + JACK_Midi, ALSA_RawMidi, ALSA_Sequencer, CoreMidi_MidiPort, @@ -44,42 +45,64 @@ class Port : public sigc::trackable { FIFO, }; - Port (PortRequest &); virtual ~Port (); - /* Direct I/O */ + // FIXME: make Manager a friend of port so these can be hidden? + + /* Only for use by MidiManager. Don't ever call this. */ + virtual void cycle_start(nframes_t nframes); - /** \return number of bytes successfully written */ - virtual int write (byte *msg, size_t msglen) = 0; + /* Only for use by MidiManager. Don't ever call this. */ + virtual void cycle_end(); - /** \return number of bytes successfully written to \a buf */ - virtual int read (byte *buf, size_t max) = 0; + /* Direct I/O */ + + /** Read a message from port. + * @param buf Raw MIDI message to send + * @param max Max size to write to @a buf + * @param timestamp Time stamp in frames of this message (relative to cycle start) + * @return number of bytes successfully written to \a buf + */ + virtual int read(byte *buf, size_t max, timestamp_t timestamp) = 0; + + /** Write a message to port. + * @param msg Raw MIDI message to send + * @param msglen Size of @a msg + * @param timestamp Time stamp in frames of this message (relative to cycle start) + * @return number of bytes successfully written + */ + virtual int write(byte *msg, size_t msglen, timestamp_t timestamp) = 0; + + /** Write a message to port. + * @return true on success. + * FIXME: describe semantics here + */ + bool midimsg (byte *msg, size_t len, timestamp_t timestamp) { + return !(write (msg, len, timestamp) == (int) len); + } - /** Slow down I/O to a loop of single byte emissions - interspersed with a busy loop of 10000 * this value. + bool clock (timestamp_t timestamp); - This may be ignored by a particular instance of this virtual - class. See FD_MidiPort for an example of where it used. */ + /** Slow down I/O to a loop of single byte emissions + * interspersed with a busy loop of 10000 * this value. + * + * This may be ignored by a particular instance of this virtual + * class. See FD_MidiPort for an example of where it used. */ void set_slowdown (size_t n) { slowdown = n; } /* select(2)/poll(2)-based I/O */ + /** Get the file descriptor for port. + * @return File descriptor, or -1 if not selectable. */ virtual int selectable() const = 0; - void selector_read_callback (Select::Selectable *, Select::Condition); - - static void xforms_read_callback (int cond, int fd, void *ptr); - static void gtk_read_callback (void *ptr, int fd, int cond); - - static void write_callback (byte *msg, unsigned int len, void *); - Channel *channel (channel_t chn) { return _channel[chn&0x7F]; } - Parser *input() { return input_parser; } - Parser *output() { return output_parser; } + Parser *input() { return input_parser; } + Parser *output() { return output_parser; } void iostat (int *written, int *read, const size_t **in_counts, @@ -99,47 +122,31 @@ class Port : public sigc::trackable { } } - /** Write a message. - * \return true on success. */ - bool midimsg (byte *msg, size_t len) { - return !(write (msg, len) == (int) len); - } - - /** Write a 3-byte message. - * \return true on success. */ - bool three_byte_msg (byte a, byte b, byte c) { - byte msg[3]; - - msg[0] = a; - msg[1] = b; - msg[2] = c; - - return !(write (msg, 3) == 3); - } - bool clock (); const char *device () const { return _devname.c_str(); } - const char *name () const { return _tagname.c_str(); } - Type type () const { return _type; } - int mode () const { return _mode; } - bool ok () const { return _ok; } - size_t number () const { return _number; } + const char *name () const { return _tagname.c_str(); } + Type type () const { return _type; } + int mode () const { return _mode; } + bool ok () const { return _ok; } + size_t number () const { return _number; } protected: - bool _ok; - Type _type; - std::string _devname; - std::string _tagname; - int _mode; - size_t _number; - Channel *_channel[16]; + bool _ok; + bool _currently_in_cycle; + nframes_t _nframes_this_cycle; + Type _type; + std::string _devname; + std::string _tagname; + int _mode; + size_t _number; + Channel *_channel[16]; sigc::connection thru_connection; - unsigned int bytes_written; - unsigned int bytes_read; - Parser *input_parser; - Parser *output_parser; - size_t slowdown; + unsigned int bytes_written; + unsigned int bytes_read; + Parser *input_parser; + Parser *output_parser; + size_t slowdown; private: static size_t nports; diff --git a/libs/midi++2/midi++/types.h b/libs/midi++2/midi++/types.h index b9d9bf33e7..dc70381d5b 100644 --- a/libs/midi++2/midi++/types.h +++ b/libs/midi++2/midi++/types.h @@ -4,9 +4,11 @@ namespace MIDI { typedef char channel_t; - typedef float controller_value_t; + typedef float controller_value_t; typedef unsigned char byte; typedef unsigned short pitchbend_t; + typedef unsigned int timestamp_t; + typedef unsigned int nframes_t; enum eventType { none = 0x0, diff --git a/libs/midi++2/midichannel.cc b/libs/midi++2/midichannel.cc index 42949591fe..fe4f4afeb2 100644 --- a/libs/midi++2/midichannel.cc +++ b/libs/midi++2/midichannel.cc @@ -25,61 +25,61 @@ using namespace sigc; using namespace MIDI; -Channel::Channel (byte channelnum, Port &p) : port (p) +Channel::Channel (byte channelnum, Port &p) : _port (p) { - channel_number = channelnum; + _channel_number = channelnum; - reset (false); + reset (0, 1, false); } void Channel::connect_input_signals () { - port.input()->channel_pressure[channel_number].connect + _port.input()->channel_pressure[_channel_number].connect (mem_fun (*this, &Channel::process_chanpress)); - port.input()->channel_note_on[channel_number].connect + _port.input()->channel_note_on[_channel_number].connect (mem_fun (*this, &Channel::process_note_on)); - port.input()->channel_note_off[channel_number].connect + _port.input()->channel_note_off[_channel_number].connect (mem_fun (*this, &Channel::process_note_off)); - port.input()->channel_poly_pressure[channel_number].connect + _port.input()->channel_poly_pressure[_channel_number].connect (mem_fun (*this, &Channel::process_polypress)); - port.input()->channel_program_change[channel_number].connect + _port.input()->channel_program_change[_channel_number].connect (mem_fun (*this, &Channel::process_program_change)); - port.input()->channel_controller[channel_number].connect + _port.input()->channel_controller[_channel_number].connect (mem_fun (*this, &Channel::process_controller)); - port.input()->channel_pitchbend[channel_number].connect + _port.input()->channel_pitchbend[_channel_number].connect (mem_fun (*this, &Channel::process_pitchbend)); - port.input()->reset.connect (mem_fun (*this, &Channel::process_reset)); + _port.input()->reset.connect (mem_fun (*this, &Channel::process_reset)); } void Channel::connect_output_signals () { - port.output()->channel_pressure[channel_number].connect + _port.output()->channel_pressure[_channel_number].connect (mem_fun (*this, &Channel::process_chanpress)); - port.output()->channel_note_on[channel_number].connect + _port.output()->channel_note_on[_channel_number].connect (mem_fun (*this, &Channel::process_note_on)); - port.output()->channel_note_off[channel_number].connect + _port.output()->channel_note_off[_channel_number].connect (mem_fun (*this, &Channel::process_note_off)); - port.output()->channel_poly_pressure[channel_number].connect + _port.output()->channel_poly_pressure[_channel_number].connect (mem_fun (*this, &Channel::process_polypress)); - port.output()->channel_program_change[channel_number].connect + _port.output()->channel_program_change[_channel_number].connect (mem_fun (*this, &Channel::process_program_change)); - port.output()->channel_controller[channel_number].connect + _port.output()->channel_controller[_channel_number].connect (mem_fun (*this, &Channel::process_controller)); - port.output()->channel_pitchbend[channel_number].connect + _port.output()->channel_pitchbend[_channel_number].connect (mem_fun (*this, &Channel::process_pitchbend)); - port.output()->reset.connect (mem_fun (*this, &Channel::process_reset)); + _port.output()->reset.connect (mem_fun (*this, &Channel::process_reset)); } void -Channel::reset (bool notes_off) +Channel::reset (timestamp_t timestamp, nframes_t nframes, bool notes_off) { - program_number = channel_number; - bank_number = 0; - pitch_bend = 0; + _program_number = _channel_number; + _bank_number = 0; + _pitch_bend = 0; _last_note_on = 0; _last_note_off = 0; @@ -87,25 +87,25 @@ Channel::reset (bool notes_off) _last_off_velocity = 0; if (notes_off) { - all_notes_off (); + all_notes_off (timestamp); } - memset (polypress, 0, sizeof (polypress)); - memset (controller_msb, 0, sizeof (controller_msb)); - memset (controller_lsb, 0, sizeof (controller_lsb)); + memset (_polypress, 0, sizeof (_polypress)); + memset (_controller_msb, 0, sizeof (_controller_msb)); + memset (_controller_lsb, 0, sizeof (_controller_lsb)); /* zero all controllers XXX not necessarily the right thing */ - memset (controller_val, 0, sizeof (controller_val)); + memset (_controller_val, 0, sizeof (_controller_val)); for (int n = 0; n < 128; n++) { - controller_14bit[n] = false; + _controller_14bit[n] = false; } - rpn_msb = 0; - rpn_lsb = 0; - nrpn_msb = 0; - nrpn_lsb = 0; + _rpn_msb = 0; + _rpn_lsb = 0; + _nrpn_msb = 0; + _nrpn_lsb = 0; _omni = true; _poly = false; @@ -155,20 +155,20 @@ Channel::process_controller (Parser &parser, EventTwoBytes *tb) it directly. */ - cv = (unsigned short) controller_val[tb->controller_number]; + cv = (unsigned short) _controller_val[tb->controller_number]; - if (controller_14bit[tb->controller_number]) { + if (_controller_14bit[tb->controller_number]) { cv = ((tb->value << 7) | (cv & 0x7f)); } else { cv = tb->value; } - controller_val[tb->controller_number] = (controller_value_t)cv; + _controller_val[tb->controller_number] = (controller_value_t)cv; } else if ((tb->controller_number >= 32 && tb->controller_number <= 63)) { - cv = (unsigned short) controller_val[tb->controller_number]; + cv = (unsigned short) _controller_val[tb->controller_number]; /* LSB for CC 0-31 arrived. @@ -183,20 +183,20 @@ Channel::process_controller (Parser &parser, EventTwoBytes *tb) int cn = tb->controller_number - 32; - if (controller_14bit[cn] == false) { - controller_14bit[cn] = true; + if (_controller_14bit[cn] == false) { + _controller_14bit[cn] = true; cv = (cv << 7) | (tb->value & 0x7f); } else { cv = (cv & 0x3f80) | (tb->value & 0x7f); } - controller_val[tb->controller_number] = + _controller_val[tb->controller_number] = (controller_value_t) cv; } else { /* controller can only take 7 bit values */ - controller_val[tb->controller_number] = + _controller_val[tb->controller_number] = (controller_value_t) tb->value; } @@ -204,11 +204,11 @@ Channel::process_controller (Parser &parser, EventTwoBytes *tb) */ if (tb->controller_number == 0) { - bank_number = (unsigned short) controller_val[0]; - if (port.input()) { - port.input()->bank_change (*port.input(), bank_number); - port.input()->channel_bank_change[channel_number] - (*port.input(), bank_number); + _bank_number = (unsigned short) _controller_val[0]; + if (_port.input()) { + _port.input()->bank_change (*_port.input(), _bank_number); + _port.input()->channel_bank_change[_channel_number] + (*_port.input(), _bank_number); } } @@ -218,47 +218,47 @@ void Channel::process_program_change (Parser &parser, byte val) { - program_number = val; + _program_number = val; } void Channel::process_chanpress (Parser &parser, byte val) { - chanpress = val; + _chanpress = val; } void Channel::process_polypress (Parser &parser, EventTwoBytes *tb) { - polypress[tb->note_number] = tb->value; + _polypress[tb->note_number] = tb->value; } void Channel::process_pitchbend (Parser &parser, pitchbend_t val) { - pitch_bend = val; + _pitch_bend = val; } void Channel::process_reset (Parser &parser) { - reset (); + reset (0, 1); } /** Write a message to a channel. * \return true if success */ bool -Channel::channel_msg (byte id, byte val1, byte val2) +Channel::channel_msg (byte id, byte val1, byte val2, timestamp_t timestamp) { unsigned char msg[3]; int len = 0; - msg[0] = id | (channel_number & 0xf); + msg[0] = id | (_channel_number & 0xf); switch (id) { case off: @@ -302,5 +302,5 @@ Channel::channel_msg (byte id, byte val1, byte val2) break; } - return port.midimsg (msg, len); + return _port.midimsg (msg, len, timestamp); } diff --git a/libs/midi++2/midicontrollable.cc b/libs/midi++2/midicontrollable.cc index f17782f3c4..24bc381255 100644 --- a/libs/midi++2/midicontrollable.cc +++ b/libs/midi++2/midicontrollable.cc @@ -308,7 +308,7 @@ Controllable::get_control_info (channel_t& chn, eventType& ev, byte& additional) void -Controllable::send_midi_feedback (float val) +Controllable::send_midi_feedback (float val, timestamp_t timestamp) { byte msg[3]; @@ -320,6 +320,6 @@ Controllable::send_midi_feedback (float val) msg[1] = control_additional; msg[2] = (byte) (val * 127.0f); - port->write (msg, 3); + port->write (msg, 3, timestamp); } diff --git a/libs/midi++2/midifactory.cc b/libs/midi++2/midifactory.cc index 38baada204..d8119e362e 100644 --- a/libs/midi++2/midifactory.cc +++ b/libs/midi++2/midifactory.cc @@ -17,11 +17,16 @@ $Id$ */ +#include <cassert> #include <midi++/types.h> #include <midi++/factory.h> #include <midi++/nullmidi.h> #include <midi++/fifomidi.h> +#ifdef WITH_JACK_MIDI +#include <midi++/jack.h> +#endif // WITH_JACK_MIDI + #ifdef WITH_ALSA #include <midi++/alsa_sequencer.h> #include <midi++/alsa_rawmidi.h> @@ -35,13 +40,21 @@ using namespace std; using namespace MIDI; +// FIXME: void* data pointer, filthy Port * -PortFactory::create_port (PortRequest &req) +PortFactory::create_port (PortRequest &req, void* data) { Port *port; switch (req.type) { +#ifdef WITH_JACK_MIDI + case Port::JACK_Midi: + assert(data != NULL); + port = new JACK_MidiPort (req, (jack_client_t*)data); + break; +#endif // WITH_JACK_MIDI + #ifdef WITH_ALSA case Port::ALSA_RawMidi: port = new ALSA_RawMidiPort (req); diff --git a/libs/midi++2/midimanager.cc b/libs/midi++2/midimanager.cc index 7b3ed7d336..bcdcddf7a4 100644 --- a/libs/midi++2/midimanager.cc +++ b/libs/midi++2/midimanager.cc @@ -33,12 +33,8 @@ using namespace MIDI; Manager *Manager::theManager = 0; Manager::Manager () - + : api_data(NULL) { - inputPort = 0; - outputPort = 0; - inputChannelNumber = 0; - outputChannelNumber = 0; } Manager::~Manager () @@ -102,8 +98,7 @@ Manager::add_port (PortRequest &req) /* modes must be different or complementary */ } - - port = factory.create_port (req); + port = factory.create_port (req, api_data); if (port == 0) { return 0; @@ -122,18 +117,6 @@ Manager::add_port (PortRequest &req) newpair.second = port; ports_by_device.insert (newpair); - /* first port added becomes the default input - port. - */ - - if (inputPort == 0) { - inputPort = port; - } - - if (outputPort == 0) { - outputPort = port; - } - return port; } @@ -154,92 +137,6 @@ Manager::remove_port (string name) return 0; } -int -Manager::set_input_port (string tag) -{ - PortMap::iterator res; - bool found = false; - - for (res = ports_by_tag.begin(); res != ports_by_tag.end(); res++) { - if (tag == (*res).first) { - found = true; - break; - } - } - - if (!found) { - return -1; - } - - inputPort = (*res).second; - - return 0; -} - -int -Manager::set_input_port (size_t portnum) - -{ - PortMap::iterator res; - - for (res = ports_by_tag.begin(); res != ports_by_tag.end(); res++) { - if ((*res).second->number() == portnum) { - inputPort = (*res).second; - return 0; - } - } - - return -1; -} - -int -Manager::set_output_port (string tag) - -{ - PortMap::iterator res; - bool found = false; - - for (res = ports_by_tag.begin(); res != ports_by_tag.end(); res++) { - if (tag == (*res).first) { - found = true; - break; - } - } - - if (!found) { - return -1; - } - - // XXX send a signal to say we're about to change output ports - - if (outputPort) { - for (channel_t chan = 0; chan < 16; chan++) { - outputPort->channel (chan)->all_notes_off (); - } - } - outputPort = (*res).second; - - // XXX send a signal to say we've changed output ports - - return 0; -} - -int -Manager::set_output_port (size_t portnum) - -{ - PortMap::iterator res; - - for (res = ports_by_tag.begin(); res != ports_by_tag.end(); res++) { - if ((*res).second->number() == portnum) { - outputPort = (*res).second; - return 0; - } - } - - return -1; -} - Port * Manager::port (string name) { @@ -372,3 +269,20 @@ Manager::parse_port_request (string str, Port::Type type) return 0; } + +void +Manager::cycle_start(nframes_t nframes) +{ + for (PortMap::iterator i = ports_by_device.begin(); + i != ports_by_device.end(); i++) + (*i).second->cycle_start(nframes); +} + +void +Manager::cycle_end() +{ + for (PortMap::iterator i = ports_by_device.begin(); + i != ports_by_device.end(); i++) + (*i).second->cycle_end(); +} + diff --git a/libs/midi++2/midiport.cc b/libs/midi++2/midiport.cc index a7c4ba0940..7f31b909d3 100644 --- a/libs/midi++2/midiport.cc +++ b/libs/midi++2/midiport.cc @@ -32,7 +32,8 @@ using namespace MIDI; size_t Port::nports = 0; Port::Port (PortRequest &req) - + : _currently_in_cycle(false) + , _nframes_this_cycle(0) { _ok = false; /* derived class must set to true if constructor succeeds. @@ -87,48 +88,28 @@ Port::~Port () * \return true on success. */ bool -Port::clock () - +Port::clock (timestamp_t timestamp) { static byte clockmsg = 0xf8; if (_mode != O_RDONLY) { - return midimsg (&clockmsg, 1); + return midimsg (&clockmsg, 1, timestamp); } return false; } void -Port::selector_read_callback (Selectable *s, Select::Condition cond) - -{ - byte buf[64]; - read (buf, sizeof (buf)); -} - -void -Port::xforms_read_callback (int cond, int fd, void *ptr) - -{ - byte buf[64]; - - ((Port *)ptr)->read (buf, sizeof (buf)); -} - -void -Port::gtk_read_callback (void *ptr, int fd, int cond) - +Port::cycle_start (nframes_t nframes) { - byte buf[64]; - - ((Port *)ptr)->read (buf, sizeof (buf)); + _currently_in_cycle = true; + _nframes_this_cycle = nframes; } void -Port::write_callback (byte *msg, unsigned int len, void *ptr) - +Port::cycle_end () { - ((Port *)ptr)->write (msg, len); + _currently_in_cycle = false; + _nframes_this_cycle = 0; } diff --git a/libs/midi++2/port_request.cc b/libs/midi++2/port_request.cc index d081bdb570..d209f02574 100644 --- a/libs/midi++2/port_request.cc +++ b/libs/midi++2/port_request.cc @@ -36,7 +36,7 @@ PortRequest::PortRequest (const string &xdev, devname = strdup (xdev.c_str()); tagname = strdup (xtag.c_str()); - + if (xmode == "output" || xmode == "out" || xmode == "OUTPUT" || @@ -58,7 +58,10 @@ PortRequest::PortRequest (const string &xdev, status = Unknown; } - if (xtype == "ALSA/RAW" || + if (xtype == "JACK" || + xtype == "jack") { + type = Port::JACK_Midi; + } else if (xtype == "ALSA/RAW" || xtype == "alsa/raw") { type = Port::ALSA_RawMidi; } else if (xtype == "ALSA/SEQUENCER" || |