mirror of
https://github.com/vsariola/sointu.git
synced 2026-02-05 07:10:28 -05:00
refactor(tracker): use strings to identify MIDI ports
This commit is contained in:
parent
651ceb3cbb
commit
173648fbdb
@ -620,16 +620,16 @@ func (m *Model) ShowLicense() Action { return MakeAction((*showLicense)(m)) }
|
||||
func (m *showLicense) Do() { m.dialog = License }
|
||||
|
||||
type selectMidiInput struct {
|
||||
Item MIDIDevice
|
||||
Item string
|
||||
*Model
|
||||
}
|
||||
|
||||
func (m *Model) SelectMidiInput(item MIDIDevice) Action {
|
||||
func (m *Model) SelectMidiInput(item string) Action {
|
||||
return MakeAction(selectMidiInput{Item: item, Model: m})
|
||||
}
|
||||
func (s selectMidiInput) Do() {
|
||||
m := s.Model
|
||||
if err := s.Item.Open(); err == nil {
|
||||
if err := s.Model.MIDI.Open(s.Item); err == nil {
|
||||
message := fmt.Sprintf("Opened MIDI device: %s", s.Item)
|
||||
m.Alerts().Add(message, Info)
|
||||
} else {
|
||||
|
||||
@ -480,7 +480,7 @@ func NewMenuBar(tr *Tracker) *MenuBar {
|
||||
}
|
||||
for input := range tr.MIDI.InputDevices {
|
||||
ret.midiMenuItems = append(ret.midiMenuItems,
|
||||
MenuItem(tr.SelectMidiInput(input), input.String(), "", icons.ImageControlPoint),
|
||||
MenuItem(tr.SelectMidiInput(input), input, "", icons.ImageControlPoint),
|
||||
)
|
||||
}
|
||||
return ret
|
||||
|
||||
@ -9,7 +9,6 @@ import "C"
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/vsariola/sointu/tracker"
|
||||
"gitlab.com/gomidi/midi/v2"
|
||||
@ -23,14 +22,9 @@ type (
|
||||
currentIn drivers.In
|
||||
broker *tracker.Broker
|
||||
}
|
||||
|
||||
RTMIDIDevice struct {
|
||||
context *RTMIDIContext
|
||||
in drivers.In
|
||||
}
|
||||
)
|
||||
|
||||
func (m *RTMIDIContext) InputDevices(yield func(tracker.MIDIDevice) bool) {
|
||||
func (m *RTMIDIContext) InputDevices(yield func(string) bool) {
|
||||
if m.driver == nil {
|
||||
return
|
||||
}
|
||||
@ -38,9 +32,8 @@ func (m *RTMIDIContext) InputDevices(yield func(tracker.MIDIDevice) bool) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for i := 0; i < len(ins); i++ {
|
||||
device := RTMIDIDevice{context: m, in: ins[i]}
|
||||
if !yield(device) {
|
||||
for _, in := range ins {
|
||||
if !yield(in.String()) {
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -56,34 +49,43 @@ func NewContext(broker *tracker.Broker) *RTMIDIContext {
|
||||
}
|
||||
|
||||
// Open an input device while closing the currently open if necessary.
|
||||
func (m RTMIDIDevice) Open() error {
|
||||
if m.context.currentIn == m.in {
|
||||
func (m *RTMIDIContext) Open(name string) error {
|
||||
if m.currentIn != nil && m.currentIn.String() == name {
|
||||
return nil
|
||||
}
|
||||
if m.context.driver == nil {
|
||||
if m.driver == nil {
|
||||
return errors.New("no driver available")
|
||||
}
|
||||
if m.context.HasDeviceOpen() {
|
||||
m.context.currentIn.Close()
|
||||
if m.IsOpen() {
|
||||
m.currentIn.Close()
|
||||
}
|
||||
m.context.currentIn = m.in
|
||||
err := m.in.Open()
|
||||
m.currentIn = nil
|
||||
ins, err := m.driver.Ins()
|
||||
if err != nil {
|
||||
m.context.currentIn = nil
|
||||
return fmt.Errorf("opening MIDI input failed: %W", err)
|
||||
return fmt.Errorf("retrieving MIDI inputs failed: %w", err)
|
||||
}
|
||||
_, err = midi.ListenTo(m.in, m.context.HandleMessage)
|
||||
for _, in := range ins {
|
||||
if in.String() == name {
|
||||
m.currentIn = in
|
||||
}
|
||||
}
|
||||
if m.currentIn == nil {
|
||||
return fmt.Errorf("MIDI input device not found: %s", name)
|
||||
}
|
||||
err = m.currentIn.Open()
|
||||
if err != nil {
|
||||
m.in.Close()
|
||||
m.context.currentIn = nil
|
||||
m.currentIn = nil
|
||||
return fmt.Errorf("opening MIDI input failed: %w", err)
|
||||
}
|
||||
_, err = midi.ListenTo(m.currentIn, m.HandleMessage)
|
||||
if err != nil {
|
||||
m.currentIn.Close()
|
||||
m.currentIn = nil
|
||||
return fmt.Errorf("listening to MIDI input failed: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d RTMIDIDevice) String() string {
|
||||
return d.in.String()
|
||||
}
|
||||
|
||||
func (m *RTMIDIContext) HandleMessage(msg midi.Message, timestampms int32) {
|
||||
var channel, key, velocity uint8
|
||||
if msg.GetNoteOn(&channel, &key, &velocity) {
|
||||
@ -109,23 +111,6 @@ func (c *RTMIDIContext) Close() {
|
||||
c.driver.Close()
|
||||
}
|
||||
|
||||
func (c *RTMIDIContext) HasDeviceOpen() bool {
|
||||
func (c *RTMIDIContext) IsOpen() bool {
|
||||
return c.currentIn != nil && c.currentIn.IsOpen()
|
||||
}
|
||||
|
||||
func (c *RTMIDIContext) TryToOpenBy(namePrefix string, takeFirst bool) {
|
||||
if namePrefix == "" && !takeFirst {
|
||||
return
|
||||
}
|
||||
for input := range c.InputDevices {
|
||||
if takeFirst || strings.HasPrefix(input.String(), namePrefix) {
|
||||
input.Open()
|
||||
return
|
||||
}
|
||||
}
|
||||
if takeFirst {
|
||||
fmt.Errorf("Could not find any MIDI Input.\n")
|
||||
} else {
|
||||
fmt.Errorf("Could not find any default MIDI Input starting with \"%s\".\n", namePrefix)
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/vsariola/sointu"
|
||||
)
|
||||
@ -126,19 +127,14 @@ type (
|
||||
Dialog int
|
||||
|
||||
MIDIContext interface {
|
||||
InputDevices(yield func(MIDIDevice) bool)
|
||||
InputDevices(yield func(string) bool)
|
||||
Open(name string) error
|
||||
Close()
|
||||
HasDeviceOpen() bool
|
||||
TryToOpenBy(name string, first bool)
|
||||
IsOpen() bool
|
||||
}
|
||||
|
||||
NullMIDIContext struct{}
|
||||
|
||||
MIDIDevice interface {
|
||||
String() string
|
||||
Open() error
|
||||
}
|
||||
|
||||
InstrumentTab int
|
||||
)
|
||||
|
||||
@ -221,6 +217,15 @@ func NewModel(broker *Broker, synthers []sointu.Synther, midiContext MIDIContext
|
||||
return m
|
||||
}
|
||||
|
||||
func FindMIDIDeviceByPrefix(c MIDIContext, prefix string) (input string, ok bool) {
|
||||
for input := range c.InputDevices {
|
||||
if strings.HasPrefix(input, prefix) {
|
||||
return input, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func (m *Model) change(kind string, t ChangeType, severity ChangeSeverity) func() {
|
||||
if m.changeLevel == 0 {
|
||||
m.changeType = NoChange
|
||||
@ -434,10 +439,10 @@ func (d *modelData) Copy() modelData {
|
||||
return ret
|
||||
}
|
||||
|
||||
func (m NullMIDIContext) InputDevices(yield func(MIDIDevice) bool) {}
|
||||
func (m NullMIDIContext) Close() {}
|
||||
func (m NullMIDIContext) HasDeviceOpen() bool { return false }
|
||||
func (m NullMIDIContext) TryToOpenBy(name string, first bool) {}
|
||||
func (m NullMIDIContext) InputDevices(yield func(string) bool) {}
|
||||
func (m NullMIDIContext) Open(name string) error { return nil }
|
||||
func (m NullMIDIContext) Close() {}
|
||||
func (m NullMIDIContext) IsOpen() bool { return false }
|
||||
|
||||
func (m *Model) resetSong() {
|
||||
m.d.Song = defaultSong.Copy()
|
||||
|
||||
Reference in New Issue
Block a user