mirror of
https://github.com/issadarkthing/gomu.git
synced 2025-04-26 13:49:21 +08:00
235 lines
4.1 KiB
Go
235 lines
4.1 KiB
Go
// Copyright (C) 2020 Raziman
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
|
|
"github.com/gdamore/tcell"
|
|
"github.com/rivo/tview"
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
type AudioFile struct {
|
|
Name string
|
|
Path string
|
|
IsAudioFile bool
|
|
Parent *tview.TreeNode
|
|
}
|
|
|
|
type Playlist struct {
|
|
*tview.TreeView
|
|
}
|
|
|
|
func InitPlaylist() *Playlist {
|
|
|
|
rootDir, err := filepath.Abs(expandTilde(viper.GetString("music_dir")))
|
|
|
|
if err != nil {
|
|
log(err.Error())
|
|
}
|
|
|
|
root := tview.NewTreeNode(path.Base(rootDir))
|
|
|
|
tree := tview.NewTreeView().SetRoot(root)
|
|
playlist := &Playlist{tree}
|
|
|
|
playlist.SetTitle(" Playlist ").SetBorder(true)
|
|
|
|
populate(root, rootDir)
|
|
|
|
var firstChild *tview.TreeNode
|
|
var prevNode *tview.TreeNode
|
|
|
|
if len(root.GetChildren()) == 0 {
|
|
firstChild = root
|
|
} else {
|
|
firstChild = root.GetChildren()[0]
|
|
}
|
|
|
|
firstChild.SetColor(textColor)
|
|
playlist.SetCurrentNode(firstChild)
|
|
// keep track of prev node so we can remove the color of highlight
|
|
prevNode = firstChild.SetColor(accentColor)
|
|
|
|
playlist.SetChangedFunc(func(node *tview.TreeNode) {
|
|
prevNode.SetColor(textColor)
|
|
root.SetColor(textColor)
|
|
node.SetColor(accentColor)
|
|
prevNode = node
|
|
})
|
|
|
|
playlist.SetSelectedFunc(func(node *tview.TreeNode) {
|
|
node.SetExpanded(!node.IsExpanded())
|
|
})
|
|
|
|
playlist.SetInputCapture(func(e *tcell.EventKey) *tcell.EventKey {
|
|
|
|
currNode := playlist.GetCurrentNode()
|
|
|
|
if currNode == playlist.GetRoot() {
|
|
return e
|
|
}
|
|
|
|
audioFile := currNode.GetReference().(*AudioFile)
|
|
|
|
switch e.Rune() {
|
|
case 'l':
|
|
|
|
playlist.addToQueue(audioFile)
|
|
currNode.SetExpanded(true)
|
|
|
|
case 'h':
|
|
|
|
// if closing node with no children
|
|
// close the node's parent
|
|
// remove the color of the node
|
|
|
|
if audioFile.IsAudioFile {
|
|
parent := audioFile.Parent
|
|
|
|
currNode.SetColor(textColor)
|
|
parent.SetExpanded(false)
|
|
parent.SetColor(accentColor)
|
|
// prevPanel = parent
|
|
playlist.SetCurrentNode(parent)
|
|
}
|
|
|
|
currNode.Collapse()
|
|
|
|
case 'L':
|
|
|
|
if !viper.GetBool("confirm_bulk_add") {
|
|
playlist.addAllToQueue(playlist.GetCurrentNode())
|
|
return e
|
|
}
|
|
|
|
confirmationPopup(
|
|
"Are you sure to add this whole directory into queue?",
|
|
func(_ int, label string) {
|
|
|
|
if label == "yes" {
|
|
playlist.addAllToQueue(playlist.GetCurrentNode())
|
|
}
|
|
|
|
pages.RemovePage("confirmation-popup")
|
|
app.SetFocus(playlist)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
return e
|
|
})
|
|
|
|
return playlist
|
|
|
|
}
|
|
|
|
func populate(root *tview.TreeNode, rootPath string) {
|
|
|
|
files, err := ioutil.ReadDir(rootPath)
|
|
|
|
if err != nil {
|
|
log(err.Error())
|
|
}
|
|
|
|
for _, file := range files {
|
|
|
|
path := filepath.Join(rootPath, file.Name())
|
|
f, err := os.Open(path)
|
|
|
|
if err != nil {
|
|
log(err.Error())
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
if !file.IsDir() {
|
|
|
|
filetype, err := GetFileContentType(f)
|
|
|
|
if err != nil {
|
|
log(err.Error())
|
|
}
|
|
|
|
// skip if not mp3 file
|
|
if filetype != "mpeg" {
|
|
continue
|
|
}
|
|
|
|
}
|
|
|
|
child := tview.NewTreeNode(file.Name())
|
|
root.AddChild(child)
|
|
|
|
audioFile := &AudioFile{
|
|
Name: file.Name(),
|
|
Path: path,
|
|
IsAudioFile: true,
|
|
Parent: root,
|
|
}
|
|
|
|
child.SetReference(audioFile)
|
|
|
|
if file.IsDir() {
|
|
audioFile.IsAudioFile = false
|
|
populate(child, path)
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// add to queue and update queue panel
|
|
func (playlist *Playlist) addToQueue(audioFile *AudioFile) {
|
|
|
|
if audioFile.IsAudioFile {
|
|
|
|
if !player.IsRunning {
|
|
|
|
player.IsRunning = true
|
|
|
|
go func() {
|
|
queue.AddItem("", audioFile.Path, 0, nil)
|
|
player.Run()
|
|
}()
|
|
|
|
} else {
|
|
|
|
songLength, err := GetLength(audioFile.Path)
|
|
|
|
if err != nil {
|
|
log(err.Error())
|
|
}
|
|
|
|
queueItemView := fmt.Sprintf("[ %s ] %s", fmtDuration(songLength), audioFile.Name)
|
|
queue.AddItem(queueItemView, audioFile.Path, 0, nil)
|
|
}
|
|
}
|
|
}
|
|
|
|
// bulk add a playlist to queue
|
|
func (playlist *Playlist) addAllToQueue(root *tview.TreeNode) {
|
|
|
|
var childrens []*tview.TreeNode
|
|
|
|
childrens = root.GetChildren()
|
|
|
|
// gets the parent if highlighted item is a file
|
|
if len(childrens) == 0 {
|
|
childrens = root.GetReference().(*AudioFile).Parent.GetChildren()
|
|
}
|
|
|
|
for _, v := range childrens {
|
|
currNode := v.GetReference().(*AudioFile)
|
|
|
|
playlist.addToQueue(currNode)
|
|
}
|
|
|
|
}
|