func (s *SystemPort) Open() error { if s.isOpen && s.stream == nil { return errors.New("Underlying portmidi port is already opened, " + "but stream is not connected to this SystemPort.") } if s.id == -1 || s.isOpen { // Fake port or opened already, ignore. return nil } var errNum C.PmError if s.IsInputPort { // The input / output naming LOOKS backwards, but we're opening a // portmidi "output stream" for input Ports and vice versa. errNum = C.Pm_OpenOutput(&(s.stream), C.PmDeviceID(s.id), nil, C.int32_t(512), nil, nil, 0) } else { errNum = C.Pm_OpenInput(&(s.stream), C.PmDeviceID(s.id), nil, C.int32_t(512), nil, nil) } if errNum == 0 { s.isOpen = true s.stop = make(chan bool, 1) s.noteOns = make(chan Note, BufferSize) s.noteOffs = make(chan Note, BufferSize) s.controlChanges = make(chan ControlChange, BufferSize) } return makePortMidiError(errNum) }
func getSystemDevices() (inputs, outputs []SystemDevice) { numDevices := int(C.Pm_CountDevices()) for i := 0; i < numDevices; i++ { info := C.Pm_GetDeviceInfo(C.PmDeviceID(i)) name := C.GoString(info.name) var isInputPort, isOutputPort, isOpen bool if info.output > 0 { // "output" means "output stream" in portmidi-speak. isInputPort = true // An OUTPUT stream is for an INPUT port. } if info.input > 0 { // "input" means "input stream" in portmidi-speak. isOutputPort = true // An INPUT stream is for an OUTPUT port. } if info.opened > 0 { isOpen = true } port := &SystemPort{isOpen: isOpen, id: i, IsInputPort: isInputPort} device := SystemDevice{Name: name} if isInputPort { device.inPort = port device.outPort = &SystemPort{isOpen: false, id: -1} inputs = append(inputs, device) } else if isOutputPort { device.outPort = port device.inPort = &SystemPort{isOpen: false, id: -1} outputs = append(outputs, device) } } return inputs, outputs }
// Returns the device info for the device indentified with deviceId. func GetDeviceInfo(deviceId DeviceID) *DeviceInfo { info := C.Pm_GetDeviceInfo(C.PmDeviceID(deviceId)) return &DeviceInfo{ Interface: C.GoString(info.interf), Name: C.GoString(info.name), IsInputAvailable: info.input > 0, IsOutputAvailable: info.output > 0, IsOpened: info.opened > 0, } }
// Initializes a new output stream. func NewOutputStream(deviceId DeviceId, bufferSize int64, latency int64) (stream *Stream, err error) { var str *C.PmStream errCode := C.Pm_OpenOutput( (*unsafe.Pointer)(unsafe.Pointer(&str)), C.PmDeviceID(deviceId), nil, C.int32_t(bufferSize), nil, nil, C.int32_t(latency)) if errCode != 0 { return nil, convertToError(errCode) } return &Stream{deviceId: deviceId, pmStream: str}, nil }
// NewOutputStream initializes a new output stream. func NewOutputStream(id DeviceID, bufferSize int64, latency int64) (stream *Stream, err error) { var str *C.PmStream errCode := C.Pm_OpenOutput( (*unsafe.Pointer)(unsafe.Pointer(&str)), C.PmDeviceID(id), nil, C.int32_t(bufferSize), nil, nil, C.int32_t(latency)) if errCode != 0 { return nil, convertToError(errCode) } if info := Info(id); !info.IsOutputAvailable { return nil, ErrOutputUnavailable } return &Stream{deviceID: id, pmStream: str}, nil }
// Initializes a new input stream. func NewInputStream(deviceId DeviceID, bufferSize int64) (stream *Stream, err error) { var str *C.PmStream errCode := C.Pm_OpenInput( (*unsafe.Pointer)(unsafe.Pointer(&str)), C.PmDeviceID(deviceId), nil, C.int32_t(bufferSize), nil, nil) if errCode != 0 { return nil, convertToError(errCode) } if info := GetDeviceInfo(deviceId); !info.IsInputAvailable { return nil, ErrInputUnavailable } return &Stream{deviceId: deviceId, pmStream: str}, nil }