diff options
author | Christian Pointner <equinox@spreadspace.org> | 2019-02-10 17:06:04 +0100 |
---|---|---|
committer | Christian Pointner <equinox@spreadspace.org> | 2019-02-10 17:06:04 +0100 |
commit | c4bf287cc3991e4e52706d3cc73ecf4a577adeeb (patch) | |
tree | a2a5435dc3067c325bde1ae5bf6355973588207b | |
parent | mixer: closer subscriber channel on unsubscribe (diff) |
refactored fader levels and mute state
-rw-r--r-- | cmd/dolmetschctld/statemachine.go | 64 | ||||
-rw-r--r-- | pkg/mixer/mixer.go | 76 |
2 files changed, 109 insertions, 31 deletions
diff --git a/cmd/dolmetschctld/statemachine.go b/cmd/dolmetschctld/statemachine.go index 1961303..e5ea0a9 100644 --- a/cmd/dolmetschctld/statemachine.go +++ b/cmd/dolmetschctld/statemachine.go @@ -59,15 +59,15 @@ func (l Language) String() string { return string(l) } -type LanguageChannel struct { - Num mixer.Channel - currentLevel mixer.FaderLevel - muted bool +type MixerChannel struct { + num mixer.Channel + level mixer.FaderLevel + mute mixer.Mute } -type LanguageChannels struct { - main LanguageChannel - voice LanguageChannel +type MixerChannels struct { + main MixerChannel + voice MixerChannel } type selectLangRequest struct { @@ -82,7 +82,7 @@ type StateMachine struct { exitedCh chan struct{} mixerEventCh chan mixer.Event - languages map[Language]LanguageChannels + languages map[Language]*MixerChannels channel2lang map[mixer.Channel]Language currentState State @@ -101,6 +101,43 @@ func (sm *StateMachine) selectLang(l Language) error { return nil } +func (sm *StateMachine) handleMixerEvent(ev mixer.Event) { + lang, exists := sm.channel2lang[ev.Channel] + if !exists { + // TODO: make this panic? + log.Printf("got mixer-event for unknown channel: %s", ev) + return + } + + mcs, exists := sm.languages[lang] + if !exists { + panic(fmt.Sprintf("channel2lang map contains unknown language entries!")) + return + } + + var mc *MixerChannel + switch ev.Channel { + case mcs.main.num: + mc = &mcs.main + case mcs.voice.num: + mc = &mcs.voice + default: + panic(fmt.Sprintf("channel2lang points to language that does not use the channel!")) + return + } + + switch ev.Type { + case mixer.EventFaderChange: + mc.level = ev.Level + case mixer.EventMute: + mc.mute = ev.Mute + } + + log.Printf("status of mixer channels for language '%s' is now:", lang) + log.Printf(" main(%d): level=%s, muted=%s", mcs.main.num, mcs.main.level, mcs.main.mute) + log.Printf(" voice(%d): level=%s, muted=%s", mcs.voice.num, mcs.voice.level, mcs.voice.mute) +} + func (sm *StateMachine) reconcile() { if sm.targetLang == sm.currentLang { sm.currentState = StateSettled @@ -117,8 +154,7 @@ func (sm *StateMachine) run() { case req := <-sm.selectLangCh: req.resultCh <- sm.selectLang(req.l) case ev := <-sm.mixerEventCh: - log.Printf("got event from mixer: %v", ev) - // TODO: update mixer channel states... + sm.handleMixerEvent(ev) case <-sm.quitCh: return } @@ -138,7 +174,7 @@ func NewStateMachine(m *mixer.Mixer) (*StateMachine, error) { sm.exitedCh = make(chan struct{}) sm.mixerEventCh = make(chan mixer.Event, 1000) - sm.languages = make(map[Language]LanguageChannels) + sm.languages = make(map[Language]*MixerChannels) sm.channel2lang = make(map[mixer.Channel]Language) sm.currentState = StateNew @@ -161,9 +197,9 @@ func (sm *StateMachine) AddLanguage(name Language, main, voice mixer.Channel) er } } - chMain := LanguageChannel{main, mixer.FaderLevel0db, false} - chVoice := LanguageChannel{voice, mixer.FaderLevel0db, false} - sm.languages[name] = LanguageChannels{chMain, chVoice} + chMain := MixerChannel{main, mixer.FaderLevelUnknown, mixer.MuteUnknown} + chVoice := MixerChannel{voice, mixer.FaderLevelUnknown, mixer.MuteUnknown} + sm.languages[name] = &MixerChannels{chMain, chVoice} sm.channel2lang[main] = name sm.channel2lang[voice] = name diff --git a/pkg/mixer/mixer.go b/pkg/mixer/mixer.go index 4db2c3a..a3348d9 100644 --- a/pkg/mixer/mixer.go +++ b/pkg/mixer/mixer.go @@ -32,9 +32,13 @@ import ( "github.com/scgolang/midi" ) -type Channel uint8 -type FaderLevel uint8 +// TODO: make this configurable +const ( + CC_MUTE = byte(0xB1) + CC_FADER = byte(0xB0) +) +type Channel uint8 type EventType int const ( @@ -53,14 +57,61 @@ func (et EventType) String() string { } } +type FaderLevel uint8 + +// TODO: make the values configurable +const ( + FaderLevelUnknown = FaderLevel(0xFF) + FaderLevelMax = FaderLevel(0x7F) + FaderLevel0db = FaderLevel(0x5F) + FaderLevelOff = FaderLevel(0x00) +) + +func (fl FaderLevel) String() string { + if fl > FaderLevelMax { + return "unknown" + } + val := fmt.Sprintf("%3d", fl) + switch fl { + case FaderLevelMax: + return val + " (max)" + case FaderLevel0db: + return val + " (0db)" + case FaderLevelOff: + return val + " (off)" + default: + return val + } +} + +type Mute int8 + +const ( + MuteUnknown = -1 + MuteUnmuted = 0 + MuteMuted = 1 +) + +func (m Mute) String() string { + switch m { + case MuteUnmuted: + return "unmuted" + case MuteMuted: + return "muted" + default: + return "unknown" + } +} + type Event struct { Channel Channel Type EventType - Value uint8 + Level FaderLevel + Mute Mute } func (e Event) String() string { - return fmt.Sprintf("Event(%s) for channel 0x%02X, value=%d", e.Type, e.Channel, e.Value) + return fmt.Sprintf("Event(%s) for channel %d: level=%s, muted=%s", e.Type, e.Channel, e.Level, e.Mute) } type Mixer struct { @@ -69,16 +120,6 @@ type Mixer struct { subscribers map[Channel]*list.List } -// TODO: make this configurable -const ( - CC_MUTE = byte(0xB1) - CC_FADER = byte(0xB0) - - FaderLevelMax = FaderLevel(0x7F) - FaderLevel0db = FaderLevel(0x60) - FaderLevelOff = FaderLevel(0x00) -) - func openDevice(devices []*midi.Device, prefix string) (d *midi.Device, err error) { for _, device := range devices { if strings.HasPrefix(device.Name, prefix) { @@ -136,16 +177,17 @@ func (m *Mixer) sendEvent(ev Event) { } func (m *Mixer) handleMidiPacket(p midi.Packet) { - ev := Event{} + ev := Event{Level: FaderLevelUnknown, Mute: MuteUnknown} ev.Channel = Channel(p.Data[1]) switch p.Data[0] { case CC_FADER: ev.Type = EventFaderChange - ev.Value = p.Data[2] + ev.Level = FaderLevel(p.Data[2]) case CC_MUTE: ev.Type = EventMute + ev.Mute = MuteUnmuted if p.Data[2] > 0 { - ev.Value = 1 + ev.Mute = MuteMuted } default: return |