Further implementation of config management
This commit is contained in:
parent
1b5d77e07a
commit
fffd67f8c0
|
@ -9,7 +9,8 @@ The GUI will work off a config similar to the following. Use the ```generate con
|
||||||
```
|
```
|
||||||
|
|
||||||
[slideshow]
|
[slideshow]
|
||||||
duration = "300s"
|
slideinterval = "300s"
|
||||||
|
restartinterval = "7d"
|
||||||
|
|
||||||
[hdmi]
|
[hdmi]
|
||||||
# These are SYSTEMD.TIME formatted times
|
# These are SYSTEMD.TIME formatted times
|
||||||
|
|
|
@ -15,27 +15,6 @@ import (
|
||||||
"git.kemonine.info/PiFrame/ui"
|
"git.kemonine.info/PiFrame/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
CLI_FLAG_CONFIG_ONLY = "config-ui-only"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
CONFIG_FILE_PATH = "/etc/default/pf.toml"
|
|
||||||
CONFIG_KEY_SLIDESHOW_DURATION = "slideshow.duration"
|
|
||||||
CONFIG_KEY_HDMI_OFF = "hdmi.off"
|
|
||||||
CONFIG_KEY_HDMI_ON = "hdmi.on"
|
|
||||||
CONFIG_KEY_ALBUMS_ROOT = "albums.root"
|
|
||||||
CONFIG_KEY_ALBUMS_SELECTED = "albums.selected"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
DEFAULT_SLIDESHOW_DURATION = "300s"
|
|
||||||
DEFAULT_HDMI_OFF = "*-*-* 00:00:00"
|
|
||||||
DEFAULT_HDMI_ON = "*-*-* 06:00:00"
|
|
||||||
DEFAULT_ALBUMS_ROOT = "/tank/pictures"
|
|
||||||
DEFAULT_ALBUM_SELECTED = "/"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Command line flag handler
|
// Command line flag handler
|
||||||
f := flag.NewFlagSet("piframe", flag.ContinueOnError)
|
f := flag.NewFlagSet("piframe", flag.ContinueOnError)
|
||||||
|
@ -44,8 +23,8 @@ func main() {
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
// Command line flags
|
// Command line flags
|
||||||
f.Bool(CLI_FLAG_CONFIG_ONLY, false, "Only show the config UI, NOT the slideshow")
|
f.Bool(ui.CLI_FLAG_CONFIG_ONLY, false, "Only show the config UI, NOT the slideshow")
|
||||||
cliFlag := f.Lookup(CLI_FLAG_CONFIG_ONLY)
|
cliFlag := f.Lookup(ui.CLI_FLAG_CONFIG_ONLY)
|
||||||
if cliFlag != nil {
|
if cliFlag != nil {
|
||||||
cliFlag.NoOptDefVal = "true"
|
cliFlag.NoOptDefVal = "true"
|
||||||
}
|
}
|
||||||
|
@ -57,25 +36,24 @@ func main() {
|
||||||
|
|
||||||
// Setup some defaults
|
// Setup some defaults
|
||||||
pfConfig.Load(confmap.Provider(map[string]interface{}{
|
pfConfig.Load(confmap.Provider(map[string]interface{}{
|
||||||
CONFIG_KEY_SLIDESHOW_DURATION: DEFAULT_SLIDESHOW_DURATION,
|
ui.CONFIG_KEY_SLIDESHOW_INTERVAL: ui.DEFAULT_SLIDESHOW_INTERVAL,
|
||||||
CONFIG_KEY_HDMI_OFF: DEFAULT_HDMI_OFF,
|
ui.CONFIG_KEY_SLIDESHOW_RESTART_INTERVAL: ui.DEFAULT_SLIDESHOW_RESTART_INTERVAL,
|
||||||
CONFIG_KEY_HDMI_ON: DEFAULT_HDMI_ON,
|
ui.CONFIG_KEY_HDMI_OFF: ui.DEFAULT_HDMI_OFF,
|
||||||
CONFIG_KEY_ALBUMS_ROOT: DEFAULT_ALBUMS_ROOT,
|
ui.CONFIG_KEY_HDMI_ON: ui.DEFAULT_HDMI_ON,
|
||||||
CONFIG_KEY_ALBUMS_SELECTED: []string{DEFAULT_ALBUM_SELECTED},
|
ui.CONFIG_KEY_ALBUMS_ROOT: ui.DEFAULT_ALBUMS_ROOT,
|
||||||
|
ui.CONFIG_KEY_ALBUMS_SELECTED: []string{ui.DEFAULT_ALBUM_SELECTED},
|
||||||
}, "."), nil)
|
}, "."), nil)
|
||||||
|
|
||||||
// Bring in /etc/defaults/pf.toml if it exists
|
// Bring in /etc/defaults/pf.toml if it exists
|
||||||
configFileProvider := file.Provider(CONFIG_FILE_PATH)
|
configFileProvider := file.Provider(ui.CONFIG_FILE_PATH)
|
||||||
_, err := os.Stat(CONFIG_FILE_PATH)
|
_, err := os.Stat(ui.CONFIG_FILE_PATH)
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
// log.Printf("%s does not exist, USING DEFAULTS", CONFIG_FILE_PATH)
|
//log.Printf("%s does not exist, USING DEFAULTS", ui.CONFIG_FILE_PATH)
|
||||||
} else {
|
} else {
|
||||||
if errConfigFile := pfConfig.Load(configFileProvider, toml.Parser()); errConfigFile != nil {
|
if errConfigFile := pfConfig.Load(configFileProvider, toml.Parser()); errConfigFile != nil {
|
||||||
log.Fatalf("Error loading config : %s", err)
|
log.Fatalf("Error loading config : %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Watch for config changes and re-load config if needed
|
// Watch for config changes and re-load config if needed
|
||||||
configFileProvider.Watch(func(event interface{}, err error) {
|
configFileProvider.Watch(func(event interface{}, err error) {
|
||||||
|
@ -92,9 +70,9 @@ func main() {
|
||||||
log.Fatalf("Error loading command line flags : %s", err)
|
log.Fatalf("Error loading command line flags : %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !pfConfig.Bool(CLI_FLAG_CONFIG_ONLY) {
|
if !pfConfig.Bool(ui.CLI_FLAG_CONFIG_ONLY) {
|
||||||
ui.Slideshow()
|
ui.Slideshow(pfConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.ConfigGui()
|
ui.ConfigGui(pfConfig)
|
||||||
}
|
}
|
||||||
|
|
83
ui/config.go
83
ui/config.go
|
@ -14,6 +14,7 @@ import (
|
||||||
|
|
||||||
"github.com/gdamore/tcell"
|
"github.com/gdamore/tcell"
|
||||||
"github.com/guillermo/go.procmeminfo"
|
"github.com/guillermo/go.procmeminfo"
|
||||||
|
"github.com/knadh/koanf"
|
||||||
"github.com/rivo/tview"
|
"github.com/rivo/tview"
|
||||||
|
|
||||||
"git.kemonine.info/PiFrame/wifi"
|
"git.kemonine.info/PiFrame/wifi"
|
||||||
|
@ -24,7 +25,6 @@ const (
|
||||||
CMD_FINDMNT = "/usr/bin/findmnt"
|
CMD_FINDMNT = "/usr/bin/findmnt"
|
||||||
CMD_VCGENCMD = "/opt/vc/bin/vcgencmd"
|
CMD_VCGENCMD = "/opt/vc/bin/vcgencmd"
|
||||||
FILE_CPU_TEMP = "/sys/class/thermal/thermal_zone0/temp"
|
FILE_CPU_TEMP = "/sys/class/thermal/thermal_zone0/temp"
|
||||||
ALBUM_ROOT_DIR = "/tank/pictures/"
|
|
||||||
SYNCTHING_FOLDER_SKIP = ".stfolder"
|
SYNCTHING_FOLDER_SKIP = ".stfolder"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ const (
|
||||||
PAGE_POWEROFF = "PAGE_POWEROFF"
|
PAGE_POWEROFF = "PAGE_POWEROFF"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ConfigGui() {
|
func ConfigGui(config *koanf.Koanf) {
|
||||||
// Memory info for status panel
|
// Memory info for status panel
|
||||||
meminfo := &procmeminfo.MemInfo{}
|
meminfo := &procmeminfo.MemInfo{}
|
||||||
err := meminfo.Update()
|
err := meminfo.Update()
|
||||||
|
@ -80,7 +80,7 @@ func ConfigGui() {
|
||||||
|
|
||||||
// Get list of all folders that can be used as albums
|
// Get list of all folders that can be used as albums
|
||||||
var albums []string
|
var albums []string
|
||||||
err = filepath.Walk(ALBUM_ROOT_DIR, func(path string, fi os.FileInfo, err error) error {
|
err = filepath.Walk(config.String(CONFIG_KEY_ALBUMS_ROOT), func(path string, fi os.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ func ConfigGui() {
|
||||||
if strings.Contains(path, SYNCTHING_FOLDER_SKIP) {
|
if strings.Contains(path, SYNCTHING_FOLDER_SKIP) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
albumName := strings.TrimPrefix(path, ALBUM_ROOT_DIR)
|
albumName := strings.TrimPrefix(path, config.String(CONFIG_KEY_ALBUMS_ROOT))
|
||||||
if albumName == "" {
|
if albumName == "" {
|
||||||
albumName = "Main Folder"
|
albumName = "Main Folder"
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,9 @@ func ConfigGui() {
|
||||||
SetTitle("Menu").
|
SetTitle("Menu").
|
||||||
SetTitleColor(tcell.ColorAqua)
|
SetTitleColor(tcell.ColorAqua)
|
||||||
menu.AddItem("Select Albums", "", '1', nil)
|
menu.AddItem("Select Albums", "", '1', nil)
|
||||||
menu.AddItem("Configure WiFi", "", '2', nil)
|
menu.AddItem("Intervals", "", '2', nil)
|
||||||
|
menu.AddItem("WiFi", "", '3', nil)
|
||||||
|
menu.AddItem("HDMI On/Off", "", '5', nil)
|
||||||
|
|
||||||
// Setup base var for main column so the menu setup is easier to manage
|
// Setup base var for main column so the menu setup is easier to manage
|
||||||
main := tview.NewFlex().
|
main := tview.NewFlex().
|
||||||
|
@ -165,6 +167,39 @@ func ConfigGui() {
|
||||||
SetBorder(true).
|
SetBorder(true).
|
||||||
SetTitleColor(tcell.ColorAqua)
|
SetTitleColor(tcell.ColorAqua)
|
||||||
|
|
||||||
|
// Select Albums Form
|
||||||
|
selectAlbumsForm := tview.NewForm()
|
||||||
|
configSelectedAlbums := config.Strings(CONFIG_KEY_ALBUMS_SELECTED)
|
||||||
|
for _, album := range albums {
|
||||||
|
albumSelected := false
|
||||||
|
for _, configSelectedAlbum := range configSelectedAlbums {
|
||||||
|
if configSelectedAlbum == "/" {
|
||||||
|
configSelectedAlbum = "Main Folder"
|
||||||
|
}
|
||||||
|
if album == configSelectedAlbum {
|
||||||
|
albumSelected = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selectAlbumsForm.AddCheckbox(album, albumSelected, nil)
|
||||||
|
}
|
||||||
|
selectAlbumsForm.AddButton("Apply", nil)
|
||||||
|
selectAlbumsForm.AddButton("Cancel", func() {
|
||||||
|
main.Clear()
|
||||||
|
app.SetFocus(menu)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Slide Interval Form
|
||||||
|
intervalsForm := tview.NewForm()
|
||||||
|
configSlideInterval := config.String(CONFIG_KEY_SLIDESHOW_INTERVAL)
|
||||||
|
configRestartInterval := config.String(CONFIG_KEY_SLIDESHOW_RESTART_INTERVAL)
|
||||||
|
intervalsForm.AddInputField("Slide", configSlideInterval, 0, nil, nil)
|
||||||
|
intervalsForm.AddInputField("Restart/Reshuffle", configRestartInterval, 0, nil, nil)
|
||||||
|
intervalsForm.AddButton("Apply", nil)
|
||||||
|
intervalsForm.AddButton("Cancel", func() {
|
||||||
|
main.Clear()
|
||||||
|
app.SetFocus(menu)
|
||||||
|
})
|
||||||
|
|
||||||
// WiFi Config Form
|
// WiFi Config Form
|
||||||
wifiConfigForm := tview.NewForm()
|
wifiConfigForm := tview.NewForm()
|
||||||
wifiConfigAccessPoint := ""
|
wifiConfigAccessPoint := ""
|
||||||
|
@ -185,13 +220,14 @@ func ConfigGui() {
|
||||||
app.SetFocus(menu)
|
app.SetFocus(menu)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Select Albums Form
|
// HDMI On/Off Form
|
||||||
selectAlbumsForm := tview.NewForm()
|
hdmiForm := tview.NewForm()
|
||||||
for _, album := range albums {
|
configHDMIOff := config.String(CONFIG_KEY_HDMI_OFF)
|
||||||
selectAlbumsForm.AddCheckbox(album, true, nil)
|
configHDMIOn := config.String(CONFIG_KEY_HDMI_ON)
|
||||||
}
|
hdmiForm.AddInputField("HDMI Off Schedule", configHDMIOff, 0, nil, nil)
|
||||||
selectAlbumsForm.AddButton("Apply", nil)
|
hdmiForm.AddInputField("HDMI On Schedule", configHDMIOn, 0, nil, nil)
|
||||||
selectAlbumsForm.AddButton("Cancel", func() {
|
hdmiForm.AddButton("Apply", nil)
|
||||||
|
hdmiForm.AddButton("Cancel", func() {
|
||||||
main.Clear()
|
main.Clear()
|
||||||
app.SetFocus(menu)
|
app.SetFocus(menu)
|
||||||
})
|
})
|
||||||
|
@ -204,12 +240,24 @@ func ConfigGui() {
|
||||||
main.AddItem(selectAlbumsForm, 0, 1, true)
|
main.AddItem(selectAlbumsForm, 0, 1, true)
|
||||||
app.SetFocus(selectAlbumsForm)
|
app.SetFocus(selectAlbumsForm)
|
||||||
}
|
}
|
||||||
if title == "Configure WiFi" {
|
if title == "WiFi" {
|
||||||
main.SetTitle("Configure WiFi")
|
main.SetTitle("Configure WiFi")
|
||||||
main.Clear()
|
main.Clear()
|
||||||
main.AddItem(wifiConfigForm, 0, 1, true)
|
main.AddItem(wifiConfigForm, 0, 1, true)
|
||||||
app.SetFocus(wifiConfigForm)
|
app.SetFocus(wifiConfigForm)
|
||||||
}
|
}
|
||||||
|
if title == "Intervals" {
|
||||||
|
main.SetTitle("Configure Intervals")
|
||||||
|
main.Clear()
|
||||||
|
main.AddItem(intervalsForm, 0, 1, true)
|
||||||
|
app.SetFocus(intervalsForm)
|
||||||
|
}
|
||||||
|
if title == "HDMI On/Off" {
|
||||||
|
main.SetTitle("Configure HDMI On/Off")
|
||||||
|
main.Clear()
|
||||||
|
main.AddItem(hdmiForm, 0, 1, true)
|
||||||
|
app.SetFocus(hdmiForm)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Side bar fields
|
// Side bar fields
|
||||||
|
@ -364,9 +412,14 @@ func ConfigGui() {
|
||||||
// Override some of the default behavior so up/dn move between fields in forms
|
// Override some of the default behavior so up/dn move between fields in forms
|
||||||
// Per API GetFocusedItemIndex on a form will be -1 if a form item isn't currently focused
|
// Per API GetFocusedItemIndex on a form will be -1 if a form item isn't currently focused
|
||||||
// We use this as a bit of a cheat to figure out if we're inside of a form that needs better nav options for users (ie. tab doesn't exist on a remote)
|
// We use this as a bit of a cheat to figure out if we're inside of a form that needs better nav options for users (ie. tab doesn't exist on a remote)
|
||||||
wifiField, wifiButton := wifiConfigForm.GetFocusedItemIndex()
|
|
||||||
albumField, albumButton := selectAlbumsForm.GetFocusedItemIndex()
|
albumField, albumButton := selectAlbumsForm.GetFocusedItemIndex()
|
||||||
if wifiField != -1 || wifiButton != -1 || albumField != -1 || albumButton != -1 {
|
intervalField, intervalButton := intervalsForm.GetFocusedItemIndex()
|
||||||
|
wifiField, wifiButton := wifiConfigForm.GetFocusedItemIndex()
|
||||||
|
hdmiField, hdmiButton := hdmiForm.GetFocusedItemIndex()
|
||||||
|
if (wifiField != -1 || wifiButton != -1 ||
|
||||||
|
albumField != -1 || albumButton != -1 ||
|
||||||
|
intervalField != -1 || intervalButton != -1 ||
|
||||||
|
hdmiField != -1 || hdmiButton != -1) {
|
||||||
switch event.Key() {
|
switch event.Key() {
|
||||||
case tcell.KeyUp:
|
case tcell.KeyUp:
|
||||||
return tcell.NewEventKey(tcell.KeyBacktab, 0, event.Modifiers())
|
return tcell.NewEventKey(tcell.KeyBacktab, 0, event.Modifiers())
|
||||||
|
|
24
ui/constants.go
Normal file
24
ui/constants.go
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
package ui
|
||||||
|
|
||||||
|
const (
|
||||||
|
CLI_FLAG_CONFIG_ONLY = "config-ui-only"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
CONFIG_FILE_PATH = "/etc/default/pf.toml"
|
||||||
|
CONFIG_KEY_SLIDESHOW_INTERVAL = "slideshow.slideinterval"
|
||||||
|
CONFIG_KEY_SLIDESHOW_RESTART_INTERVAL = "slideshow.restartinterval"
|
||||||
|
CONFIG_KEY_HDMI_OFF = "hdmi.off"
|
||||||
|
CONFIG_KEY_HDMI_ON = "hdmi.on"
|
||||||
|
CONFIG_KEY_ALBUMS_ROOT = "albums.root"
|
||||||
|
CONFIG_KEY_ALBUMS_SELECTED = "albums.selected"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DEFAULT_SLIDESHOW_INTERVAL = "300s"
|
||||||
|
DEFAULT_SLIDESHOW_RESTART_INTERVAL = "7d"
|
||||||
|
DEFAULT_HDMI_OFF = "*-*-* 00:00:00"
|
||||||
|
DEFAULT_HDMI_ON = "*-*-* 06:00:00"
|
||||||
|
DEFAULT_ALBUMS_ROOT = "/tank/pictures"
|
||||||
|
DEFAULT_ALBUM_SELECTED = "/"
|
||||||
|
)
|
|
@ -9,14 +9,14 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/eiannone/keyboard"
|
"github.com/eiannone/keyboard"
|
||||||
|
"github.com/knadh/koanf"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CMD_FIM = "/usr/local/bin/pf-fim.sh"
|
CMD_FIM = "/usr/local/bin/pf-fim.sh"
|
||||||
SLIDESHOW_INTERVAL = 300 * time.Second
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Slideshow() {
|
func Slideshow(config *koanf.Koanf) {
|
||||||
// fim placeholder so we can operate on it when a exit slideshow is received
|
// fim placeholder so we can operate on it when a exit slideshow is received
|
||||||
var fim *exec.Cmd = nil
|
var fim *exec.Cmd = nil
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ func Slideshow() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Advance slideshow every interval as defined in const()
|
// Advance slideshow every interval as defined in const()
|
||||||
ticker := time.NewTicker(SLIDESHOW_INTERVAL)
|
ticker := time.NewTicker(config.Duration(CONFIG_KEY_SLIDESHOW_INTERVAL))
|
||||||
stop_ticker := make(chan struct{})
|
stop_ticker := make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
|
@ -68,7 +68,6 @@ func Slideshow() {
|
||||||
if event.Err != nil {
|
if event.Err != nil {
|
||||||
log.Fatalf("Error listening to key events : %s", err)
|
log.Fatalf("Error listening to key events : %s", err)
|
||||||
}
|
}
|
||||||
log.Printf("You pressed: key %X\n", event.Key)
|
|
||||||
|
|
||||||
// Keys for fim event management (previous/next in particular)
|
// Keys for fim event management (previous/next in particular)
|
||||||
fimKey := ""
|
fimKey := ""
|
||||||
|
@ -100,7 +99,7 @@ func Slideshow() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error controlling fim : %s", err)
|
log.Fatalf("Error controlling fim : %s", err)
|
||||||
}
|
}
|
||||||
ticker.Reset(SLIDESHOW_INTERVAL)
|
ticker.Reset(config.Duration(CONFIG_KEY_SLIDESHOW_INTERVAL))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue