mirror of
https://github.com/onyx-and-iris/voicemeeter.git
synced 2026-04-18 13:33:30 +00:00
pooler now accepts channels
done channels used to clean up pooler if GUI goes down InitPooler() added to Remote type, useful for reinitiating the Pooler. For this reason Pooler now defined as singleton type.
This commit is contained in:
146
publisher.go
146
publisher.go
@@ -6,40 +6,14 @@ import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// observer defines the interface any registered observers must satisfy
|
||||
type observer interface {
|
||||
OnUpdate(subject string)
|
||||
}
|
||||
|
||||
// publisher defines methods that support observers
|
||||
// publisher defines the list of observer channels
|
||||
type publisher struct {
|
||||
observerList []observer
|
||||
observers []chan string
|
||||
}
|
||||
|
||||
// Register adds an observer to observerList
|
||||
func (p *publisher) Register(o observer) {
|
||||
p.observerList = append(p.observerList, o)
|
||||
}
|
||||
|
||||
// Deregister removes an observer from observerList
|
||||
func (p *publisher) Deregister(o observer) {
|
||||
var indexToRemove int
|
||||
|
||||
for i, observer := range p.observerList {
|
||||
if observer == o {
|
||||
indexToRemove = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
p.observerList = append(p.observerList[:indexToRemove], p.observerList[indexToRemove+1:]...)
|
||||
}
|
||||
|
||||
// notify updates observers of any changes
|
||||
func (p *publisher) notify(subject string) {
|
||||
for _, observer := range p.observerList {
|
||||
observer.OnUpdate(subject)
|
||||
}
|
||||
// Register adds an observer channel to the channelList
|
||||
func (p *publisher) Register(channel chan string) {
|
||||
p.observers = append(p.observers, channel)
|
||||
}
|
||||
|
||||
type event struct {
|
||||
@@ -85,32 +59,81 @@ func (e *event) Remove(events ...string) {
|
||||
}
|
||||
}
|
||||
|
||||
// pooler continuously polls the dirty paramters
|
||||
var p *pooler
|
||||
|
||||
// pooler continuously polls the dirty parameters
|
||||
// it is expected to be run in a goroutine
|
||||
type pooler struct {
|
||||
k *kind
|
||||
run bool
|
||||
event *event
|
||||
k *kind
|
||||
run bool
|
||||
event *event
|
||||
pdirtyDone chan bool
|
||||
mdirtyDone chan bool
|
||||
midiDone chan bool
|
||||
ldirtyDone chan bool
|
||||
publisher
|
||||
}
|
||||
|
||||
func newPooler(k *kind) *pooler {
|
||||
p := &pooler{
|
||||
k: k,
|
||||
run: true,
|
||||
event: newEvent(),
|
||||
if p == nil {
|
||||
p = &pooler{
|
||||
k: k,
|
||||
run: true,
|
||||
event: newEvent(),
|
||||
pdirtyDone: make(chan bool),
|
||||
mdirtyDone: make(chan bool),
|
||||
midiDone: make(chan bool),
|
||||
ldirtyDone: make(chan bool),
|
||||
}
|
||||
go p.done()
|
||||
go p.parameters()
|
||||
go p.macrobuttons()
|
||||
go p.midi()
|
||||
go p.levels()
|
||||
}
|
||||
go p.parameters()
|
||||
go p.macrobuttons()
|
||||
go p.midi()
|
||||
go p.levels()
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *pooler) done() {
|
||||
for {
|
||||
select {
|
||||
case _, ok := <-p.pdirtyDone:
|
||||
if !ok {
|
||||
p.pdirtyDone = nil
|
||||
}
|
||||
case _, ok := <-p.mdirtyDone:
|
||||
if !ok {
|
||||
p.mdirtyDone = nil
|
||||
}
|
||||
case _, ok := <-p.midiDone:
|
||||
if !ok {
|
||||
p.midiDone = nil
|
||||
}
|
||||
case _, ok := <-p.ldirtyDone:
|
||||
if !ok {
|
||||
p.ldirtyDone = nil
|
||||
}
|
||||
}
|
||||
if p.pdirtyDone == nil && p.mdirtyDone == nil && p.midiDone == nil && p.ldirtyDone == nil {
|
||||
for _, ch := range p.observers {
|
||||
close(ch)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *pooler) parameters() {
|
||||
for p.run {
|
||||
if p.event.pdirty && pdirty() {
|
||||
p.notify("pdirty")
|
||||
pdirty, err := pdirty()
|
||||
if err != nil {
|
||||
close(p.pdirtyDone)
|
||||
break
|
||||
}
|
||||
if p.event.pdirty && pdirty {
|
||||
for _, ch := range p.observers {
|
||||
ch <- "pdirty"
|
||||
}
|
||||
}
|
||||
time.Sleep(33 * time.Millisecond)
|
||||
}
|
||||
@@ -118,8 +141,15 @@ func (p *pooler) parameters() {
|
||||
|
||||
func (p *pooler) macrobuttons() {
|
||||
for p.run {
|
||||
if p.event.mdirty && mdirty() {
|
||||
p.notify("mdirty")
|
||||
mdirty, err := mdirty()
|
||||
if err != nil {
|
||||
close(p.mdirtyDone)
|
||||
break
|
||||
}
|
||||
if p.event.mdirty && mdirty {
|
||||
for _, ch := range p.observers {
|
||||
ch <- "mdirty"
|
||||
}
|
||||
}
|
||||
time.Sleep(33 * time.Millisecond)
|
||||
}
|
||||
@@ -127,8 +157,15 @@ func (p *pooler) macrobuttons() {
|
||||
|
||||
func (p *pooler) midi() {
|
||||
for p.run {
|
||||
if p.event.midi && getMidiMessage() {
|
||||
p.notify("midi")
|
||||
midi, err := getMidiMessage()
|
||||
if err != nil {
|
||||
close(p.midiDone)
|
||||
break
|
||||
}
|
||||
if p.event.midi && midi {
|
||||
for _, ch := range p.observers {
|
||||
ch <- "midi"
|
||||
}
|
||||
}
|
||||
time.Sleep(33 * time.Millisecond)
|
||||
}
|
||||
@@ -138,10 +175,17 @@ func (p *pooler) levels() {
|
||||
_levelCache = newLevelCache(p.k)
|
||||
|
||||
for p.run {
|
||||
if p.event.ldirty && ldirty(p.k) {
|
||||
ldirty, err := ldirty(p.k)
|
||||
if err != nil {
|
||||
close(p.ldirtyDone)
|
||||
break
|
||||
}
|
||||
if p.event.ldirty && ldirty {
|
||||
update(_levelCache.stripLevels, _levelCache.stripLevelsBuff, (2*p.k.PhysIn)+(8*p.k.VirtIn))
|
||||
update(_levelCache.busLevels, _levelCache.busLevelsBuff, 8*p.k.NumBus())
|
||||
p.notify("ldirty")
|
||||
for _, ch := range p.observers {
|
||||
ch <- "ldirty"
|
||||
}
|
||||
}
|
||||
time.Sleep(33 * time.Millisecond)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user