diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2012-04-24 02:28:51 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2012-04-24 02:28:51 +0000 |
commit | 33140f32671576a285d62f529447f941f96313fc (patch) | |
tree | 44faee5b21e3181077d0c22180895fb072432a53 /libs/midi++2/midi++ | |
parent | 10d37fecc1b54487a5fb0f3652bfb45a5224ef8b (diff) |
add support for IP MIDI (multicast MIDI over IP UDP sockets) to ardour and use it if requested inside MCP code. required renaming the pre-existing MIDI::Port as MIDI:JackMIDIPort - MIDI::Port becomes the base type for both JackMIDIPort and IPMIDIPort
git-svn-id: svn://localhost/ardour2/branches/3.0@12069 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/midi++2/midi++')
-rw-r--r-- | libs/midi++2/midi++/channel.h | 8 | ||||
-rw-r--r-- | libs/midi++2/midi++/ipmidi_port.h | 76 | ||||
-rw-r--r-- | libs/midi++2/midi++/jack_midi_port.h | 103 | ||||
-rw-r--r-- | libs/midi++2/midi++/manager.h | 12 | ||||
-rw-r--r-- | libs/midi++2/midi++/parser.h | 8 | ||||
-rw-r--r-- | libs/midi++2/midi++/port.h | 145 | ||||
-rw-r--r-- | libs/midi++2/midi++/port_base.h | 158 |
7 files changed, 294 insertions, 216 deletions
diff --git a/libs/midi++2/midi++/channel.h b/libs/midi++2/midi++/channel.h index 370a569156..d00ce700c5 100644 --- a/libs/midi++2/midi++/channel.h +++ b/libs/midi++2/midi++/channel.h @@ -39,9 +39,9 @@ class Port; class Channel : public PBD::ScopedConnectionList { public: - Channel (byte channel_number, PortBase &); + Channel (byte channel_number, Port &); - PortBase &midi_port() { return _port; } + Port &midi_port() { return _port; } byte channel() { return _channel_number; } byte program() { return _program_number; } byte bank() { return _bank_number; } @@ -111,11 +111,11 @@ class Channel : public PBD::ScopedConnectionList { } protected: - friend class PortBase; + friend class Port; void connect_signals (); private: - PortBase& _port; + Port& _port; /* Current channel values */ byte _channel_number; diff --git a/libs/midi++2/midi++/ipmidi_port.h b/libs/midi++2/midi++/ipmidi_port.h new file mode 100644 index 0000000000..bf949bd601 --- /dev/null +++ b/libs/midi++2/midi++/ipmidi_port.h @@ -0,0 +1,76 @@ +/* + Copyright (C) 1998-2010 Paul Barton-Davis + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __libmidi_ipmidi_port_h__ +#define __libmidi_ipmidi_port_h__ + +#include <string> +#include <iostream> +#if defined(WIN32) +#include <winsock.h> +#else +#include <arpa/inet.h> +#include <net/if.h> +#endif + +#include <jack/types.h> + +#include "pbd/xml++.h" +#include "pbd/crossthread.h" +#include "pbd/signals.h" +#include "pbd/ringbuffer.h" + +#include "evoral/Event.hpp" +#include "evoral/EventRingBuffer.hpp" + +#include "midi++/types.h" +#include "midi++/parser.h" +#include "midi++/port.h" + +namespace MIDI { + +class IPMIDIPort : public Port { + public: + IPMIDIPort (int base_port = lowest_ipmidi_port_default, const std::string& ifname = std::string()); + IPMIDIPort (const XMLNode&); + ~IPMIDIPort (); + + XMLNode& get_state () const; + void set_state (const XMLNode&); + + int write (byte *msg, size_t msglen, timestamp_t timestamp); + int read (byte *buf, size_t bufsize); + void parse (framecnt_t timestamp); + int selectable () const; + + static const int lowest_ipmidi_port_default = 21928; + +private: + int sockin; + int sockout; + struct sockaddr_in addrout; + + bool open_sockets (int base_port, const std::string& ifname); + void close_sockets (); + + void init (std::string const &, Flags); +}; + +} // namespace MIDI + +#endif // __libmidi_ipmidi_port_h__ diff --git a/libs/midi++2/midi++/jack_midi_port.h b/libs/midi++2/midi++/jack_midi_port.h new file mode 100644 index 0000000000..e381120a99 --- /dev/null +++ b/libs/midi++2/midi++/jack_midi_port.h @@ -0,0 +1,103 @@ +/* + Copyright (C) 1998-2010 Paul Barton-Davis + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __libmidi_port_h__ +#define __libmidi_port_h__ + +#include <string> +#include <iostream> + +#include <jack/types.h> + +#include "pbd/xml++.h" +#include "pbd/crossthread.h" +#include "pbd/signals.h" +#include "pbd/ringbuffer.h" + +#include "evoral/Event.hpp" +#include "evoral/EventRingBuffer.hpp" + +#include "midi++/types.h" +#include "midi++/parser.h" +#include "midi++/port.h" + +namespace MIDI { + +class Channel; +class PortRequest; + +class JackMIDIPort : public Port { + public: + JackMIDIPort (std::string const &, Port::Flags, jack_client_t *); + JackMIDIPort (const XMLNode&, jack_client_t *); + ~JackMIDIPort (); + + XMLNode& get_state () const; + void set_state (const XMLNode&); + + void cycle_start (pframes_t nframes); + void cycle_end (); + + void parse (framecnt_t timestamp); + int write (byte *msg, size_t msglen, timestamp_t timestamp); + int read (byte *buf, size_t bufsize); + void drain (int check_interval_usecs); + int selectable () const { return xthread.selectable(); } + + pframes_t nframes_this_cycle() const { return _nframes_this_cycle; } + + void reestablish (jack_client_t *); + void reconnect (); + + static void set_process_thread (pthread_t); + static pthread_t get_process_thread () { return _process_thread; } + static bool is_process_thread(); + + static PBD::Signal0<void> MakeConnections; + static PBD::Signal0<void> JackHalted; + +private: + bool _currently_in_cycle; + pframes_t _nframes_this_cycle; + jack_client_t* _jack_client; + jack_port_t* _jack_port; + timestamp_t _last_write_timestamp; + RingBuffer< Evoral::Event<double> > output_fifo; + Evoral::EventRingBuffer<timestamp_t> input_fifo; + Glib::Mutex output_fifo_lock; + CrossThreadChannel xthread; + + int create_port (); + + /** Channel used to signal to the MidiControlUI that input has arrived */ + + std::string _connections; + PBD::ScopedConnection connect_connection; + PBD::ScopedConnection halt_connection; + void flush (void* jack_port_buffer); + void jack_halted (); + void make_connections (); + void init (std::string const &, Flags); + + static pthread_t _process_thread; + +}; + +} // namespace MIDI + +#endif // __libmidi_port_h__ diff --git a/libs/midi++2/midi++/manager.h b/libs/midi++2/midi++/manager.h index bab4a18dd2..c37ba392b4 100644 --- a/libs/midi++2/midi++/manager.h +++ b/libs/midi++2/midi++/manager.h @@ -88,12 +88,12 @@ class Manager { static Manager *theManager; MIDI::MachineControl* _mmc; - MIDI::Port* _mtc_input_port; - MIDI::Port* _mtc_output_port; - MIDI::Port* _midi_input_port; - MIDI::Port* _midi_output_port; - MIDI::Port* _midi_clock_input_port; - MIDI::Port* _midi_clock_output_port; + MIDI::Port* _mtc_input_port; + MIDI::Port* _mtc_output_port; + MIDI::Port* _midi_input_port; + MIDI::Port* _midi_output_port; + MIDI::Port* _midi_clock_input_port; + MIDI::Port* _midi_clock_output_port; SerializedRCUManager<PortList> _ports; }; diff --git a/libs/midi++2/midi++/parser.h b/libs/midi++2/midi++/parser.h index ac452798cc..f5f343e952 100644 --- a/libs/midi++2/midi++/parser.h +++ b/libs/midi++2/midi++/parser.h @@ -29,7 +29,7 @@ namespace MIDI { -class PortBase; +class Port; class Parser; typedef PBD::Signal1<void,Parser&> ZeroByteSignal; @@ -41,7 +41,7 @@ typedef PBD::Signal3<void,Parser &, byte *, size_t> Signal; class Parser { public: - Parser (PortBase &p); + Parser (Port &p); ~Parser (); /* sets the time that will be reported for any MTC or MIDI Clock @@ -105,7 +105,7 @@ class Parser { const char *midi_event_type_name (MIDI::eventType); void trace (bool onoff, std::ostream *o, const std::string &prefix = ""); bool tracing() { return trace_stream != 0; } - PortBase &port() { return _port; } + Port &port() { return _port; } void set_offline (bool); bool offline() const { return _offline; } @@ -136,7 +136,7 @@ class Parser { void reset_mtc_state (); private: - PortBase&_port; + Port&_port; /* tracing */ std::ostream *trace_stream; diff --git a/libs/midi++2/midi++/port.h b/libs/midi++2/midi++/port.h index e7b532013e..a2315f7284 100644 --- a/libs/midi++2/midi++/port.h +++ b/libs/midi++2/midi++/port.h @@ -16,8 +16,8 @@ */ -#ifndef __libmidi_port_h__ -#define __libmidi_port_h__ +#ifndef __libmidi_port_base_h__ +#define __libmidi_port_base_h__ #include <string> #include <iostream> @@ -34,70 +34,127 @@ #include "midi++/types.h" #include "midi++/parser.h" -#include "midi++/port_base.h" namespace MIDI { class Channel; class PortRequest; -class Port : public PortBase { +class Port { public: - Port (std::string const &, PortBase::Flags, jack_client_t *); - Port (const XMLNode&, jack_client_t *); - ~Port (); + enum Flags { + IsInput = JackPortIsInput, + IsOutput = JackPortIsOutput, + }; + + Port (std::string const &, Flags); + Port (const XMLNode&); + virtual ~Port (); XMLNode& get_state () const; void set_state (const XMLNode&); - void cycle_start (pframes_t nframes); - void cycle_end (); + // 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 (pframes_t nframes) {} + /* Only for use by MidiManager. Don't ever call this. */ + virtual void cycle_end () {} + + /** 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; + + /** Read raw bytes from a port. + * @param buf memory to store read data in + * @param bufsize size of @a buf + * @return number of bytes successfully read, negative if error + */ + virtual int read (byte *buf, size_t bufsize) = 0; + + /** block until the output FIFO used by non-process threads + * is empty, checking every @a check_interval_usecs usecs + * for current status. Not to be called by a thread that + * executes any part of a JACK process callback (will + * simply return immediately in that situation). + */ + virtual void drain (int check_interval_usecs) {} + + /** Write a message to port. + * @return true on success. + * FIXME: describe semantics here + */ + int midimsg (byte *msg, size_t len, timestamp_t timestamp) { + return !(write (msg, len, timestamp) == (int) len); + } + + virtual void parse (framecnt_t timestamp) = 0; + + bool clock (timestamp_t timestamp); + + /* 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; + + Channel *channel (channel_t chn) { + return _channel[chn&0x7F]; + } + + Parser* parser () { + return _parser; + } + + const char *name () const { return _tagname.c_str(); } + bool ok () const { return _ok; } - void parse (framecnt_t timestamp); - int write (byte *msg, size_t msglen, timestamp_t timestamp); - int read (byte *buf, size_t bufsize); - void drain (int check_interval_usecs); - int selectable () const { return xthread.selectable(); } + virtual bool centrally_parsed() const; + void set_centrally_parsed (bool yn) { _centrally_parsed = yn; } - pframes_t nframes_this_cycle() const { return _nframes_this_cycle; } + bool receives_input () const { + return _flags == IsInput; + } - void reestablish (jack_client_t *); - void reconnect (); + bool sends_output () const { + return _flags == IsOutput; + } - static void set_process_thread (pthread_t); - static pthread_t get_process_thread () { return _process_thread; } - static bool is_process_thread(); + struct Descriptor { + std::string tag; + Flags flags; - static PBD::Signal0<void> MakeConnections; - static PBD::Signal0<void> JackHalted; + Descriptor (const XMLNode&); + XMLNode& get_state(); + }; -private: - bool _currently_in_cycle; - pframes_t _nframes_this_cycle; - jack_client_t* _jack_client; - jack_port_t* _jack_port; - timestamp_t _last_write_timestamp; - RingBuffer< Evoral::Event<double> > output_fifo; - Evoral::EventRingBuffer<timestamp_t> input_fifo; - Glib::Mutex output_fifo_lock; - CrossThreadChannel xthread; + static std::string state_node_name; - int create_port (); + protected: + bool _ok; + std::string _tagname; + Channel* _channel[16]; + Parser* _parser; + Flags _flags; + bool _centrally_parsed; - /** Channel used to signal to the MidiControlUI that input has arrived */ - - std::string _connections; - PBD::ScopedConnection connect_connection; - PBD::ScopedConnection halt_connection; - void flush (void* jack_port_buffer); - void jack_halted (); - void make_connections (); void init (std::string const &, Flags); +}; - static pthread_t _process_thread; - +struct PortSet { + PortSet (std::string str) : owner (str) { } + + std::string owner; + std::list<XMLNode> ports; }; +std::ostream & operator << (std::ostream& os, const Port& port); + } // namespace MIDI -#endif // __libmidi_port_h__ +#endif // __libmidi_port_base_h__ diff --git a/libs/midi++2/midi++/port_base.h b/libs/midi++2/midi++/port_base.h deleted file mode 100644 index f1649d84ba..0000000000 --- a/libs/midi++2/midi++/port_base.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - Copyright (C) 1998-2010 Paul Barton-Davis - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#ifndef __libmidi_port_base_h__ -#define __libmidi_port_base_h__ - -#include <string> -#include <iostream> - -#include <jack/types.h> - -#include "pbd/xml++.h" -#include "pbd/crossthread.h" -#include "pbd/signals.h" -#include "pbd/ringbuffer.h" - -#include "evoral/Event.hpp" -#include "evoral/EventRingBuffer.hpp" - -#include "midi++/types.h" -#include "midi++/parser.h" - -namespace MIDI { - -class Channel; -class PortRequest; - -class PortBase { - public: - enum Flags { - IsInput = JackPortIsInput, - IsOutput = JackPortIsOutput, - }; - - PortBase (std::string const &, Flags); - PortBase (const XMLNode&); - virtual ~PortBase (); - - XMLNode& get_state () const; - void set_state (const XMLNode&); - - // 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 (pframes_t nframes) {} - /* Only for use by MidiManager. Don't ever call this. */ - virtual void cycle_end () {} - - /** 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; - - /** Read raw bytes from a port. - * @param buf memory to store read data in - * @param bufsize size of @a buf - * @return number of bytes successfully read, negative if error - */ - virtual int read (byte *buf, size_t bufsize) = 0; - - /** block until the output FIFO used by non-process threads - * is empty, checking every @a check_interval_usecs usecs - * for current status. Not to be called by a thread that - * executes any part of a JACK process callback (will - * simply return immediately in that situation). - */ - virtual void drain (int check_interval_usecs) {} - - /** Write a message to port. - * @return true on success. - * FIXME: describe semantics here - */ - int midimsg (byte *msg, size_t len, timestamp_t timestamp) { - return !(write (msg, len, timestamp) == (int) len); - } - - bool clock (timestamp_t timestamp); - - /* 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; - - Channel *channel (channel_t chn) { - return _channel[chn&0x7F]; - } - - Parser* parser () { - return _parser; - } - - const char *name () const { return _tagname.c_str(); } - bool ok () const { return _ok; } - - virtual bool centrally_parsed() const; - void set_centrally_parsed (bool yn) { _centrally_parsed = yn; } - - bool receives_input () const { - return _flags == IsInput; - } - - bool sends_output () const { - return _flags == IsOutput; - } - - struct Descriptor { - std::string tag; - Flags flags; - - Descriptor (const XMLNode&); - XMLNode& get_state(); - }; - - static std::string state_node_name; - - protected: - bool _ok; - std::string _tagname; - Channel* _channel[16]; - Parser* _parser; - Flags _flags; - bool _centrally_parsed; - - void init (std::string const &, Flags); -}; - -struct PortSet { - PortSet (std::string str) : owner (str) { } - - std::string owner; - std::list<XMLNode> ports; -}; - -std::ostream & operator << (std::ostream& os, const PortBase& port); - -} // namespace MIDI - -#endif // __libmidi_port_base_h__ |