|
|
|
@ -12,7 +12,7 @@ import (
|
|
|
|
|
"github.com/lawl/pulseaudio"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type uistate struct {
|
|
|
|
|
type ntcontext struct {
|
|
|
|
|
inputList []input
|
|
|
|
|
noiseSupressorState int
|
|
|
|
|
paClient *pulseaudio.Client
|
|
|
|
@ -33,25 +33,25 @@ var green = color.RGBA{34, 187, 69, 255}
|
|
|
|
|
var red = color.RGBA{255, 70, 70, 255}
|
|
|
|
|
var orange = color.RGBA{255, 140, 0, 255}
|
|
|
|
|
|
|
|
|
|
func updatefn(w *nucular.Window, ui *uistate) {
|
|
|
|
|
func updatefn(ctx *ntcontext, w *nucular.Window) {
|
|
|
|
|
|
|
|
|
|
if !ui.paClient.Connected() {
|
|
|
|
|
connectScreen(w, ui)
|
|
|
|
|
if !ctx.paClient.Connected() {
|
|
|
|
|
connectScreen(ctx, w)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ui.loadingScreen {
|
|
|
|
|
loadingScreen(w, ui)
|
|
|
|
|
if ctx.loadingScreen {
|
|
|
|
|
loadingScreen(ctx, w)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ui.licenseScreen {
|
|
|
|
|
licenseScreen(w, ui)
|
|
|
|
|
if ctx.licenseScreen {
|
|
|
|
|
licenseScreen(ctx, w)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ui.versionScreen {
|
|
|
|
|
versionScreen(w, ui)
|
|
|
|
|
if ctx.versionScreen {
|
|
|
|
|
versionScreen(ctx, w)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -61,48 +61,48 @@ func updatefn(w *nucular.Window, ui *uistate) {
|
|
|
|
|
if w := w.Menu(label.TA("About", "LC"), 120, nil); w != nil {
|
|
|
|
|
w.Row(10).Dynamic(1)
|
|
|
|
|
if w.MenuItem(label.T("Licenses")) {
|
|
|
|
|
ui.licenseScreen = true
|
|
|
|
|
ctx.licenseScreen = true
|
|
|
|
|
}
|
|
|
|
|
w.Row(10).Dynamic(1)
|
|
|
|
|
if w.MenuItem(label.T("Source code")) {
|
|
|
|
|
exec.Command("xdg-open", "https://github.com/lawl/NoiseTorch").Run()
|
|
|
|
|
}
|
|
|
|
|
if w.MenuItem(label.T("Version")) {
|
|
|
|
|
ui.versionScreen = true
|
|
|
|
|
ctx.versionScreen = true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
w.MenubarEnd()
|
|
|
|
|
|
|
|
|
|
w.Row(15).Dynamic(1)
|
|
|
|
|
|
|
|
|
|
if ui.noiseSupressorState == loaded {
|
|
|
|
|
if ctx.noiseSupressorState == loaded {
|
|
|
|
|
w.LabelColored("NoiseTorch active", "RC", green)
|
|
|
|
|
} else if ui.noiseSupressorState == unloaded {
|
|
|
|
|
} else if ctx.noiseSupressorState == unloaded {
|
|
|
|
|
w.LabelColored("NoiseTorch inactive", "RC", red)
|
|
|
|
|
} else if ui.noiseSupressorState == inconsistent {
|
|
|
|
|
} else if ctx.noiseSupressorState == inconsistent {
|
|
|
|
|
w.LabelColored("Inconsistent state, please unload first.", "RC", orange)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ui.update.available && !ui.update.triggered {
|
|
|
|
|
if ctx.update.available && !ctx.update.triggered {
|
|
|
|
|
w.Row(20).Ratio(0.9, 0.1)
|
|
|
|
|
w.LabelColored("Update available! Click to install version: "+ui.update.serverVersion, "LC", green)
|
|
|
|
|
w.LabelColored("Update available! Click to install version: "+ctx.update.serverVersion, "LC", green)
|
|
|
|
|
if w.ButtonText("Update") {
|
|
|
|
|
ui.update.triggered = true
|
|
|
|
|
go update(ui)
|
|
|
|
|
(*ui.masterWindow).Changed()
|
|
|
|
|
ctx.update.triggered = true
|
|
|
|
|
go update(ctx)
|
|
|
|
|
(*ctx.masterWindow).Changed()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ui.update.triggered {
|
|
|
|
|
if ctx.update.triggered {
|
|
|
|
|
w.Row(20).Dynamic(1)
|
|
|
|
|
w.Label(ui.update.updatingText, "CC")
|
|
|
|
|
w.Label(ctx.update.updatingText, "CC")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if w.TreePush(nucular.TreeTab, "Settings", true) {
|
|
|
|
|
w.Row(15).Dynamic(2)
|
|
|
|
|
if w.CheckboxText("Display Monitor Sources", &ui.config.DisplayMonitorSources) {
|
|
|
|
|
ui.sourceListColdWidthIndex++ //recompute the with because of new elements
|
|
|
|
|
go writeConfig(ui.config)
|
|
|
|
|
if w.CheckboxText("Display Monitor Sources", &ctx.config.DisplayMonitorSources) {
|
|
|
|
|
ctx.sourceListColdWidthIndex++ //recompute the with because of new elements
|
|
|
|
|
go writeConfig(ctx.config)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
w.Spacing(1)
|
|
|
|
@ -112,13 +112,13 @@ func updatefn(w *nucular.Window, ui *uistate) {
|
|
|
|
|
if w.Input().Mouse.HoveringRect(w.LastWidgetBounds) {
|
|
|
|
|
w.Tooltip("If you have a decent microphone, you can usually turn this all the way up.")
|
|
|
|
|
}
|
|
|
|
|
if w.SliderInt(0, &ui.config.Threshold, 95, 1) {
|
|
|
|
|
go writeConfig(ui.config)
|
|
|
|
|
ui.reloadRequired = true
|
|
|
|
|
if w.SliderInt(0, &ctx.config.Threshold, 95, 1) {
|
|
|
|
|
go writeConfig(ctx.config)
|
|
|
|
|
ctx.reloadRequired = true
|
|
|
|
|
}
|
|
|
|
|
w.Label(fmt.Sprintf("%d%%", ui.config.Threshold), "RC")
|
|
|
|
|
w.Label(fmt.Sprintf("%d%%", ctx.config.Threshold), "RC")
|
|
|
|
|
|
|
|
|
|
if ui.reloadRequired {
|
|
|
|
|
if ctx.reloadRequired {
|
|
|
|
|
w.Row(20).Dynamic(1)
|
|
|
|
|
w.LabelColored("Reloading NoiseTorch is required to apply these changes.", "LC", orange)
|
|
|
|
|
}
|
|
|
|
@ -129,19 +129,19 @@ func updatefn(w *nucular.Window, ui *uistate) {
|
|
|
|
|
w.Row(15).Dynamic(1)
|
|
|
|
|
w.Label("Select an input device below:", "LC")
|
|
|
|
|
|
|
|
|
|
for i := range ui.inputList {
|
|
|
|
|
el := &ui.inputList[i]
|
|
|
|
|
for i := range ctx.inputList {
|
|
|
|
|
el := &ctx.inputList[i]
|
|
|
|
|
|
|
|
|
|
if el.isMonitor && !ui.config.DisplayMonitorSources {
|
|
|
|
|
if el.isMonitor && !ctx.config.DisplayMonitorSources {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
w.Row(15).Static()
|
|
|
|
|
w.LayoutFitWidth(0, 0)
|
|
|
|
|
if w.CheckboxText("", &el.checked) {
|
|
|
|
|
ensureOnlyOneInputSelected(&ui.inputList, el)
|
|
|
|
|
ensureOnlyOneInputSelected(&ctx.inputList, el)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
w.LayoutFitWidth(ui.sourceListColdWidthIndex, 0)
|
|
|
|
|
w.LayoutFitWidth(ctx.sourceListColdWidthIndex, 0)
|
|
|
|
|
if el.dynamicLatency {
|
|
|
|
|
w.Label(el.Name, "LC")
|
|
|
|
|
} else {
|
|
|
|
@ -153,53 +153,53 @@ func updatefn(w *nucular.Window, ui *uistate) {
|
|
|
|
|
w.Spacing(1)
|
|
|
|
|
|
|
|
|
|
w.Row(25).Dynamic(2)
|
|
|
|
|
if ui.noiseSupressorState != unloaded {
|
|
|
|
|
if ctx.noiseSupressorState != unloaded {
|
|
|
|
|
if w.ButtonText("Unload NoiseTorch") {
|
|
|
|
|
ui.loadingScreen = true
|
|
|
|
|
ui.reloadRequired = false
|
|
|
|
|
ctx.loadingScreen = true
|
|
|
|
|
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 err := unloadSupressor(ui.paClient); err != nil {
|
|
|
|
|
if err := unloadSupressor(ctx.paClient); err != nil {
|
|
|
|
|
log.Println(err)
|
|
|
|
|
}
|
|
|
|
|
//wait until PA reports it has actually loaded it, timeout at 10s
|
|
|
|
|
for i := 0; i < 20; i++ {
|
|
|
|
|
if supressorState(ui.paClient) != unloaded {
|
|
|
|
|
if supressorState(ctx.paClient) != unloaded {
|
|
|
|
|
time.Sleep(time.Millisecond * 500)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ui.loadingScreen = false
|
|
|
|
|
(*ui.masterWindow).Changed()
|
|
|
|
|
ctx.loadingScreen = false
|
|
|
|
|
(*ctx.masterWindow).Changed()
|
|
|
|
|
}()
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
w.Spacing(1)
|
|
|
|
|
}
|
|
|
|
|
txt := "Load NoiseTorch"
|
|
|
|
|
if ui.noiseSupressorState == loaded {
|
|
|
|
|
if ctx.noiseSupressorState == loaded {
|
|
|
|
|
txt = "Reload NoiseTorch"
|
|
|
|
|
}
|
|
|
|
|
if inp, ok := inputSelection(ui); ok && ui.noiseSupressorState != inconsistent {
|
|
|
|
|
if inp, ok := inputSelection(ctx); ok && ctx.noiseSupressorState != inconsistent {
|
|
|
|
|
if w.ButtonText(txt) {
|
|
|
|
|
ui.loadingScreen = true
|
|
|
|
|
ui.reloadRequired = false
|
|
|
|
|
ctx.loadingScreen = true
|
|
|
|
|
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 ui.noiseSupressorState == loaded {
|
|
|
|
|
if err := unloadSupressor(ui.paClient); err != nil {
|
|
|
|
|
if ctx.noiseSupressorState == loaded {
|
|
|
|
|
if err := unloadSupressor(ctx.paClient); err != nil {
|
|
|
|
|
log.Println(err)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if err := loadSupressor(ui.paClient, inp, ui); err != nil {
|
|
|
|
|
if err := loadSupressor(ctx, inp); err != nil {
|
|
|
|
|
log.Println(err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//wait until PA reports it has actually loaded it, timeout at 10s
|
|
|
|
|
for i := 0; i < 20; i++ {
|
|
|
|
|
if supressorState(ui.paClient) != loaded {
|
|
|
|
|
if supressorState(ctx.paClient) != loaded {
|
|
|
|
|
time.Sleep(time.Millisecond * 500)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ui.loadingScreen = false
|
|
|
|
|
(*ui.masterWindow).Changed()
|
|
|
|
|
ctx.loadingScreen = false
|
|
|
|
|
(*ctx.masterWindow).Changed()
|
|
|
|
|
}()
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
@ -220,8 +220,8 @@ func ensureOnlyOneInputSelected(inps *[]input, current *input) {
|
|
|
|
|
current.checked = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func inputSelection(ui *uistate) (input, bool) {
|
|
|
|
|
for _, in := range ui.inputList {
|
|
|
|
|
func inputSelection(ctx *ntcontext) (input, bool) {
|
|
|
|
|
for _, in := range ctx.inputList {
|
|
|
|
|
if in.checked {
|
|
|
|
|
return in, true
|
|
|
|
|
}
|
|
|
|
@ -229,16 +229,16 @@ func inputSelection(ui *uistate) (input, bool) {
|
|
|
|
|
return input{}, false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func loadingScreen(w *nucular.Window, ui *uistate) {
|
|
|
|
|
func loadingScreen(ctx *ntcontext, w *nucular.Window) {
|
|
|
|
|
w.Row(50).Dynamic(1)
|
|
|
|
|
w.Label("Working...", "CB")
|
|
|
|
|
w.Row(50).Dynamic(1)
|
|
|
|
|
w.Label("(this may take a few seconds)", "CB")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func licenseScreen(w *nucular.Window, ui *uistate) {
|
|
|
|
|
func licenseScreen(ctx *ntcontext, w *nucular.Window) {
|
|
|
|
|
w.Row(255).Dynamic(1)
|
|
|
|
|
field := &ui.licenseTextArea
|
|
|
|
|
field := &ctx.licenseTextArea
|
|
|
|
|
field.Flags |= nucular.EditMultiline
|
|
|
|
|
if len(field.Buffer) < 1 {
|
|
|
|
|
field.Buffer = []rune(licenseString)
|
|
|
|
@ -248,11 +248,11 @@ func licenseScreen(w *nucular.Window, ui *uistate) {
|
|
|
|
|
w.Row(20).Dynamic(2)
|
|
|
|
|
w.Spacing(1)
|
|
|
|
|
if w.ButtonText("OK") {
|
|
|
|
|
ui.licenseScreen = false
|
|
|
|
|
ctx.licenseScreen = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func versionScreen(w *nucular.Window, ui *uistate) {
|
|
|
|
|
func versionScreen(ctx *ntcontext, w *nucular.Window) {
|
|
|
|
|
w.Row(50).Dynamic(1)
|
|
|
|
|
w.Label("Version", "CB")
|
|
|
|
|
w.Row(50).Dynamic(1)
|
|
|
|
@ -262,19 +262,19 @@ func versionScreen(w *nucular.Window, ui *uistate) {
|
|
|
|
|
w.Row(20).Dynamic(2)
|
|
|
|
|
w.Spacing(1)
|
|
|
|
|
if w.ButtonText("OK") {
|
|
|
|
|
ui.versionScreen = false
|
|
|
|
|
ctx.versionScreen = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func connectScreen(w *nucular.Window, ui *uistate) {
|
|
|
|
|
func connectScreen(ctx *ntcontext, w *nucular.Window) {
|
|
|
|
|
w.Row(50).Dynamic(1)
|
|
|
|
|
w.Label("Connecting to pulseaudio...", "CB")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func resetUI(ui *uistate) {
|
|
|
|
|
ui.loadingScreen = false
|
|
|
|
|
func resetUI(ctx *ntcontext) {
|
|
|
|
|
ctx.loadingScreen = false
|
|
|
|
|
|
|
|
|
|
if ui.masterWindow != nil {
|
|
|
|
|
(*ui.masterWindow).Changed()
|
|
|
|
|
if ctx.masterWindow != nil {
|
|
|
|
|
(*ctx.masterWindow).Changed()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|