Skip to content

Commit

Permalink
Showing 12 changed files with 1,231 additions and 27 deletions.
42 changes: 42 additions & 0 deletions cmd/sni/apps.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# This file defines application shortcuts for the Applications menu.
# To install, copy this file to your configuration directory:
# On MacOS and Linux, this is "$HOME/.sni/"
# On Windows, this is "%LOCALAPPDATA%/sni/"

# `apps` is a list of application shortcuts
apps:

- # `name` is what is displayed in the Applications menu:
name: RetroArch
# `os` specifies that this app is only launchable on this particular operating system
# if `os` is missing/empty, then the Application will appear on all operating systems.
# valid values are:
# "windows" = Windows
# "linux" = Linux
# "darwin" = MacOS
os: darwin
# `path` is the location of the executable to open:
# On MacOS, app bundle folders that end in .app are launched via `open -a <path> <args...>`
# On Windows and Linux, executable files are launched normally
path: /Applications/RetroArch.app

- name: RetroArch
os: windows
path: C:\RetroArch-Win64\RetroArch.exe

- name: OpenTracker
os: darwin
# `dir` is the current directory that the executable is launched from:
dir: $HOME/Developer/me/alttpo/OpenTracker/OpenTracker/bin/Debug/net5.0
# `path` does not have to be an absolute path, and could be found in the system lookup $PATH
path: dotnet
# `args` is the list of arguments passed to the application:
args:
- OpenTracker.dll

- name: SNI Home Page
# `url` will open the given URL when clicked in the menu:
# On MacOS, URLs are launched via `open <url>`
# On Windows, URLs are launched via `start <url>`
# On Linux, URLs are launched via `xdg-open <url>`
url: https://github.com/alttpo/sni
121 changes: 121 additions & 0 deletions cmd/sni/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package config

import (
"fmt"
"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
"log"
"os"
"path/filepath"
"runtime"
"sni/ob"
)

var (
ConfigObservable ob.Observable
configObservable = ob.NewObservable()
ConfigPath string

AppsObservable ob.Observable
appsObservable = ob.NewObservable()
AppsPath string
)

var VerboseLogging bool = false

var (
Config *viper.Viper = viper.New()
Apps *viper.Viper = viper.New()
)

func Load() {
log.Printf("config: load\n")

loadConfig()
loadApps()
}

func Save() {
var err error

log.Printf("config: save\n")

err = Config.WriteConfigAs(ConfigPath)
if err != nil {
log.Printf("config: save: %s\n", err)
return
}
}

func loadConfig() {
ConfigObservable = configObservable

// load configuration:
Config.SetEnvPrefix("SNI")
configFilename := "config"
Config.SetConfigName(configFilename)
Config.SetConfigType("yaml")
if runtime.GOOS == "windows" {
ConfigPath = os.ExpandEnv("$LOCALAPPDATA/sni/")
_ = os.Mkdir(ConfigPath, 0644|os.ModeDir)
Config.AddConfigPath(ConfigPath)
} else {
ConfigPath = os.ExpandEnv("$HOME/.sni/")
Config.AddConfigPath(ConfigPath)
}
ConfigPath = filepath.Join(ConfigPath, fmt.Sprintf("%s.yaml", configFilename))

Config.OnConfigChange(func(_ fsnotify.Event) {
log.Printf("config: %s.yaml modified\n", configFilename)
configObservable.ObjectPublish(Config)
})
Config.WatchConfig()

err := Config.ReadInConfig()
if err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
// no problem.
} else {
log.Printf("%s\n", err)
}
return
}

configObservable.ObjectPublish(Config)
}

func loadApps() {
AppsObservable = appsObservable

// load configuration:
appsFilename := "apps"
Apps.SetConfigName(appsFilename)
Apps.SetConfigType("yaml")
if runtime.GOOS == "windows" {
AppsPath = os.ExpandEnv("$LOCALAPPDATA/sni/")
_ = os.Mkdir(AppsPath, 0644|os.ModeDir)
Apps.AddConfigPath(AppsPath)
} else {
AppsPath = os.ExpandEnv("$HOME/.sni/")
Apps.AddConfigPath(AppsPath)
}
AppsPath = filepath.Join(ConfigPath, fmt.Sprintf("%s.yaml", appsFilename))

Apps.OnConfigChange(func(_ fsnotify.Event) {
log.Printf("config: %s.yaml modified\n", appsFilename)
appsObservable.ObjectPublish(Apps)
})
Apps.WatchConfig()

err := Apps.ReadInConfig()
if err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
// no problem.
} else {
log.Printf("%s\n", err)
}
return
}

appsObservable.ObjectPublish(Apps)
}
7 changes: 4 additions & 3 deletions cmd/sni/main.go
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@ import (
"net/http"
"os"
"path/filepath"
"sni/cmd/sni/config"
"sni/cmd/sni/tray"
"sni/snes/services/grpcimpl"
"sni/snes/services/usb2snes"
@@ -38,7 +39,7 @@ var (
cpuprofile = flag.String("cpuprofile", "", "start pprof profiler on addr:port")
)

func init() {
func main() {
log.SetFlags(log.LstdFlags | log.Lmicroseconds | log.LUTC)

ts := time.Now().Format("2006-01-02T15:04:05.000Z")
@@ -53,9 +54,7 @@ func init() {
log.Printf("sni %s %s built on %s by %s", version, commit, date, builtBy)
log.Printf("logging to '%s'\n", logPath)
log.SetOutput(io.MultiWriter(os.Stderr, logFile))
}

func main() {
flag.Parse()
if *cpuprofile != "" {
go func() {
@@ -64,6 +63,8 @@ func main() {
}()
}

config.Load()

// explicitly initialize all the drivers:
fxpakpro.DriverInit()
luabridge.DriverInit()
77 changes: 77 additions & 0 deletions cmd/sni/tray/launch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package tray

import (
"log"
"os"
"os/exec"
"path/filepath"
"runtime"
)

type appConfig struct {
Name string
Tooltip string

Os string

Dir string
Path string
Args []string

Url string
}

func launch(app *appConfig) {
path := app.Path
path = os.ExpandEnv(path)
cleanPath := filepath.Clean(path)

args := app.Args[:]
// expand environment variables like `$SNI_USB2SNES_LISTEN_HOST`:
for j, arg := range args {
args[j] = os.ExpandEnv(arg)
}

dir := app.Dir
dir = os.ExpandEnv(dir)

if app.Url != "" {
log.Printf("open: %s\n", app.Url)

var cmd *exec.Cmd
if runtime.GOOS == "darwin" {
cmd = exec.Command("open", app.Url)
} else if runtime.GOOS == "windows" {
cmd = exec.Command("start", app.Url)
} else {
cmd = exec.Command("xdg-open", app.Url)
}

err := cmd.Start()
if err != nil {
log.Printf("open: %s\n", err)
return
}

return
}

if runtime.GOOS == "darwin" {
if filepath.Ext(cleanPath) == ".app" {
// open app bundles with "open" command:
if fi, err := os.Stat(cleanPath); err == nil && fi.IsDir() {
args = append([]string{"-a", path}, args...)
path = "open"
}
}
}

log.Printf("open: %s %s\n", path, args)
cmd := exec.Command(path, args...)
cmd.Dir = dir
err := cmd.Start()
if err != nil {
log.Printf("open: %s\n", err)
return
}
}
Loading

0 comments on commit 2c7edac

Please sign in to comment.