parent
c50589ef5f
commit
803053317a
10 changed files with 407 additions and 92 deletions
|
@ -10,12 +10,6 @@ fmt:
|
|||
- gofmt -l -s -e .
|
||||
- exit $(gofmt -l -s -e . | wc -l)
|
||||
|
||||
lint:
|
||||
stage: validate
|
||||
script:
|
||||
- go get -u golang.org/x/lint/golint
|
||||
- golint -set_exit_status
|
||||
|
||||
vet:
|
||||
stage: validate
|
||||
script:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
0.1.5:
|
||||
- Add initial volume configuration option and flag
|
||||
- Add queue feature
|
||||
- Use default terminal colors
|
||||
|
||||
0.1.4:
|
||||
|
|
|
@ -2,8 +2,9 @@ This document covers the [ditty](https://gitlab.com/tslocum/ditty)
|
|||
configuration options and their defaults.
|
||||
|
||||
# Options
|
||||
|
||||
|
||||
* **--buffer-size** Audio buffer size, defaults to 500ms.
|
||||
* **--autoplay-queue** Start playing when the queue is added to.
|
||||
* **--restrict-library** Restrict access to a folder and its subfolders.
|
||||
* **--fd** Write audio in WAV format to the specified file descriptor instead. This allows ditty to be used over ssh:
|
||||
* `ssh ditty.rocketnine.space -t 'ditty --fd=2' 2> >(aplay --quiet)`
|
||||
|
@ -13,13 +14,16 @@ configuration options and their defaults.
|
|||
|
||||
* **Select** Enter
|
||||
* **Pause** Space
|
||||
* **Refresh** R
|
||||
* **Toggle hidden folder visibility** .
|
||||
* **Browse parent folder and focus last** Backspace
|
||||
* **Queue** Q
|
||||
* **Delete from queue** D
|
||||
* **Toggle focused list** Tab
|
||||
* **Browse items** J/K, Down/Up and PageDown/PageUp
|
||||
* **Previous track** P
|
||||
* **Next track** N
|
||||
* **Volume** -/+/M
|
||||
* **Refresh** R
|
||||
* **Toggle hidden folder visibility** .
|
||||
* **Browse parent folder and focus last** Backspace
|
||||
* **Exit** Escape
|
||||
|
||||
# Default ~/.config/ditty/config.yaml
|
||||
|
@ -34,6 +38,12 @@ input:
|
|||
- 'Space'
|
||||
refresh:
|
||||
- 'r'
|
||||
queue:
|
||||
- 'q'
|
||||
delete:
|
||||
- 'd'
|
||||
focus-next:
|
||||
- 'Tab'
|
||||
hidden-folders:
|
||||
- '.'
|
||||
browse-parent:
|
||||
|
|
|
@ -30,9 +30,7 @@ Choose one of the following methods:
|
|||
|
||||
### Compile
|
||||
|
||||
```
|
||||
go get gitlab.com/tslocum/ditty
|
||||
```
|
||||
```go get gitlab.com/tslocum/ditty```
|
||||
|
||||
## Dependencies
|
||||
|
||||
|
@ -49,4 +47,4 @@ See [CONFIGURATION.md](https://gitlab.com/tslocum/ditty/blob/master/CONFIGURATIO
|
|||
|
||||
## Support
|
||||
|
||||
Please share issues/suggestions [here](https://gitlab.com/tslocum/ditty/issues).
|
||||
Please share issues and suggestions [here](https://gitlab.com/tslocum/ditty/issues).
|
||||
|
|
33
audio.go
33
audio.go
|
@ -165,8 +165,7 @@ func play(audioFile *audioFile) {
|
|||
}
|
||||
|
||||
go app.QueueUpdateDraw(func() {
|
||||
updateMain()
|
||||
updateQueue()
|
||||
updateLists()
|
||||
updateStatus()
|
||||
})
|
||||
}
|
||||
|
@ -187,10 +186,10 @@ func pause() {
|
|||
}
|
||||
|
||||
func nextTrack() {
|
||||
if mainBufferCursor-1 < len(mainBufferFiles)-1 {
|
||||
mainBufferCursor++
|
||||
if queueCursor < len(queueFiles)-1 {
|
||||
queueCursor++
|
||||
|
||||
entry := selectedEntry()
|
||||
entry := selectedQueueEntry()
|
||||
audioFile, err := openFile(path.Join(mainBufferDirectory, entry.File.Name()), entry.Metadata)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -202,25 +201,21 @@ func nextTrack() {
|
|||
}
|
||||
|
||||
func skipPrevious() {
|
||||
if mainBufferCursor > 1 {
|
||||
if offsetEntry(-1).File.IsDir() {
|
||||
return
|
||||
}
|
||||
|
||||
listPrevious()
|
||||
go listSelect()
|
||||
if offsetQueueEntry(-1) == nil {
|
||||
return
|
||||
}
|
||||
|
||||
queuePrevious()
|
||||
go queueSelect()
|
||||
}
|
||||
|
||||
func skipNext() {
|
||||
if mainBufferCursor < len(mainBufferFiles) {
|
||||
if offsetEntry(1).File.IsDir() {
|
||||
return
|
||||
}
|
||||
|
||||
listNext()
|
||||
go listSelect()
|
||||
if offsetQueueEntry(1) == nil {
|
||||
return
|
||||
}
|
||||
|
||||
queueNext()
|
||||
go queueSelect()
|
||||
}
|
||||
|
||||
func roundUnit(x, unit float64) float64 {
|
||||
|
|
127
gui.go
127
gui.go
|
@ -26,19 +26,30 @@ var (
|
|||
bottomstatusbuf *cview.TextView
|
||||
|
||||
mainBufferFiles []*libraryEntry
|
||||
mainBufferCursor int
|
||||
mainBufferCursor = 1 // Position cursor on first entry
|
||||
mainBufferDirectory string
|
||||
mainBufferOrigin int
|
||||
mainBufHeight int
|
||||
mainBufferAutoFocus string // Entry path to focus after loading display
|
||||
|
||||
mainBuffer bytes.Buffer
|
||||
mainLock = new(sync.Mutex)
|
||||
|
||||
queueFiles []*libraryEntry
|
||||
queueCursor int
|
||||
queueDirectory string
|
||||
queueOrigin int
|
||||
queueHeight int
|
||||
|
||||
queueBuffer bytes.Buffer
|
||||
queueLock = new(sync.Mutex)
|
||||
|
||||
queueFocused bool
|
||||
|
||||
seekStart, seekEnd int
|
||||
volumeStart, volumeEnd int
|
||||
|
||||
screenWidth, screenHeight int
|
||||
mainBufHeight int
|
||||
|
||||
mainBuffer bytes.Buffer
|
||||
mainLock = new(sync.Mutex)
|
||||
|
||||
statusText string
|
||||
statusBuffer bytes.Buffer
|
||||
|
@ -82,6 +93,11 @@ func initTUI() error {
|
|||
return mainbuf.GetInnerRect()
|
||||
})
|
||||
|
||||
queuebuf.SetDrawFunc(func(screen tcell.Screen, x, y, width, height int) (i int, i2 int, i3 int, i4 int) {
|
||||
queueHeight = height
|
||||
return queuebuf.GetInnerRect()
|
||||
})
|
||||
|
||||
app.SetRoot(grid, true)
|
||||
|
||||
return nil
|
||||
|
@ -204,21 +220,25 @@ func updateMain() {
|
|||
var printed int
|
||||
var line string
|
||||
if mainBufferOrigin == 0 {
|
||||
if mainBufferCursor == 0 {
|
||||
mainBuffer.WriteString("[::r]")
|
||||
}
|
||||
writeListItemPrefix(&mainBuffer, !queueFocused, mainBufferCursor, 0)
|
||||
|
||||
if mainBufferDirectory == "/" {
|
||||
line = "./"
|
||||
} else {
|
||||
line = "../"
|
||||
}
|
||||
mainBuffer.WriteString(line)
|
||||
|
||||
if queueFocused {
|
||||
writeListItemSuffix(&mainBuffer, !queueFocused, mainBufferCursor, 0)
|
||||
}
|
||||
for i := len(line); i < screenWidth-2; i++ {
|
||||
mainBuffer.WriteRune(' ')
|
||||
}
|
||||
if mainBufferCursor == 0 {
|
||||
mainBuffer.WriteString("[-:-:-]")
|
||||
if !queueFocused {
|
||||
writeListItemSuffix(&mainBuffer, !queueFocused, mainBufferCursor, 0)
|
||||
}
|
||||
|
||||
printed++
|
||||
}
|
||||
for i, entry := range mainBufferFiles {
|
||||
|
@ -230,20 +250,25 @@ func updateMain() {
|
|||
mainBuffer.WriteRune('\n')
|
||||
}
|
||||
|
||||
if i == mainBufferCursor-1 {
|
||||
mainBuffer.WriteString("[::r]")
|
||||
}
|
||||
writeListItemPrefix(&mainBuffer, !queueFocused, mainBufferCursor-1, i)
|
||||
|
||||
if entry.File.IsDir() {
|
||||
line = entry.File.Name() + "/"
|
||||
} else {
|
||||
line = entry.String()
|
||||
}
|
||||
mainBuffer.WriteString(line)
|
||||
|
||||
if queueFocused {
|
||||
writeListItemSuffix(&mainBuffer, !queueFocused, mainBufferCursor-1, i)
|
||||
}
|
||||
|
||||
for i := runewidth.StringWidth(line); i < screenWidth-2; i++ {
|
||||
mainBuffer.WriteRune(' ')
|
||||
}
|
||||
if i == mainBufferCursor-1 {
|
||||
mainBuffer.WriteString("[-:-:-]")
|
||||
|
||||
if !queueFocused {
|
||||
writeListItemSuffix(&mainBuffer, !queueFocused, mainBufferCursor-1, i)
|
||||
}
|
||||
|
||||
printed++
|
||||
|
@ -256,7 +281,77 @@ func updateMain() {
|
|||
}
|
||||
|
||||
func updateQueue() {
|
||||
// TODO
|
||||
queueLock.Lock()
|
||||
defer queueLock.Unlock()
|
||||
|
||||
queueBuffer.Reset()
|
||||
|
||||
var printed int
|
||||
var line string
|
||||
for i, entry := range queueFiles {
|
||||
if i < queueOrigin || i-queueOrigin > queueHeight-1 {
|
||||
continue
|
||||
}
|
||||
|
||||
if printed > 0 {
|
||||
queueBuffer.WriteRune('\n')
|
||||
}
|
||||
|
||||
writeListItemPrefix(&queueBuffer, queueFocused, queueCursor, i)
|
||||
|
||||
if entry.File.IsDir() {
|
||||
line = entry.File.Name() + "/"
|
||||
} else {
|
||||
line = entry.String()
|
||||
}
|
||||
queueBuffer.WriteString(line)
|
||||
|
||||
if !queueFocused {
|
||||
writeListItemSuffix(&queueBuffer, queueFocused, queueCursor, i)
|
||||
}
|
||||
for i := runewidth.StringWidth(line); i < screenWidth-2; i++ {
|
||||
queueBuffer.WriteRune(' ')
|
||||
}
|
||||
if queueFocused {
|
||||
writeListItemSuffix(&queueBuffer, queueFocused, queueCursor, i)
|
||||
}
|
||||
|
||||
printed++
|
||||
if printed == queueHeight-2 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
queuebuf.SetText(queueBuffer.String())
|
||||
}
|
||||
|
||||
func writeListItemPrefix(buffer *bytes.Buffer, focused bool, cursor int, i int) {
|
||||
if focused {
|
||||
if i == cursor {
|
||||
buffer.WriteString("[::r]")
|
||||
}
|
||||
} else {
|
||||
if i == cursor {
|
||||
buffer.WriteString("[::bu]")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func writeListItemSuffix(buffer *bytes.Buffer, focused bool, cursor int, i int) {
|
||||
if focused {
|
||||
if i == cursor {
|
||||
buffer.WriteString("[-:-:-]")
|
||||
}
|
||||
} else {
|
||||
if i == cursor {
|
||||
buffer.WriteString("[-:-:-]")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateLists() {
|
||||
updateMain()
|
||||
updateQueue()
|
||||
}
|
||||
|
||||
func updateStatus() {
|
||||
|
|
|
@ -12,6 +12,9 @@ const (
|
|||
actionSelect = "select"
|
||||
actionPause = "pause"
|
||||
actionRefresh = "refresh"
|
||||
actionQueue = "queue"
|
||||
actionDelete = "delete"
|
||||
actionFocusNext = "focus-next"
|
||||
actionToggleHidden = "hidden-folders"
|
||||
actionBrowseParent = "browse-parent"
|
||||
actionVolumeMute = "volume-mute"
|
||||
|
@ -30,6 +33,9 @@ var actionHandlers = map[string]func(){
|
|||
actionSelect: listSelect,
|
||||
actionPause: pause,
|
||||
actionRefresh: listRefresh,
|
||||
actionQueue: listQueue,
|
||||
actionDelete: listDelete,
|
||||
actionFocusNext: toggleFocusedList,
|
||||
actionToggleHidden: listToggleHidden,
|
||||
actionBrowseParent: browseParent,
|
||||
actionVolumeMute: toggleMute,
|
||||
|
@ -87,6 +93,9 @@ func setDefaultKeyBinds() {
|
|||
actionSelect: {"Enter"},
|
||||
actionPause: {"Space"},
|
||||
actionRefresh: {"r"},
|
||||
actionQueue: {"q"},
|
||||
actionDelete: {"d"},
|
||||
actionFocusNext: {"Tab"},
|
||||
actionToggleHidden: {"."},
|
||||
actionBrowseParent: {"Backspace"},
|
||||
actionVolumeMute: {"m"},
|
||||
|
|
266
gui_list.go
266
gui_list.go
|
@ -6,34 +6,83 @@ import (
|
|||
)
|
||||
|
||||
func listPrevious() {
|
||||
if mainBufferOrigin > 0 && mainBufferCursor == mainBufferOrigin {
|
||||
mainBufferOrigin--
|
||||
}
|
||||
if mainBufferCursor > 0 {
|
||||
mainBufferCursor--
|
||||
}
|
||||
|
||||
go app.QueueUpdateDraw(updateMain)
|
||||
}
|
||||
|
||||
func listNext() {
|
||||
if mainBufferCursor < len(mainBufferFiles) {
|
||||
mainBufferCursor++
|
||||
if mainBufferCursor-mainBufferOrigin > mainBufHeight-3 {
|
||||
mainBufferOrigin++
|
||||
if !queueFocused {
|
||||
if mainBufferOrigin > 0 && mainBufferCursor == mainBufferOrigin {
|
||||
mainBufferOrigin--
|
||||
}
|
||||
if mainBufferCursor > 0 {
|
||||
mainBufferCursor--
|
||||
}
|
||||
} else {
|
||||
if queueOrigin > 0 && queueCursor == queueOrigin {
|
||||
queueOrigin--
|
||||
}
|
||||
if queueCursor > 0 {
|
||||
queueCursor--
|
||||
}
|
||||
}
|
||||
|
||||
go app.QueueUpdateDraw(updateMain)
|
||||
go app.QueueUpdateDraw(updateLists)
|
||||
}
|
||||
|
||||
func listNext() {
|
||||
if !queueFocused {
|
||||
if mainBufferCursor < len(mainBufferFiles) {
|
||||
mainBufferCursor++
|
||||
if mainBufferCursor-mainBufferOrigin > mainBufHeight-3 {
|
||||
mainBufferOrigin++
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if queueCursor < len(queueFiles)-1 {
|
||||
queueCursor++
|
||||
if queueCursor-queueOrigin > queueHeight-3 {
|
||||
queueOrigin++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
go app.QueueUpdateDraw(updateLists)
|
||||
}
|
||||
|
||||
func queuePrevious() {
|
||||
if queueOrigin > 0 && queueCursor == queueOrigin {
|
||||
queueOrigin--
|
||||
}
|
||||
if queueCursor > 0 {
|
||||
queueCursor--
|
||||
}
|
||||
|
||||
go app.QueueUpdateDraw(updateQueue)
|
||||
}
|
||||
|
||||
func queueNext() {
|
||||
if queueCursor < len(queueFiles)-1 {
|
||||
queueCursor++
|
||||
queueOrigin = queueCursor - ((queueHeight - 3) / 2)
|
||||
if queueOrigin < 0 {
|
||||
queueOrigin = 0
|
||||
}
|
||||
if queueOrigin > (len(queueFiles)-1)-(queueHeight-3) {
|
||||
queueOrigin = (len(queueFiles) - 1) - (queueHeight - 3)
|
||||
}
|
||||
}
|
||||
|
||||
go app.QueueUpdateDraw(updateQueue)
|
||||
}
|
||||
|
||||
func listSelect() {
|
||||
if queueFocused {
|
||||
queueSelect()
|
||||
return
|
||||
}
|
||||
|
||||
if mainBufferCursor == 0 {
|
||||
browseFolder(path.Join(mainBufferDirectory, ".."))
|
||||
return
|
||||
}
|
||||
|
||||
entry := selectedEntry()
|
||||
entry := selectedMainEntry()
|
||||
if entry.File.IsDir() {
|
||||
browseFolder(path.Join(mainBufferDirectory, path.Base(entry.File.Name())))
|
||||
return
|
||||
|
@ -55,48 +104,179 @@ func listSelect() {
|
|||
go app.QueueUpdateDraw(updateStatus)
|
||||
}
|
||||
|
||||
func selectedEntry() *libraryEntry {
|
||||
func queueSelect() {
|
||||
entry := selectedQueueEntry()
|
||||
if entry.File.IsDir() {
|
||||
// TODO error
|
||||
return
|
||||
}
|
||||
|
||||
audioFile, err := openFile(entry.Path, entry.Metadata)
|
||||
if err != nil {
|
||||
statusText = err.Error()
|
||||
go func() {
|
||||
time.Sleep(5 * time.Second)
|
||||
statusText = ""
|
||||
go app.QueueUpdateDraw(updateMain)
|
||||
}()
|
||||
go app.QueueUpdateDraw(updateMain)
|
||||
return
|
||||
}
|
||||
go play(audioFile)
|
||||
|
||||
go app.QueueUpdateDraw(updateStatus)
|
||||
}
|
||||
|
||||
func listQueue() {
|
||||
if mainBufferCursor == 0 {
|
||||
// TODO Show error
|
||||
return
|
||||
}
|
||||
|
||||
entry := selectedMainEntry()
|
||||
if entry == nil {
|
||||
return
|
||||
} else if entry.File.IsDir() {
|
||||
scanFiles := scanFolderRecursively(entry.Path)
|
||||
|
||||
queueLock.Lock()
|
||||
queueFiles = append(queueFiles, scanFiles...)
|
||||
queueLock.Unlock()
|
||||
|
||||
if playOnQueue && playingFileID == 0 && len(queueFiles) > 0 {
|
||||
queueSelect()
|
||||
}
|
||||
go app.QueueUpdateDraw(updateQueue)
|
||||
return
|
||||
}
|
||||
|
||||
queueLock.Lock()
|
||||
defer queueLock.Unlock()
|
||||
|
||||
queueFiles = append(queueFiles, entry)
|
||||
|
||||
if playOnQueue && playingFileID == 0 {
|
||||
queueSelect()
|
||||
}
|
||||
go app.QueueUpdateDraw(updateLists)
|
||||
}
|
||||
|
||||
func listDelete() {
|
||||
if !queueFocused {
|
||||
return
|
||||
}
|
||||
|
||||
queueLock.Lock()
|
||||
defer queueLock.Unlock()
|
||||
|
||||
if len(queueFiles) <= queueCursor {
|
||||
return
|
||||
}
|
||||
|
||||
queueFiles = append(queueFiles[:queueCursor], queueFiles[queueCursor+1:]...)
|
||||
|
||||
if queueCursor > len(queueFiles)-1 {
|
||||
queueCursor = len(queueFiles) - 1
|
||||
if queueCursor < 0 {
|
||||
queueCursor = 0
|
||||
}
|
||||
}
|
||||
|
||||
go app.QueueUpdateDraw(updateQueue)
|
||||
}
|
||||
|
||||
func selectedMainEntry() *libraryEntry {
|
||||
return mainBufferFiles[mainBufferCursor-1]
|
||||
}
|
||||
|
||||
func offsetEntry(offset int) *libraryEntry {
|
||||
func offsetMainEntry(offset int) *libraryEntry {
|
||||
if (mainBufferCursor-1)+offset < 0 || (mainBufferCursor-1)+offset >= len(mainBufferFiles) {
|
||||
return nil
|
||||
}
|
||||
return mainBufferFiles[(mainBufferCursor-1)+offset]
|
||||
}
|
||||
|
||||
func selectedQueueEntry() *libraryEntry {
|
||||
return queueFiles[queueCursor]
|
||||
}
|
||||
|
||||
func offsetQueueEntry(offset int) *libraryEntry {
|
||||
if queueCursor+offset < 0 || queueCursor+offset >= len(queueFiles) {
|
||||
return nil
|
||||
}
|
||||
return queueFiles[queueCursor+offset]
|
||||
}
|
||||
|
||||
func listPreviousPage() {
|
||||
if mainBufferOrigin == 0 {
|
||||
mainBufferCursor = 0
|
||||
if !queueFocused {
|
||||
if mainBufferOrigin == 0 {
|
||||
mainBufferCursor = 0
|
||||
|
||||
go app.QueueUpdateDraw(updateMain)
|
||||
return
|
||||
}
|
||||
|
||||
mainBufferOrigin -= (mainBufHeight - 1) - 2
|
||||
if mainBufferOrigin < 0 {
|
||||
mainBufferOrigin = 0
|
||||
}
|
||||
mainBufferCursor = mainBufferOrigin
|
||||
|
||||
go app.QueueUpdateDraw(updateMain)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if queueOrigin == 0 {
|
||||
queueCursor = 0
|
||||
|
||||
mainBufferOrigin -= (mainBufHeight - 1) - 2
|
||||
if mainBufferOrigin < 0 {
|
||||
mainBufferOrigin = 0
|
||||
}
|
||||
mainBufferCursor = mainBufferOrigin
|
||||
go app.QueueUpdateDraw(updateQueue)
|
||||
return
|
||||
}
|
||||
|
||||
go app.QueueUpdateDraw(updateMain)
|
||||
queueOrigin -= (queueHeight - 1) - 2
|
||||
if queueOrigin < 0 {
|
||||
queueOrigin = 0
|
||||
}
|
||||
queueCursor = queueOrigin
|
||||
|
||||
go app.QueueUpdateDraw(updateQueue)
|
||||
}
|
||||
}
|
||||
|
||||
func listNextPage() {
|
||||
numEntries := len(mainBufferFiles)
|
||||
if !queueFocused {
|
||||
numEntries := len(mainBufferFiles)
|
||||
|
||||
if mainBufferOrigin >= numEntries-(mainBufHeight-1) {
|
||||
mainBufferCursor = numEntries
|
||||
if mainBufferOrigin >= numEntries-(mainBufHeight-1) {
|
||||
mainBufferCursor = numEntries
|
||||
|
||||
go app.QueueUpdateDraw(updateMain)
|
||||
return
|
||||
}
|
||||
|
||||
mainBufferOrigin += (mainBufHeight - 1) - 2
|
||||
if mainBufferOrigin > (numEntries-(mainBufHeight-1))+2 {
|
||||
mainBufferOrigin = (numEntries - (mainBufHeight - 1)) + 2
|
||||
}
|
||||
mainBufferCursor = mainBufferOrigin
|
||||
|
||||
go app.QueueUpdateDraw(updateMain)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
numEntries := len(queueFiles)
|
||||
|
||||
mainBufferOrigin += (mainBufHeight - 1) - 2
|
||||
if mainBufferOrigin > (numEntries-(mainBufHeight-1))+2 {
|
||||
mainBufferOrigin = (numEntries - (mainBufHeight - 1)) + 2
|
||||
}
|
||||
mainBufferCursor = mainBufferOrigin
|
||||
if queueOrigin >= numEntries-(queueHeight-1) {
|
||||
queueCursor = numEntries - 1
|
||||
|
||||
go app.QueueUpdateDraw(updateMain)
|
||||
go app.QueueUpdateDraw(updateQueue)
|
||||
return
|
||||
}
|
||||
|
||||
queueOrigin += queueHeight - 2
|
||||
if queueOrigin > ((numEntries-1)-(queueHeight-1))+2 {
|
||||
queueOrigin = ((numEntries - 1) - (queueHeight - 1)) + 2
|
||||
}
|
||||
queueCursor = queueOrigin
|
||||
|
||||
go app.QueueUpdateDraw(updateQueue)
|
||||
}
|
||||
}
|
||||
|
||||
func listRefresh() {
|
||||
|
@ -122,3 +302,9 @@ func listToggleHidden() {
|
|||
|
||||
listRefresh()
|
||||
}
|
||||
|
||||
func toggleFocusedList() {
|
||||
queueFocused = !queueFocused
|
||||
|
||||
go app.QueueUpdateDraw(updateLists)
|
||||
}
|
||||
|
|
31
library.go
31
library.go
|
@ -36,6 +36,7 @@ func readMetadata(f *os.File) *metadata {
|
|||
|
||||
type libraryEntry struct {
|
||||
File os.FileInfo
|
||||
Path string
|
||||
Metadata *metadata
|
||||
}
|
||||
|
||||
|
@ -59,10 +60,12 @@ func scanFolder(scanPath string) []*libraryEntry {
|
|||
|
||||
var entries []*libraryEntry
|
||||
for _, fileInfo := range files {
|
||||
p := path.Join(scanPath, fileInfo.Name())
|
||||
|
||||
b := path.Base(fileInfo.Name())
|
||||
if fileInfo.IsDir() {
|
||||
if b != "" && (b[0] != '.' || showHiddenFolders) {
|
||||
entries = append(entries, &libraryEntry{File: fileInfo, Metadata: &metadata{Title: fileInfo.Name()}})
|
||||
entries = append(entries, &libraryEntry{File: fileInfo, Path: p, Metadata: &metadata{Title: fileInfo.Name()}})
|
||||
}
|
||||
|
||||
continue
|
||||
|
@ -70,14 +73,14 @@ func scanFolder(scanPath string) []*libraryEntry {
|
|||
continue
|
||||
}
|
||||
|
||||
f, err := os.Open(path.Join(scanPath, fileInfo.Name()))
|
||||
f, err := os.Open(p)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
metadata := readMetadata(f)
|
||||
f.Close()
|
||||
|
||||
entries = append(entries, &libraryEntry{File: fileInfo, Metadata: metadata})
|
||||
entries = append(entries, &libraryEntry{File: fileInfo, Path: p, Metadata: metadata})
|
||||
}
|
||||
|
||||
sort.Slice(entries, func(i, j int) bool {
|
||||
|
@ -94,3 +97,25 @@ func scanFolder(scanPath string) []*libraryEntry {
|
|||
|
||||
return entries
|
||||
}
|
||||
|
||||
func scanFolderRecursively(path string) []*libraryEntry {
|
||||
var entries []*libraryEntry
|
||||
|
||||
scanFiles := scanFolder(path)
|
||||
for _, entry := range scanFiles {
|
||||
if !entry.File.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
entries = append(entries, scanFolder(entry.Path)...)
|
||||
}
|
||||
for _, entry := range scanFiles {
|
||||
if entry.File.IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
entries = append(entries, entry)
|
||||
}
|
||||
|
||||
return entries
|
||||
}
|
||||
|
|
2
main.go
2
main.go
|
@ -36,6 +36,7 @@ var (
|
|||
restrictLibrary string
|
||||
showHiddenFolders bool
|
||||
startingVolumeFlag int
|
||||
playOnQueue bool
|
||||
|
||||
version = "0.0.0"
|
||||
done = make(chan bool)
|
||||
|
@ -53,6 +54,7 @@ func main() {
|
|||
flag.IntVar(&streamFdInt, "fd", -1, "stream audio to file descriptor")
|
||||
flag.IntVar(&startingVolumeFlag, "volume", -1, "initial volume level 0-100")
|
||||
flag.StringVar(&restrictLibrary, "restrict-library", "", "restrict library to path")
|
||||
flag.BoolVar(&playOnQueue, "autoplay-queue", true, "starting playing on initial queue")
|
||||
flag.DurationVar(&bufferSize, "buffer-size", defaultBufferSize, "audio buffer size")
|
||||
flag.StringVar(&debugAddress, "debug-address", "", "address to serve debug info")
|
||||
flag.BoolVar(&showHiddenFolders, "hidden-folders", false, "show hidden folders")
|
||||
|
|
Loading…
Reference in a new issue