Wire up more of the config ; apply hdmi on/off schedules on save
This commit is contained in:
parent
769029b9c2
commit
15dfaa31f9
|
@ -12,6 +12,7 @@ import (
|
|||
"github.com/knadh/koanf/providers/posflag"
|
||||
flag "github.com/spf13/pflag"
|
||||
|
||||
pfconfig "git.kemonine.info/PiFrame/config"
|
||||
"git.kemonine.info/PiFrame/ui"
|
||||
)
|
||||
|
||||
|
@ -23,8 +24,8 @@ func main() {
|
|||
os.Exit(0)
|
||||
}
|
||||
// Command line flags
|
||||
f.Bool(ui.CLI_FLAG_CONFIG_ONLY, false, "Only show the config UI, NOT the slideshow")
|
||||
cliFlag := f.Lookup(ui.CLI_FLAG_CONFIG_ONLY)
|
||||
f.Bool(pfconfig.CLI_FLAG_CONFIG_ONLY, false, "Only show the config UI, NOT the slideshow")
|
||||
cliFlag := f.Lookup(pfconfig.CLI_FLAG_CONFIG_ONLY)
|
||||
if cliFlag != nil {
|
||||
cliFlag.NoOptDefVal = "true"
|
||||
}
|
||||
|
@ -36,17 +37,17 @@ func main() {
|
|||
|
||||
// Setup some defaults
|
||||
pfConfig.Load(confmap.Provider(map[string]interface{}{
|
||||
ui.CONFIG_KEY_SLIDESHOW_INTERVAL: ui.DEFAULT_SLIDESHOW_INTERVAL,
|
||||
ui.CONFIG_KEY_SLIDESHOW_RESTART_INTERVAL: ui.DEFAULT_SLIDESHOW_RESTART_INTERVAL,
|
||||
ui.CONFIG_KEY_HDMI_OFF: ui.DEFAULT_HDMI_OFF,
|
||||
ui.CONFIG_KEY_HDMI_ON: ui.DEFAULT_HDMI_ON,
|
||||
ui.CONFIG_KEY_ALBUMS_ROOT: ui.DEFAULT_ALBUMS_ROOT,
|
||||
ui.CONFIG_KEY_ALBUMS_SELECTED: []string{ui.DEFAULT_ALBUM_SELECTED},
|
||||
pfconfig.CONFIG_KEY_SLIDESHOW_INTERVAL: pfconfig.DEFAULT_SLIDESHOW_INTERVAL,
|
||||
pfconfig.CONFIG_KEY_SLIDESHOW_RESTART_INTERVAL: pfconfig.DEFAULT_SLIDESHOW_RESTART_INTERVAL,
|
||||
pfconfig.CONFIG_KEY_HDMI_OFF: pfconfig.DEFAULT_HDMI_OFF,
|
||||
pfconfig.CONFIG_KEY_HDMI_ON: pfconfig.DEFAULT_HDMI_ON,
|
||||
pfconfig.CONFIG_KEY_ALBUMS_ROOT: pfconfig.DEFAULT_ALBUMS_ROOT,
|
||||
pfconfig.CONFIG_KEY_ALBUMS_SELECTED: []string{pfconfig.DEFAULT_ALBUM_SELECTED},
|
||||
}, "."), nil)
|
||||
|
||||
// Bring in /etc/defaults/pf.toml if it exists
|
||||
configFileProvider := file.Provider(ui.CONFIG_FILE_PATH)
|
||||
_, err := os.Stat(ui.CONFIG_FILE_PATH)
|
||||
configFileProvider := file.Provider(pfconfig.CONFIG_FILE_PATH)
|
||||
_, err := os.Stat(pfconfig.CONFIG_FILE_PATH)
|
||||
if os.IsNotExist(err) {
|
||||
//log.Printf("%s does not exist, USING DEFAULTS", ui.CONFIG_FILE_PATH)
|
||||
} else {
|
||||
|
@ -70,13 +71,13 @@ func main() {
|
|||
log.Fatalf("Error loading command line flags : %s", err)
|
||||
}
|
||||
|
||||
if !pfConfig.Bool(ui.CLI_FLAG_CONFIG_ONLY) {
|
||||
if !pfConfig.Bool(pfconfig.CLI_FLAG_CONFIG_ONLY) {
|
||||
ui.Slideshow(pfConfig)
|
||||
}
|
||||
|
||||
// Reset the CLI flag so it's never writted to the config as 'true'
|
||||
pfConfig.Load(confmap.Provider(map[string]interface{}{
|
||||
ui.CLI_FLAG_CONFIG_ONLY: false,
|
||||
pfconfig.CLI_FLAG_CONFIG_ONLY: false,
|
||||
}, "."), nil)
|
||||
|
||||
ui.ConfigGui(pfConfig)
|
||||
|
|
3
config/README.md
Normal file
3
config/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# config
|
||||
|
||||
Mini module for working with PiFrame configuration file.
|
|
@ -1,4 +1,4 @@
|
|||
package ui
|
||||
package config
|
||||
|
||||
const (
|
||||
CLI_FLAG_CONFIG_ONLY = "config-ui-only"
|
71
ui/config.go
71
ui/config.go
|
@ -1,22 +1,25 @@
|
|||
package ui
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/gdamore/tcell"
|
||||
"github.com/guillermo/go.procmeminfo"
|
||||
"github.com/knadh/koanf"
|
||||
"github.com/knadh/koanf/parsers/toml"
|
||||
"github.com/knadh/koanf/providers/confmap"
|
||||
"github.com/rivo/tview"
|
||||
|
||||
"git.kemonine.info/PiFrame/config"
|
||||
"git.kemonine.info/PiFrame/utils"
|
||||
"git.kemonine.info/PiFrame/wifi"
|
||||
)
|
||||
|
@ -35,7 +38,7 @@ const (
|
|||
PAGE_POWEROFF = "PAGE_POWEROFF"
|
||||
)
|
||||
|
||||
func ConfigGui(config *koanf.Koanf) {
|
||||
func ConfigGui(pfconfig *koanf.Koanf) {
|
||||
// Memory info for status panel
|
||||
meminfo := &procmeminfo.MemInfo{}
|
||||
err := meminfo.Update()
|
||||
|
@ -67,7 +70,7 @@ func ConfigGui(config *koanf.Koanf) {
|
|||
|
||||
// Get list of all folders that can be used as albums
|
||||
var albums []string
|
||||
err = filepath.Walk(config.String(CONFIG_KEY_ALBUMS_ROOT), func(path string, fi os.FileInfo, err error) error {
|
||||
err = filepath.Walk(pfconfig.String(config.CONFIG_KEY_ALBUMS_ROOT), func(path string, fi os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -75,7 +78,7 @@ func ConfigGui(config *koanf.Koanf) {
|
|||
if strings.Contains(path, SYNCTHING_FOLDER_SKIP) {
|
||||
return nil
|
||||
}
|
||||
albumName := strings.TrimPrefix(path, config.String(CONFIG_KEY_ALBUMS_ROOT))
|
||||
albumName := strings.TrimPrefix(path, pfconfig.String(config.CONFIG_KEY_ALBUMS_ROOT))
|
||||
if albumName == "" {
|
||||
albumName = "Main Folder"
|
||||
}
|
||||
|
@ -166,7 +169,7 @@ func ConfigGui(config *koanf.Koanf) {
|
|||
|
||||
// Select Albums Form
|
||||
selectAlbumsForm := tview.NewForm()
|
||||
configSelectedAlbums := config.Strings(CONFIG_KEY_ALBUMS_SELECTED)
|
||||
configSelectedAlbums := pfconfig.Strings(config.CONFIG_KEY_ALBUMS_SELECTED)
|
||||
for _, album := range albums {
|
||||
albumSelected := false
|
||||
for _, configSelectedAlbum := range configSelectedAlbums {
|
||||
|
@ -187,8 +190,8 @@ func ConfigGui(config *koanf.Koanf) {
|
|||
|
||||
// Slide Interval Form
|
||||
intervalsForm := tview.NewForm()
|
||||
configSlideInterval := config.String(CONFIG_KEY_SLIDESHOW_INTERVAL)
|
||||
configRestartInterval := config.String(CONFIG_KEY_SLIDESHOW_RESTART_INTERVAL)
|
||||
configSlideInterval := pfconfig.String(config.CONFIG_KEY_SLIDESHOW_INTERVAL)
|
||||
configRestartInterval := pfconfig.String(config.CONFIG_KEY_SLIDESHOW_RESTART_INTERVAL)
|
||||
intervalsForm.AddInputField("Slide", configSlideInterval, 0, nil, func(value string) {
|
||||
configSlideInterval = value
|
||||
})
|
||||
|
@ -223,8 +226,8 @@ func ConfigGui(config *koanf.Koanf) {
|
|||
|
||||
// HDMI On/Off Form
|
||||
hdmiForm := tview.NewForm()
|
||||
configHDMIOff := config.String(CONFIG_KEY_HDMI_OFF)
|
||||
configHDMIOn := config.String(CONFIG_KEY_HDMI_ON)
|
||||
configHDMIOff := pfconfig.String(config.CONFIG_KEY_HDMI_OFF)
|
||||
configHDMIOn := pfconfig.String(config.CONFIG_KEY_HDMI_ON)
|
||||
hdmiForm.AddInputField("HDMI Off Schedule", configHDMIOff, 0, nil, func(value string) {
|
||||
configHDMIOff = value
|
||||
})
|
||||
|
@ -377,21 +380,49 @@ func ConfigGui(config *koanf.Koanf) {
|
|||
AddButtons([]string{"Yes", "Cancel"}).
|
||||
SetDoneFunc(func(buttonIndex int, buttonLabel string) {
|
||||
if buttonLabel == "Yes" {
|
||||
// Housekeeping var for data to be written to disk
|
||||
var hdmiForDisk bytes.Buffer
|
||||
|
||||
// Apply HDMI configuration (on/off)
|
||||
valueForTemplate := utils.SystemdTimer{OnCalendar: configHDMIOn}
|
||||
screenOn, err := template.New("screenon.systemd.timer").Parse(utils.SCREEN_ON_DOT_TIMER)
|
||||
if err != nil {
|
||||
log.Fatalf("Error setting up screen on systemd timer : %s", err)
|
||||
}
|
||||
err = screenOn.Execute(&hdmiForDisk, valueForTemplate)
|
||||
if err != nil {
|
||||
log.Fatalf("Error setting up screen on systemd timer : %s", err)
|
||||
}
|
||||
utils.WriteFile(utils.SCREEN_ON_TIMER_PATH, utils.SCREEN_ON_TIMER_PATH+".tmp", hdmiForDisk.Bytes())
|
||||
|
||||
valueForTemplate.OnCalendar = configHDMIOff
|
||||
hdmiForDisk.Truncate(0)
|
||||
screenOff, err := template.New("screenoff.systemd.timer").Parse(utils.SCREEN_OFF_DOT_TIMER)
|
||||
if err != nil {
|
||||
log.Fatalf("Error setting up screen off systemd timer : %s", err)
|
||||
}
|
||||
err = screenOff.Execute(&hdmiForDisk, valueForTemplate)
|
||||
if err != nil {
|
||||
log.Fatalf("Error setting up screen off systemd timer : %s", err)
|
||||
}
|
||||
utils.WriteFile(utils.SCREEN_OFF_TIMER_PATH, utils.SCREEN_OFF_TIMER_PATH+".tmp", hdmiForDisk.Bytes())
|
||||
|
||||
// Reload systemd units after applying HDMI config
|
||||
utils.SystemdDaemonReload()
|
||||
|
||||
// Apply configuration updates to main config manager prior to saving
|
||||
pfconfig.Load(confmap.Provider(map[string]interface{}{
|
||||
config.DEFAULT_HDMI_ON: configHDMIOn,
|
||||
config.DEFAULT_HDMI_OFF: configHDMIOff,
|
||||
}, "."), nil)
|
||||
|
||||
// Save configuration
|
||||
parser := toml.Parser()
|
||||
dataForDisk, err := config.Marshal(parser)
|
||||
configForDisk, err := pfconfig.Marshal(parser)
|
||||
if err != nil {
|
||||
log.Fatalf("Error preparing config for disk write : %s", err)
|
||||
}
|
||||
existingStat, err := os.Lstat(CONFIG_FILE_PATH)
|
||||
if err != nil {
|
||||
log.Fatalf("Error checking if config exists : %s", err)
|
||||
}
|
||||
if err := ioutil.WriteFile(CONFIG_FILE_PATH_TMP, dataForDisk, existingStat.Mode()); err != nil {
|
||||
log.Fatalf("Error writing temp config file : %s", err)
|
||||
}
|
||||
if err := os.Rename(CONFIG_FILE_PATH_TMP, CONFIG_FILE_PATH); err != nil {
|
||||
log.Fatalf("Error moving new config in place : %s", err)
|
||||
}
|
||||
utils.WriteFile(config.CONFIG_FILE_PATH, config.CONFIG_FILE_PATH_TMP, configForDisk)
|
||||
app.Stop()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ import (
|
|||
|
||||
"github.com/eiannone/keyboard"
|
||||
"github.com/knadh/koanf"
|
||||
|
||||
pfconfig "git.kemonine.info/PiFrame/config"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -32,7 +34,7 @@ func Slideshow(config *koanf.Koanf) {
|
|||
}
|
||||
|
||||
// Advance slideshow every interval as defined in const()
|
||||
ticker := time.NewTicker(config.Duration(CONFIG_KEY_SLIDESHOW_INTERVAL))
|
||||
ticker := time.NewTicker(config.Duration(pfconfig.CONFIG_KEY_SLIDESHOW_INTERVAL))
|
||||
stop_ticker := make(chan struct{})
|
||||
go func() {
|
||||
for {
|
||||
|
@ -99,7 +101,7 @@ func Slideshow(config *koanf.Koanf) {
|
|||
if err != nil {
|
||||
log.Fatalf("Error controlling fim : %s", err)
|
||||
}
|
||||
ticker.Reset(config.Duration(CONFIG_KEY_SLIDESHOW_INTERVAL))
|
||||
ticker.Reset(config.Duration(pfconfig.CONFIG_KEY_SLIDESHOW_INTERVAL))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
20
utils/files.go
Normal file
20
utils/files.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
func WriteFile(destinationPath string, tempPath string, dataForDisk []byte) {
|
||||
existingStat, err := os.Lstat(destinationPath)
|
||||
if err != nil {
|
||||
log.Fatalf("Error checking if file exists : %s", err)
|
||||
}
|
||||
if err := ioutil.WriteFile(tempPath, dataForDisk, existingStat.Mode()); err != nil {
|
||||
log.Fatalf("Error writing temp file : %s", err)
|
||||
}
|
||||
if err := os.Rename(tempPath, destinationPath); err != nil {
|
||||
log.Fatalf("Error moving new in place : %s", err)
|
||||
}
|
||||
}
|
28
utils/hdmi.go
Normal file
28
utils/hdmi.go
Normal file
|
@ -0,0 +1,28 @@
|
|||
package utils
|
||||
|
||||
type SystemdTimer struct {
|
||||
OnCalendar string
|
||||
}
|
||||
|
||||
const SCREEN_ON_DOT_TIMER = `
|
||||
[Unit]
|
||||
Description=Turn on display
|
||||
|
||||
[Timer]
|
||||
OnCalendar={{.OnCalendar}}
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
`
|
||||
const SCREEN_OFF_DOT_TIMER = `
|
||||
[Unit]
|
||||
Description=Turn off display
|
||||
|
||||
[Timer]
|
||||
OnCalendar={{.OnCalendar}}
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
`
|
23
utils/systemd.go
Normal file
23
utils/systemd.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
const (
|
||||
CMD_SYSTEMCTL = "/usr/bin/systemctl"
|
||||
)
|
||||
|
||||
const (
|
||||
SCREEN_ON_TIMER_PATH = "/etc/systemd/system/screen-on.timer"
|
||||
SCREEN_OFF_TIMER_PATH = "/etc/systemd/system/screen-off.timer"
|
||||
)
|
||||
|
||||
func SystemdDaemonReload() {
|
||||
// Reload systemd units
|
||||
err := exec.Command(CMD_SYSTEMCTL, "daemon-reload").Run()
|
||||
if err != nil {
|
||||
log.Fatalf("Error running %s : %s", CMD_SYSTEMCTL, err)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue