Add option to disable remembering app state
This commit is contained in:
parent
eec273682c
commit
fd60e6b054
10 changed files with 80 additions and 27 deletions
|
@ -1,5 +1,6 @@
|
|||
0.1.9:
|
||||
- Remember working directory, queue, playing file and position
|
||||
- Add option to clear queue
|
||||
|
||||
0.1.8:
|
||||
- Allow reordering interface elements
|
||||
|
|
|
@ -18,6 +18,7 @@ configuration options and their defaults.
|
|||
* **Pause** Space
|
||||
* **Queue** Q
|
||||
* **Delete from queue** D
|
||||
* **Clear queue** Ctrl+U
|
||||
* **Toggle focused list** Tab
|
||||
* **Browse items** J/K, Down/Up and PageDown/PageUp
|
||||
* **Previous track** P
|
||||
|
@ -35,6 +36,8 @@ layout: main,queue,playing
|
|||
|
||||
volume: 100
|
||||
|
||||
remember: true
|
||||
|
||||
input:
|
||||
select:
|
||||
- 'Enter'
|
||||
|
@ -46,6 +49,8 @@ input:
|
|||
- 'q'
|
||||
delete:
|
||||
- 'd'
|
||||
clear-queue:
|
||||
- 'Ctrl+u'
|
||||
focus-next:
|
||||
- 'Tab'
|
||||
hidden-folders:
|
||||
|
|
|
@ -3,6 +3,13 @@
|
|||
|
||||
Audio player
|
||||
|
||||
## Features
|
||||
|
||||
- Uses a small amount of resources
|
||||
- Files are read in chunks
|
||||
- Remembers playing song and queue on exit
|
||||
- Supports FLAC, MP3, OGG and WAV files
|
||||
|
||||
## Screenshot
|
||||
|
||||
[![](https://ditty.rocketnine.space/static/screenshot2.png)](https://ditty.rocketnine.space/static/screenshot2.png)
|
||||
|
|
13
config.go
13
config.go
|
@ -6,6 +6,7 @@ type appConfig struct {
|
|||
Input map[string][]string // Keybinds
|
||||
Layout string
|
||||
Volume int // Starting volume
|
||||
Remember bool
|
||||
Dir string
|
||||
QueueFiles []*LibraryEntry
|
||||
QueuePlaying int
|
||||
|
@ -13,8 +14,16 @@ type appConfig struct {
|
|||
}
|
||||
|
||||
var config = &appConfig{
|
||||
Layout: defaultLayout,
|
||||
Volume: defaultVolume,
|
||||
Layout: defaultLayout,
|
||||
Volume: defaultVolume,
|
||||
Remember: true,
|
||||
}
|
||||
|
||||
func clearAppState() {
|
||||
config.Dir = ""
|
||||
config.QueueFiles = nil
|
||||
config.QueuePlaying = 0
|
||||
config.AudioPosition = 0
|
||||
}
|
||||
|
||||
func saveAppState() {
|
||||
|
|
10
go.mod
10
go.mod
|
@ -7,7 +7,7 @@ replace github.com/faiface/beep => github.com/cswank/beep v0.0.0-20210131195430-
|
|||
require (
|
||||
code.rocketnine.space/tslocum/cbind v0.1.5
|
||||
code.rocketnine.space/tslocum/cview v1.5.4
|
||||
code.rocketnine.space/tslocum/ez v0.0.0-20210502054046-e1e0d1009c8f
|
||||
code.rocketnine.space/tslocum/ez v0.0.0-20210506053631-12ed6a7c1375
|
||||
github.com/dhowden/tag v0.0.0-20201120070457-d52dcb253c63
|
||||
github.com/faiface/beep v1.0.2
|
||||
github.com/gdamore/tcell/v2 v2.2.1
|
||||
|
@ -16,9 +16,9 @@ require (
|
|||
github.com/jfreymuth/oggvorbis v1.0.3 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.12
|
||||
github.com/mewkiz/pkg v0.0.0-20210112042322-0b163ae15d52 // indirect
|
||||
golang.org/x/exp v0.0.0-20210430132503-b698a44fee45 // indirect
|
||||
golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb // indirect
|
||||
golang.org/x/exp v0.0.0-20210503015746-b3083d562e1d // indirect
|
||||
golang.org/x/image v0.0.0-20210504121937-7319ad40d33e // indirect
|
||||
golang.org/x/mobile v0.0.0-20210220033013-bdb1ca9a1e08 // indirect
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887 // indirect
|
||||
golang.org/x/term v0.0.0-20210429154555-c04ba851c2a4 // indirect
|
||||
golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6 // indirect
|
||||
golang.org/x/term v0.0.0-20210503060354-a79de5458b56 // indirect
|
||||
)
|
||||
|
|
20
go.sum
20
go.sum
|
@ -2,8 +2,8 @@ code.rocketnine.space/tslocum/cbind v0.1.5 h1:i6NkeLLNPNMS4NWNi3302Ay3zSU6MrqOT+
|
|||
code.rocketnine.space/tslocum/cbind v0.1.5/go.mod h1:LtfqJTzM7qhg88nAvNhx+VnTjZ0SXBJtxBObbfBWo/M=
|
||||
code.rocketnine.space/tslocum/cview v1.5.4 h1:zBUFAanViudrAw8ZCqNxaufqrYL6a7F1AkkIClXIzYo=
|
||||
code.rocketnine.space/tslocum/cview v1.5.4/go.mod h1:JjgoZi3b528SaV923oQq14PGUCTE/g/6iggnDUxsChE=
|
||||
code.rocketnine.space/tslocum/ez v0.0.0-20210502054046-e1e0d1009c8f h1:zvqqu4UY7lwNo6thsoRYeUZm9qqZ0F66diIEVhN9oDQ=
|
||||
code.rocketnine.space/tslocum/ez v0.0.0-20210502054046-e1e0d1009c8f/go.mod h1:SQrM+bQ4eZdyAVTxuF2BNnyAnojHP6Kcmm2vMszoFWw=
|
||||
code.rocketnine.space/tslocum/ez v0.0.0-20210506053631-12ed6a7c1375 h1:GYTFUS0slXVZ78wCAP0qh5u9ENc+5VhvyFGojnwYRA4=
|
||||
code.rocketnine.space/tslocum/ez v0.0.0-20210506053631-12ed6a7c1375/go.mod h1:SQrM+bQ4eZdyAVTxuF2BNnyAnojHP6Kcmm2vMszoFWw=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
|
@ -93,13 +93,13 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
|||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
|
||||
golang.org/x/exp v0.0.0-20210430132503-b698a44fee45 h1:XqRf5+0Xvcb6/S21xhk9fABamGZ7gSWdIPyRv2EEhBc=
|
||||
golang.org/x/exp v0.0.0-20210430132503-b698a44fee45/go.mod h1:cJRhTyGheUtAt9+V1LK3LYoFneBlmiX5bePSkB17RVE=
|
||||
golang.org/x/exp v0.0.0-20210503015746-b3083d562e1d h1:GVdk3fETn7OIrVsO9oikNOn5qWu8EcgkTtcDD9IGyQ4=
|
||||
golang.org/x/exp v0.0.0-20210503015746-b3083d562e1d/go.mod h1:MSdmUWF4ZWBPSUbgUX/gaau5kvnbkSs9pgtY6B9JXDE=
|
||||
golang.org/x/image v0.0.0-20190220214146-31aff87c08e9/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb h1:fqpd0EBDzlHRCjiphRR5Zo/RSWWQlWv34418dnEixWk=
|
||||
golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20210504121937-7319ad40d33e h1:PzJMNfFQx+QO9hrC1GwZ4BoPGeNGhfeQEgcQFArEjPk=
|
||||
golang.org/x/image v0.0.0-20210504121937-7319ad40d33e/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
|
@ -130,13 +130,13 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210309040221-94ec62e08169/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210331175145-43e1dd70ce54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887 h1:dXfMednGJh/SUUFjTLsWJz3P+TQt9qnR11GgeI3vWKs=
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6 h1:cdsMqa2nXzqlgs183pHxtvoVwU7CyzaCTAUOg94af4c=
|
||||
golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210317153231-de623e64d2a6/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210429154555-c04ba851c2a4 h1:UPou2i3GzKgi6igR+/0C5XyHKBngHxBp/CL5CQ0p3Zk=
|
||||
golang.org/x/term v0.0.0-20210429154555-c04ba851c2a4/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210503060354-a79de5458b56 h1:b8jxX3zqjpqb2LklXPzKSGJhzyxCOZSz8ncv8Nv+y7w=
|
||||
golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
|
|
4
gui.go
4
gui.go
|
@ -39,8 +39,8 @@ var (
|
|||
mainLock = new(sync.Mutex)
|
||||
|
||||
queueFiles []*LibraryEntry
|
||||
queueCursor = -1
|
||||
queuePlaying int
|
||||
queueCursor = -1 // Focused entry
|
||||
queuePlaying int // Playing entry
|
||||
|
||||
queueBuffer bytes.Buffer
|
||||
queueLock = new(sync.Mutex)
|
||||
|
|
|
@ -14,6 +14,7 @@ const (
|
|||
actionRefresh = "refresh"
|
||||
actionQueue = "queue"
|
||||
actionDelete = "delete"
|
||||
actionClearQueue = "clear-queue"
|
||||
actionFocusNext = "focus-next"
|
||||
actionToggleHidden = "hidden-folders"
|
||||
actionBrowseParent = "browse-parent"
|
||||
|
@ -35,6 +36,7 @@ var actionHandlers = map[string]func(){
|
|||
actionRefresh: listRefresh,
|
||||
actionQueue: listQueue,
|
||||
actionDelete: listDelete,
|
||||
actionClearQueue: clearQueue,
|
||||
actionFocusNext: toggleFocusedList,
|
||||
actionToggleHidden: listToggleHidden,
|
||||
actionBrowseParent: browseParent,
|
||||
|
@ -95,6 +97,7 @@ func setDefaultKeyBinds() {
|
|||
actionRefresh: {"r"},
|
||||
actionQueue: {"q"},
|
||||
actionDelete: {"d"},
|
||||
actionClearQueue: {"Ctrl+u"},
|
||||
actionFocusNext: {"Tab"},
|
||||
actionToggleHidden: {"."},
|
||||
actionBrowseParent: {"Backspace"},
|
||||
|
|
17
gui_list.go
17
gui_list.go
|
@ -159,6 +159,23 @@ func listDelete() {
|
|||
go app.QueueUpdateDraw(updateQueue)
|
||||
}
|
||||
|
||||
func clearQueue() {
|
||||
queueLock.Lock()
|
||||
defer queueLock.Unlock()
|
||||
|
||||
if len(queueFiles) > queuePlaying {
|
||||
queueFiles = []*LibraryEntry{queueFiles[queuePlaying]}
|
||||
} else {
|
||||
queueFiles = nil
|
||||
}
|
||||
queuePlaying = 0
|
||||
|
||||
app.QueueUpdateDraw(func() {
|
||||
queueList.SetCurrentItem(0)
|
||||
updateQueue()
|
||||
})
|
||||
}
|
||||
|
||||
func selectedMainEntry() *LibraryEntry {
|
||||
cursor := mainList.GetCurrentItemIndex()
|
||||
if cursor < 0 || cursor-1 > len(mainFiles) {
|
||||
|
|
27
main.go
27
main.go
|
@ -98,8 +98,15 @@ func main() {
|
|||
defer pprof.StopCPUProfile()
|
||||
}
|
||||
|
||||
ez.SetAppName("ditty")
|
||||
err := ez.ReadConfig(config, configPath)
|
||||
if configPath == "" {
|
||||
var err error
|
||||
configPath, err = ez.DefaultConfigPath("ditty")
|
||||
if err != nil {
|
||||
log.Fatalf("failed to determine default configuration file path: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
err := ez.Deserialize(config, configPath)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to read configuration file: %s", err)
|
||||
}
|
||||
|
@ -150,10 +157,10 @@ func main() {
|
|||
|
||||
startPath := strings.Join(flag.Args(), " ")
|
||||
if startPath == "" {
|
||||
if config.Dir != "" {
|
||||
startPath = config.Dir
|
||||
} else if restrictLibrary != "" {
|
||||
if restrictLibrary != "" {
|
||||
startPath = restrictLibrary
|
||||
} else if config.Remember && config.Dir != "" {
|
||||
startPath = config.Dir
|
||||
} else {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil || wd == "" {
|
||||
|
@ -190,7 +197,7 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
if config.QueueFiles != nil {
|
||||
if config.Remember && config.QueueFiles != nil {
|
||||
queueFiles = config.QueueFiles
|
||||
app.QueueUpdateDraw(func() {
|
||||
updateQueue()
|
||||
|
@ -213,8 +220,12 @@ func main() {
|
|||
for {
|
||||
select {
|
||||
case <-done:
|
||||
saveAppState()
|
||||
ez.SaveConfig(config, configPath) // Failing isn't an issue, this could be logged though
|
||||
if config.Remember {
|
||||
saveAppState()
|
||||
} else {
|
||||
clearAppState()
|
||||
}
|
||||
ez.Serialize(config, configPath) // Failing isn't an issue, this could be logged though
|
||||
|
||||
if streamFd != nil {
|
||||
streamFd.Close()
|
||||
|
|
Loading…
Reference in a new issue