Fix #193: exit and reactivate existing instance if another instance running

This commit is contained in:
Drew Weymouth
2023-06-17 17:00:47 -07:00
parent 0906d118b4
commit 20e4d8c5f2
5 changed files with 57 additions and 6 deletions
+53 -3
View File
@@ -12,14 +12,22 @@ import (
"github.com/dweymouth/supersonic/backend/util"
"github.com/dweymouth/supersonic/player"
"github.com/dweymouth/supersonic/sharedutil"
"github.com/fsnotify/fsnotify"
"github.com/google/uuid"
"github.com/20after4/configdir"
"github.com/zalando/go-keyring"
)
const (
sessionDir = "session"
sessionLockFile = ".lock"
sessionActivateFile = ".activate"
)
var (
ErrNoServers = errors.New("no servers set up")
ErrNoServers = errors.New("no servers set up")
ErrAnotherInstance = errors.New("another instance is running")
)
type App struct {
@@ -29,6 +37,7 @@ type App struct {
PlaybackManager *PlaybackManager
Player *player.Player
UpdateChecker UpdateChecker
OnReactivate func()
appName string
appVersionTag string
@@ -42,15 +51,34 @@ func (a *App) VersionTag() string {
}
func StartupApp(appName, appVersionTag, configFile, latestReleaseURL string) (*App, error) {
a := &App{appName: appName, appVersionTag: appVersionTag, configFile: configFile}
a.bgrndCtx, a.cancel = context.WithCancel(context.Background())
sessionPath := configdir.LocalConfig(appName, sessionDir)
if _, err := os.Stat(path.Join(sessionPath, sessionLockFile)); err == nil {
log.Println("Another instance is running. Reactivating it and exiting...")
if f, err := os.Create(path.Join(sessionPath, sessionActivateFile)); err == nil {
f.Close()
}
return nil, ErrAnotherInstance
}
log.Printf("Starting %s...", appName)
log.Printf("Using config dir: %s", configdir.LocalConfig(appName))
log.Printf("Using cache dir: %s", configdir.LocalCache(appName))
a := &App{appName: appName, appVersionTag: appVersionTag, configFile: configFile}
a.bgrndCtx, a.cancel = context.WithCancel(context.Background())
a.readConfig()
if !a.Config.Application.AllowMultiInstance {
log.Println("Creating session lock file")
os.MkdirAll(sessionPath, 0770)
if f, err := os.Create(path.Join(sessionPath, sessionLockFile)); err == nil {
f.Close()
} else {
log.Printf("error creating session file: %s", err.Error())
}
a.startSessionWatcher(sessionPath)
}
a.UpdateChecker = NewUpdateChecker(appVersionTag, latestReleaseURL, &a.Config.Application.LastCheckedVersion)
a.UpdateChecker.Start(a.bgrndCtx, 24*time.Hour)
@@ -87,6 +115,27 @@ func (a *App) readConfig() {
a.Config = cfg
}
func (a *App) startSessionWatcher(sessionPath string) {
if sessionWatch, err := fsnotify.NewWatcher(); err == nil {
sessionWatch.Add(sessionPath)
go func() {
for {
select {
case <-a.bgrndCtx.Done():
return
case event, ok := <-sessionWatch.Events:
if ok && event.Op == fsnotify.Create && path.Base(event.Name) == sessionActivateFile {
os.Remove(path.Join(sessionPath, sessionActivateFile))
if a.OnReactivate != nil {
a.OnReactivate()
}
}
}
}
}()
}
}
func (a *App) initMPV() error {
p := player.NewWithClientName(a.appName)
c := a.Config.LocalPlayback
@@ -163,6 +212,7 @@ func (a *App) Shutdown() {
a.cancel()
a.Player.Destroy()
a.Config.WriteConfigFile(a.configPath())
os.RemoveAll(configdir.LocalConfig(a.appName, sessionDir))
}
func (a *App) configPath() string {
+2
View File
@@ -28,6 +28,7 @@ type AppConfig struct {
EnableSystemTray bool
CloseToSystemTray bool
StartupPage string
AllowMultiInstance bool
// Experimental - may be removed in future
FontNormalTTF string
@@ -119,6 +120,7 @@ func DefaultConfig(appVersionTag string) *Config {
EnableSystemTray: true,
CloseToSystemTray: false,
StartupPage: "Albums",
AllowMultiInstance: false,
},
AlbumPage: AlbumPageConfig{
TracklistColumns: []string{"Artist", "Time", "Plays", "Favorite", "Rating"},
+1 -1
View File
@@ -8,6 +8,7 @@ require (
github.com/20after4/configdir v0.1.1
github.com/dweymouth/go-mpv v0.0.0-20230406003141-7f1858e503ee
github.com/dweymouth/go-subsonic v0.0.0-20230614154319-792d18c75fb4
github.com/fsnotify/fsnotify v1.5.4
github.com/google/uuid v1.3.0
github.com/pelletier/go-toml/v2 v2.0.8
github.com/zalando/go-keyring v0.2.1
@@ -20,7 +21,6 @@ require (
github.com/danieljoos/wincred v1.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fredbi/uri v0.1.0 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/fyne-io/gl-js v0.0.0-20220119005834-d2da28d9ccfe // indirect
github.com/fyne-io/glfw-js v0.0.0-20220120001248-ee7290d23504 // indirect
github.com/fyne-io/image v0.0.0-20220602074514-4956b0afb3d2 // indirect
-2
View File
@@ -78,8 +78,6 @@ github.com/dweymouth/fyne/v2 v2.3.0-rc1.0.20230505012127-ca61c153b2a5 h1:uXbHzg9
github.com/dweymouth/fyne/v2 v2.3.0-rc1.0.20230505012127-ca61c153b2a5/go.mod h1:X2+NrR+62mvAiAt2fwKT7035zQsE77KVV1NlvWo4vW8=
github.com/dweymouth/go-mpv v0.0.0-20230406003141-7f1858e503ee h1:ZGyJ6wp7CAfT31BugypcF/TPKEy2RrGR9JFq1JOjOpY=
github.com/dweymouth/go-mpv v0.0.0-20230406003141-7f1858e503ee/go.mod h1:Ov0ieN90M7i+0k3OxhA/g1dozGs+UcPHDsMKqPgRDk0=
github.com/dweymouth/go-subsonic v0.0.0-20230513020020-0790f53c2868 h1:403Dden/cdQyDM8ydonHLxTBPjgQXZ76PUfmBG92+Dw=
github.com/dweymouth/go-subsonic v0.0.0-20230513020020-0790f53c2868/go.mod h1:fUez6NFiEJiQTZizZ1BThZr5GJXAbigzGYjEPNm4tdI=
github.com/dweymouth/go-subsonic v0.0.0-20230614154319-792d18c75fb4 h1:cuyvB4GjTMBHKJwMJ/LFpuKfSVXuCheNj6fgxBa3m1Y=
github.com/dweymouth/go-subsonic v0.0.0-20230614154319-792d18c75fb4/go.mod h1:fUez6NFiEJiQTZizZ1BThZr5GJXAbigzGYjEPNm4tdI=
github.com/eclipse/paho.mqtt.golang v1.3.5/go.mod h1:eTzb4gxwwyWpqBUHGQZ4ABAV7+Jgm1PklsYT/eo8Hcc=
+1
View File
@@ -38,6 +38,7 @@ func main() {
h = 800
}
mainWindow := ui.NewMainWindow(fyneApp, displayName, appVersion, myApp, fyne.NewSize(w, h))
myApp.OnReactivate = mainWindow.Show
go func() {
// TODO: There is a race condition with laying out the window before the