drivers

package
v2.1.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 8, 2024 License: MIT Imports: 3 Imported by: 39

README

Drivers for gomidi

All drivers must obey the following rules. If not, it is considered a bug.

  1. Implement the midi.Driver, midi.In and midi.Out interfaces
  2. Autoregister via midi.RegisterDriver(drv) within init function
  3. The String() method must return a unique and indentifying string
  4. The driver expects multiple goroutines to use its writing and reading methods and locks accordingly (to be threadsafe).
  5. The midi.In ports respects any running status bytes when converting to midi.Message(s)
  6. The midi.Out ports accept running status bytes.
  7. The New function may take optional driver specific arguments. These are all organized as functional optional arguments.
  8. The midi.In port is responsible for buffering of sysex data. Only complete sysex data is passed to the listener.
  9. The midi In port must check the ListenConfig and act accordingly.
  10. incomplete sysex data must be cached inside the sender and flushed, if the data is complete.

Reason for the timestamp choice of the listener callback

  1. we don't want floating point, but integers of small fractions of time (easier to calculate with).
  2. not every driver tracks a delta timing. the ones that don't should indicate with a -1. also some underlying drivers use floats for delta timing, so we can't be sure to don't get negative values.
  3. for the size, we find that int32 is large enough, if we take a reasonable resolution of 1 millisecond. Then we get max int32 = 2147483647 / 10 (ms) / 1000 (sec) / 60 (min) / 60 (hours) / 24 = 2,48 days of maximal duration when converting to absolute timing (starting from the first message), which should be long enough for a midi recording. int64 would double the needed ressources for no real benefit.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrListenStopped = fmt.Errorf("ERROR: stopped listening")
View Source
var ErrPortClosed = fmt.Errorf("ERROR: port is closed")
View Source
var (

	// REGISTRY is the registry for MIDI drivers
	REGISTRY = map[string]Driver{}
)

Functions

func Close

func Close()

Close closes the first available driver

func Register

func Register(d Driver)

RegisterDriver register a driver

Types

type Driver

type Driver interface {

	// Ins returns the available MIDI input ports.
	Ins() ([]In, error)

	// Outs returns the available MIDI output ports.
	Outs() ([]Out, error)

	// String returns the name of the driver.
	String() string

	// Close closes the driver. Must be called for cleanup at the end of a session.
	Close() error
}

Driver is a driver for MIDI connections. It may provide the timing delta to the previous message in micro seconds. It must send the given MIDI data immediately.

func Get

func Get() Driver

Get returns the first available driver

type In

type In interface {
	Port

	// Listen listens for incoming messages. It returns a function that must be used to stop listening.
	// The onMsg callback is called for every non-sysex message. The onMsg callback must not be nil.
	// The config defines further listening options (see ListenConfig)
	// The listening must be stopped before the port may be closed.
	Listen(
		onMsg func(msg []byte, milliseconds int32),
		config ListenConfig,
	) (
		stopFn func(),
		err error,
	)
}

In is an interface for a MIDI input port

func InByName

func InByName(portName string) (in In, err error)

InByName opens the first midi in port that contains the given name

func InByNumber

func InByNumber(portNumber int) (in In, err error)

InByNumber opens the midi in port with the given number

func Ins

func Ins() ([]In, error)

Ins return the available MIDI in ports

type ListenConfig

type ListenConfig struct {

	// TimeCode lets the timecode messages pass through, if set
	TimeCode bool

	// ActiveSense lets the active sense messages pass through, if set
	ActiveSense bool

	// SysEx lets the sysex messaes pass through, if set
	SysEx bool

	// SysExBufferSize defines the size of the buffer for sysex messages (in bytes).
	// SysEx messages larger than this size will be ignored.
	// When SysExBufferSize is 0, the default buffersize (1024) is used.
	SysExBufferSize uint32

	// OnErr is the callback that is called for any error happening during the listening.
	OnErr func(error)
}

ListenConfig defines the configuration for in port listening

type Out

type Out interface {
	Port

	//Send(data [3]byte) error
	Send(data []byte) error
}

Out is an interface for a MIDI output port.

func OutByName

func OutByName(portName string) (out Out, err error)

OutByName opens the first midi out port that contains the given name

func OutByNumber

func OutByNumber(portNumber int) (out Out, err error)

OutByNumber opens the midi out port with the given number

func Outs

func Outs() ([]Out, error)

Outs return the available MIDI out ports

type Port

type Port interface {

	// Open opens the MIDI port. An implementation should save the open state to make it
	// save to call open when the port is already open without getting an error.
	Open() error

	// Close closes the MIDI port. An implementation should save the open state to make it
	// save to call close when the port is already closed without getting an error.
	Close() error

	// IsOpen returns wether the MIDI port is open.
	IsOpen() bool

	// Number returns the number of the MIDI port. It is only guaranteed that the numbers are unique within
	// MIDI port groups i.e. within MIDI input ports and MIDI output ports. So there may be the same number
	// for a given MIDI input port and some MIDI output port. Or not - that depends on the underlying driver.
	Number() int

	// String represents the MIDI port by a string, aka name.
	String() string

	// Underlying returns the underlying implementation of the driver
	Underlying() interface{}
}

Port is an interface for a MIDI port. In order to be lockless (for realtime), a port is not threadsafe, so none of its method may be called from different goroutines.

type Reader

type Reader struct {
	SysExBufferSize uint32
	OnMsg           func([]byte, int32)
	HandleSysex     bool
	OnErr           func(error)
	// contains filtered or unexported fields
}

func NewReader

func NewReader(config ListenConfig, onMsg func([]byte, int32)) *Reader

func (*Reader) EachMessage

func (r *Reader) EachMessage(bt []byte, deltaMilliSeconds int32)

func (r *Reader) EachMessage(bt []byte, deltaSeconds float64) {

func (*Reader) Reset

func (r *Reader) Reset()

Directories

Path Synopsis
internal
Package midicatdrv provides a Driver to connect via the program midicat (from the tools).
Package midicatdrv provides a Driver to connect via the program midicat (from the tools).
Package portmididrv provides an Driver to connect via portmidi.
Package portmididrv provides an Driver to connect via portmidi.
imported/portmidi
Package portmidi provides PortMidi bindings.
Package portmidi provides PortMidi bindings.
Package rtmididrv provides a Driver to connect via rtmidi.
Package rtmididrv provides a Driver to connect via rtmidi.
Package testdrv provides a Driver for testing.
Package testdrv provides a Driver for testing.
Package webmididrv provides a Driver to connect to MIDI ports in the browser (via webmidi).
Package webmididrv provides a Driver to connect to MIDI ports in the browser (via webmidi).
example Module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL