|
|
@ -34,6 +34,7 @@ type ntcontext struct {
|
|
|
|
capsMismatch bool
|
|
|
|
capsMismatch bool
|
|
|
|
views *ViewStack
|
|
|
|
views *ViewStack
|
|
|
|
serverInfo audioserverinfo
|
|
|
|
serverInfo audioserverinfo
|
|
|
|
|
|
|
|
virtualDeviceInUse bool
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//TODO pull some of these strucs out of UI, they don't belong here
|
|
|
|
//TODO pull some of these strucs out of UI, they don't belong here
|
|
|
@ -149,13 +150,13 @@ func mainView(ctx *ntcontext, w *nucular.Window) {
|
|
|
|
if w.CheckboxText("Filter Microphone", &ctx.config.FilterInput) {
|
|
|
|
if w.CheckboxText("Filter Microphone", &ctx.config.FilterInput) {
|
|
|
|
ctx.sourceListColdWidthIndex++ //recompute the with because of new elements
|
|
|
|
ctx.sourceListColdWidthIndex++ //recompute the with because of new elements
|
|
|
|
go writeConfig(ctx.config)
|
|
|
|
go writeConfig(ctx.config)
|
|
|
|
go (func() { ctx.noiseSupressorState = supressorState(ctx) })()
|
|
|
|
go (func() { ctx.noiseSupressorState, _ = supressorState(ctx) })()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if w.CheckboxText("Filter Headphones", &ctx.config.FilterOutput) {
|
|
|
|
if w.CheckboxText("Filter Headphones", &ctx.config.FilterOutput) {
|
|
|
|
ctx.sourceListColdWidthIndex++ //recompute the with because of new elements
|
|
|
|
ctx.sourceListColdWidthIndex++ //recompute the with because of new elements
|
|
|
|
go writeConfig(ctx.config)
|
|
|
|
go writeConfig(ctx.config)
|
|
|
|
go (func() { ctx.noiseSupressorState = supressorState(ctx) })()
|
|
|
|
go (func() { ctx.noiseSupressorState, _ = supressorState(ctx) })()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
w.TreePop()
|
|
|
|
w.TreePop()
|
|
|
@ -239,21 +240,19 @@ func mainView(ctx *ntcontext, w *nucular.Window) {
|
|
|
|
w.Row(25).Dynamic(2)
|
|
|
|
w.Row(25).Dynamic(2)
|
|
|
|
if ctx.noiseSupressorState != unloaded {
|
|
|
|
if ctx.noiseSupressorState != unloaded {
|
|
|
|
if w.ButtonText("Unload NoiseTorch") {
|
|
|
|
if w.ButtonText("Unload NoiseTorch") {
|
|
|
|
ctx.views.Push(loadingView)
|
|
|
|
|
|
|
|
ctx.reloadRequired = false
|
|
|
|
ctx.reloadRequired = false
|
|
|
|
go func() { // don't block the UI thread, just display a working screen so user can't run multiple loads/unloads
|
|
|
|
if ctx.virtualDeviceInUse {
|
|
|
|
if err := unloadSupressor(ctx); err != nil {
|
|
|
|
confirm := makeConfirmView(ctx,
|
|
|
|
log.Println(err)
|
|
|
|
"Virtual Device in Use",
|
|
|
|
}
|
|
|
|
"Some applications may behave weirdly when you remove a device they're currently using",
|
|
|
|
//wait until PA reports it has actually loaded it, timeout at 10s
|
|
|
|
"Unload",
|
|
|
|
for i := 0; i < 20; i++ {
|
|
|
|
"Go back",
|
|
|
|
if supressorState(ctx) != unloaded {
|
|
|
|
func() { uiUnloadNoisetorch(ctx) },
|
|
|
|
time.Sleep(time.Millisecond * 500)
|
|
|
|
func() {})
|
|
|
|
}
|
|
|
|
ctx.views.Push(confirm)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ctx.views.Pop()
|
|
|
|
go uiUnloadNoisetorch(ctx)
|
|
|
|
(*ctx.masterWindow).Changed()
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
w.Spacing(1)
|
|
|
|
w.Spacing(1)
|
|
|
@ -271,30 +270,20 @@ func mainView(ctx *ntcontext, w *nucular.Window) {
|
|
|
|
((ctx.config.FilterOutput && ctx.config.GuiltTripped) || !ctx.config.FilterOutput) &&
|
|
|
|
((ctx.config.FilterOutput && ctx.config.GuiltTripped) || !ctx.config.FilterOutput) &&
|
|
|
|
ctx.noiseSupressorState != inconsistent {
|
|
|
|
ctx.noiseSupressorState != inconsistent {
|
|
|
|
if w.ButtonText(txt) {
|
|
|
|
if w.ButtonText(txt) {
|
|
|
|
ctx.views.Push(loadingView)
|
|
|
|
|
|
|
|
ctx.reloadRequired = false
|
|
|
|
ctx.reloadRequired = false
|
|
|
|
go func() { // don't block the UI thread, just display a working screen so user can't run multiple loads/unloads
|
|
|
|
|
|
|
|
if ctx.noiseSupressorState == loaded {
|
|
|
|
|
|
|
|
if err := unloadSupressor(ctx); err != nil {
|
|
|
|
|
|
|
|
log.Println(err)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := loadSupressor(ctx, &inp, &out); err != nil {
|
|
|
|
|
|
|
|
log.Println(err)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//wait until PA reports it has actually loaded it, timeout at 10s
|
|
|
|
if ctx.virtualDeviceInUse {
|
|
|
|
for i := 0; i < 20; i++ {
|
|
|
|
confirm := makeConfirmView(ctx,
|
|
|
|
if supressorState(ctx) != loaded {
|
|
|
|
"Virtual Device in Use",
|
|
|
|
time.Sleep(time.Millisecond * 500)
|
|
|
|
"Some applications may behave weirdly when you reload a device they're currently using",
|
|
|
|
}
|
|
|
|
"Reload",
|
|
|
|
}
|
|
|
|
"Go back",
|
|
|
|
ctx.config.LastUsedInput = inp.ID
|
|
|
|
func() { uiReloadNoisetorch(ctx, inp, out) },
|
|
|
|
ctx.config.LastUsedOutput = out.ID
|
|
|
|
func() {})
|
|
|
|
go writeConfig(ctx.config)
|
|
|
|
ctx.views.Push(confirm)
|
|
|
|
ctx.views.Pop()
|
|
|
|
} else {
|
|
|
|
(*ctx.masterWindow).Changed()
|
|
|
|
go uiReloadNoisetorch(ctx, inp, out)
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
w.Spacing(1)
|
|
|
|
w.Spacing(1)
|
|
|
@ -302,6 +291,45 @@ func mainView(ctx *ntcontext, w *nucular.Window) {
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func uiUnloadNoisetorch(ctx *ntcontext) {
|
|
|
|
|
|
|
|
ctx.views.Push(loadingView)
|
|
|
|
|
|
|
|
if err := unloadSupressor(ctx); err != nil {
|
|
|
|
|
|
|
|
log.Println(err)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//wait until PA reports it has actually loaded it, timeout at 10s
|
|
|
|
|
|
|
|
for i := 0; i < 20; i++ {
|
|
|
|
|
|
|
|
if state, _ := supressorState(ctx); state != unloaded {
|
|
|
|
|
|
|
|
time.Sleep(time.Millisecond * 500)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx.views.Pop()
|
|
|
|
|
|
|
|
(*ctx.masterWindow).Changed()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func uiReloadNoisetorch(ctx *ntcontext, inp, out device) {
|
|
|
|
|
|
|
|
ctx.views.Push(loadingView)
|
|
|
|
|
|
|
|
if ctx.noiseSupressorState == loaded {
|
|
|
|
|
|
|
|
if err := unloadSupressor(ctx); err != nil {
|
|
|
|
|
|
|
|
log.Println(err)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := loadSupressor(ctx, &inp, &out); err != nil {
|
|
|
|
|
|
|
|
log.Println(err)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//wait until PA reports it has actually loaded it, timeout at 10s
|
|
|
|
|
|
|
|
for i := 0; i < 20; i++ {
|
|
|
|
|
|
|
|
if state, _ := supressorState(ctx); state != loaded {
|
|
|
|
|
|
|
|
time.Sleep(time.Millisecond * 500)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx.config.LastUsedInput = inp.ID
|
|
|
|
|
|
|
|
ctx.config.LastUsedOutput = out.ID
|
|
|
|
|
|
|
|
go writeConfig(ctx.config)
|
|
|
|
|
|
|
|
ctx.views.Pop()
|
|
|
|
|
|
|
|
(*ctx.masterWindow).Changed()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func ensureOnlyOneInputSelected(inps *[]device, current *device) {
|
|
|
|
func ensureOnlyOneInputSelected(inps *[]device, current *device) {
|
|
|
|
if current.checked != true {
|
|
|
|
if current.checked != true {
|
|
|
|
return
|
|
|
|
return
|
|
|
@ -443,6 +471,27 @@ func makeFatalErrorView(ctx *ntcontext, errorMsg string) ViewFunc {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func makeConfirmView(ctx *ntcontext, title, text, confirmText, denyText string, confirmfunc, denyfunc func()) ViewFunc {
|
|
|
|
|
|
|
|
return func(ctx *ntcontext, w *nucular.Window) {
|
|
|
|
|
|
|
|
w.Row(15).Dynamic(1)
|
|
|
|
|
|
|
|
w.Label(title, "CB")
|
|
|
|
|
|
|
|
w.Row(15).Dynamic(1)
|
|
|
|
|
|
|
|
w.Label(text, "CB")
|
|
|
|
|
|
|
|
w.Row(40).Dynamic(1)
|
|
|
|
|
|
|
|
w.Row(25).Dynamic(2)
|
|
|
|
|
|
|
|
if w.ButtonText(denyText) {
|
|
|
|
|
|
|
|
ctx.views.Pop()
|
|
|
|
|
|
|
|
go denyfunc()
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if w.ButtonText(confirmText) {
|
|
|
|
|
|
|
|
ctx.views.Pop()
|
|
|
|
|
|
|
|
go confirmfunc()
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func resetUI(ctx *ntcontext) {
|
|
|
|
func resetUI(ctx *ntcontext) {
|
|
|
|
ctx.views = NewViewStack()
|
|
|
|
ctx.views = NewViewStack()
|
|
|
|
ctx.views.Push(mainView)
|
|
|
|
ctx.views.Push(mainView)
|
|
|
|