mirror of
https://github.com/issadarkthing/gomu.git
synced 2025-04-25 13:48:49 +08:00
refactor: extract audiofile.go from playlist.go
This commit is contained in:
parent
05bf59e30a
commit
dcb8fda7ba
28
command.go
28
command.go
@ -46,10 +46,10 @@ func (c Command) defineCommands() {
|
||||
|
||||
c.define("delete_playlist", func() {
|
||||
audioFile := gomu.playlist.getCurrentFile()
|
||||
if audioFile.isAudioFile {
|
||||
if audioFile.IsAudioFile() {
|
||||
return
|
||||
}
|
||||
err := confirmDeleteAllPopup(audioFile.node)
|
||||
err := confirmDeleteAllPopup(audioFile.Node())
|
||||
if err != nil {
|
||||
errorPopup(err)
|
||||
}
|
||||
@ -58,7 +58,7 @@ func (c Command) defineCommands() {
|
||||
c.define("delete_file", func() {
|
||||
audioFile := gomu.playlist.getCurrentFile()
|
||||
// prevent from deleting a directory
|
||||
if !audioFile.isAudioFile {
|
||||
if !audioFile.IsAudioFile() {
|
||||
return
|
||||
}
|
||||
|
||||
@ -81,8 +81,8 @@ func (c Command) defineCommands() {
|
||||
}
|
||||
// this ensures it downloads to
|
||||
// the correct dir
|
||||
if audioFile.isAudioFile {
|
||||
downloadMusicPopup(audioFile.parent)
|
||||
if audioFile.IsAudioFile() {
|
||||
downloadMusicPopup(audioFile.ParentNode())
|
||||
} else {
|
||||
downloadMusicPopup(currNode)
|
||||
}
|
||||
@ -91,7 +91,7 @@ func (c Command) defineCommands() {
|
||||
c.define("add_queue", func() {
|
||||
audioFile := gomu.playlist.getCurrentFile()
|
||||
currNode := gomu.playlist.GetCurrentNode()
|
||||
if audioFile.isAudioFile {
|
||||
if audioFile.IsAudioFile() {
|
||||
gomu.queue.pushFront(audioFile)
|
||||
if len(gomu.queue.items) == 1 && !gomu.player.IsRunning() {
|
||||
err := gomu.queue.playQueue()
|
||||
@ -111,8 +111,8 @@ func (c Command) defineCommands() {
|
||||
// close the node's parent
|
||||
// remove the color of the node
|
||||
|
||||
if audioFile.isAudioFile {
|
||||
parent := audioFile.parent
|
||||
if audioFile.IsAudioFile() {
|
||||
parent := audioFile.ParentNode()
|
||||
gomu.playlist.setHighlight(parent)
|
||||
parent.SetExpanded(false)
|
||||
}
|
||||
@ -165,7 +165,7 @@ func (c Command) defineCommands() {
|
||||
files := make([]string, len(gomu.playlist.getAudioFiles()))
|
||||
|
||||
for i, file := range gomu.playlist.getAudioFiles() {
|
||||
files[i] = file.name
|
||||
files[i] = file.Name()
|
||||
}
|
||||
|
||||
searchPopup("Search", files, func(text string) {
|
||||
@ -175,7 +175,7 @@ func (c Command) defineCommands() {
|
||||
logError(err)
|
||||
}
|
||||
|
||||
gomu.playlist.setHighlight(audio.node)
|
||||
gomu.playlist.setHighlight(audio.Node())
|
||||
gomu.playlist.refresh()
|
||||
})
|
||||
})
|
||||
@ -245,14 +245,14 @@ func (c Command) defineCommands() {
|
||||
|
||||
audios := make([]string, 0, len(queue.items))
|
||||
for _, file := range queue.items {
|
||||
audios = append(audios, file.name)
|
||||
audios = append(audios, file.Name())
|
||||
}
|
||||
|
||||
searchPopup("Songs", audios, func(selected string) {
|
||||
|
||||
index := 0
|
||||
for i, v := range queue.items {
|
||||
if v.name == selected {
|
||||
if v.Name() == selected {
|
||||
index = i
|
||||
}
|
||||
}
|
||||
@ -426,7 +426,7 @@ func (c Command) defineCommands() {
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
if audioFile.isAudioFile {
|
||||
if audioFile.IsAudioFile() {
|
||||
go func() {
|
||||
err := lyricPopup(lang, audioFile, &wg)
|
||||
if err != nil {
|
||||
@ -442,7 +442,7 @@ func (c Command) defineCommands() {
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
if audioFile.isAudioFile {
|
||||
if audioFile.IsAudioFile() {
|
||||
go func() {
|
||||
err := lyricPopup(lang, audioFile, &wg)
|
||||
if err != nil {
|
||||
|
3
go.mod
3
go.mod
@ -6,7 +6,7 @@ require (
|
||||
github.com/PuerkitoBio/goquery v1.6.1 // indirect
|
||||
github.com/antchfx/htmlquery v1.2.3 // indirect
|
||||
github.com/antchfx/xmlquery v1.3.4 // indirect
|
||||
github.com/bogem/id3v2 v1.2.0 // indirect
|
||||
github.com/bogem/id3v2 v1.2.0
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/disintegration/imaging v1.6.2
|
||||
github.com/faiface/beep v1.0.2
|
||||
@ -29,7 +29,6 @@ require (
|
||||
github.com/tramhao/id3v2 v1.2.1
|
||||
github.com/ztrue/tracerr v0.3.0
|
||||
gitlab.com/diamondburned/ueberzug-go v0.0.0-20190521043425-7c15a5f63b06
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
|
||||
golang.org/x/exp v0.0.0-20201229011636-eab1b5eb1a03 // indirect
|
||||
golang.org/x/image v0.0.0-20201208152932-35266b937fa6 // indirect
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect
|
||||
|
1
go.sum
1
go.sum
@ -108,7 +108,6 @@ gitlab.com/diamondburned/ueberzug-go v0.0.0-20190521043425-7c15a5f63b06/go.mod h
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20180710024300-14dda7b62fcd/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
|
152
player/audiofile.go
Normal file
152
player/audiofile.go
Normal file
@ -0,0 +1,152 @@
|
||||
// Copyright (C) 2020 Raziman
|
||||
|
||||
package player
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/rivo/tview"
|
||||
"github.com/tramhao/id3v2"
|
||||
"github.com/ztrue/tracerr"
|
||||
)
|
||||
|
||||
var _ Audio = (*AudioFile)(nil)
|
||||
|
||||
// AudioFile represents directories and mp3 files
|
||||
// isAudioFile equals to false if it is a directory
|
||||
type AudioFile struct {
|
||||
name string
|
||||
path string
|
||||
isAudioFile bool
|
||||
length time.Duration
|
||||
node *tview.TreeNode
|
||||
parent *tview.TreeNode
|
||||
}
|
||||
|
||||
// NewAudioFile return a new instance of Audiofile
|
||||
func NewAudioFile() *AudioFile {
|
||||
return &AudioFile{}
|
||||
}
|
||||
|
||||
// Name return the name of AudioFile
|
||||
func (a *AudioFile) Name() string {
|
||||
return a.name
|
||||
}
|
||||
|
||||
// SetName set the name of AudioFile
|
||||
func (a *AudioFile) SetName(name string) {
|
||||
if name == "" {
|
||||
return
|
||||
}
|
||||
a.name = name
|
||||
}
|
||||
|
||||
// Path return the path of AudioFile
|
||||
func (a *AudioFile) Path() string {
|
||||
return a.path
|
||||
}
|
||||
|
||||
// SetPath return the path of AudioFile
|
||||
func (a *AudioFile) SetPath(path string) {
|
||||
a.path = path
|
||||
}
|
||||
|
||||
// IsAudioFile check if the file is song or directory
|
||||
func (a *AudioFile) IsAudioFile() bool {
|
||||
return a.isAudioFile
|
||||
}
|
||||
|
||||
// SetIsAudioFile check if the file is song or directory
|
||||
func (a *AudioFile) SetIsAudioFile(isAudioFile bool) {
|
||||
a.isAudioFile = isAudioFile
|
||||
}
|
||||
|
||||
// Len return the length of AudioFile
|
||||
func (a *AudioFile) Len() time.Duration {
|
||||
return a.length
|
||||
}
|
||||
|
||||
// SetLen set the length of AudioFile
|
||||
func (a *AudioFile) SetLen(length time.Duration) {
|
||||
a.length = length
|
||||
}
|
||||
|
||||
// Parent return the parent directory of AudioFile
|
||||
func (a *AudioFile) Parent() *AudioFile {
|
||||
if a.parent == nil {
|
||||
return nil
|
||||
}
|
||||
return a.parent.GetReference().(*AudioFile)
|
||||
}
|
||||
|
||||
// SetParentNode return the parent directory of AudioFile
|
||||
func (a *AudioFile) SetParentNode(parentNode *tview.TreeNode) {
|
||||
if parentNode == nil {
|
||||
return
|
||||
}
|
||||
a.parent = parentNode
|
||||
}
|
||||
|
||||
// ParentNode return the parent node of AudioFile
|
||||
func (a *AudioFile) ParentNode() *tview.TreeNode {
|
||||
if a.parent == nil {
|
||||
return nil
|
||||
}
|
||||
return a.parent
|
||||
}
|
||||
|
||||
// Node return the current node of AudioFile
|
||||
func (a *AudioFile) Node() *tview.TreeNode {
|
||||
if a.node == nil {
|
||||
return nil
|
||||
}
|
||||
return a.node
|
||||
}
|
||||
|
||||
// SetNode return the current node of AudioFile
|
||||
func (a *AudioFile) SetNode(node *tview.TreeNode) {
|
||||
a.node = node
|
||||
}
|
||||
|
||||
// String return the string of AudioFile
|
||||
func (a *AudioFile) String() string {
|
||||
if a == nil {
|
||||
return "nil"
|
||||
}
|
||||
return fmt.Sprintf("%#v", a)
|
||||
}
|
||||
|
||||
// LoadTagMap will load from tag and return a map of langExt to lyrics
|
||||
func (a *AudioFile) LoadTagMap() (tag *id3v2.Tag, popupLyricMap map[string]string, options []string, err error) {
|
||||
|
||||
popupLyricMap = make(map[string]string)
|
||||
|
||||
if a.isAudioFile {
|
||||
tag, err = id3v2.Open(a.path, id3v2.Options{Parse: true})
|
||||
if err != nil {
|
||||
return nil, nil, nil, tracerr.Wrap(err)
|
||||
}
|
||||
defer tag.Close()
|
||||
} else {
|
||||
return nil, nil, nil, fmt.Errorf("not an audio file")
|
||||
}
|
||||
usltFrames := tag.GetFrames(tag.CommonID("Unsynchronised lyrics/text transcription"))
|
||||
|
||||
for _, f := range usltFrames {
|
||||
uslf, ok := f.(id3v2.UnsynchronisedLyricsFrame)
|
||||
if !ok {
|
||||
return nil, nil, nil, errors.New("USLT error")
|
||||
}
|
||||
res := uslf.Lyrics
|
||||
popupLyricMap[uslf.ContentDescriptor] = res
|
||||
}
|
||||
for option := range popupLyricMap {
|
||||
options = append(options, option)
|
||||
}
|
||||
sort.Strings(options)
|
||||
|
||||
return tag, popupLyricMap, options, err
|
||||
}
|
@ -21,6 +21,7 @@ import (
|
||||
ugo "gitlab.com/diamondburned/ueberzug-go"
|
||||
|
||||
"github.com/issadarkthing/gomu/lyric"
|
||||
"github.com/issadarkthing/gomu/player"
|
||||
)
|
||||
|
||||
// PlayingBar shows song name, progress and lyric
|
||||
@ -145,7 +146,7 @@ func (p *PlayingBar) setSongTitle(title string) {
|
||||
}
|
||||
|
||||
// Resets progress bar, ready for execution
|
||||
func (p *PlayingBar) newProgress(currentSong *AudioFile, full int) {
|
||||
func (p *PlayingBar) newProgress(currentSong *player.AudioFile, full int) {
|
||||
p.setFull(full)
|
||||
p.setProgress(0)
|
||||
p.hasTag = false
|
||||
@ -158,7 +159,7 @@ func (p *PlayingBar) newProgress(currentSong *AudioFile, full int) {
|
||||
p.albumPhoto = nil
|
||||
}
|
||||
|
||||
err := p.loadLyrics(currentSong.path)
|
||||
err := p.loadLyrics(currentSong.Path())
|
||||
if err != nil {
|
||||
errorPopup(err)
|
||||
return
|
||||
@ -191,7 +192,7 @@ func (p *PlayingBar) newProgress(currentSong *AudioFile, full int) {
|
||||
p.subtitle = p.subtitles[0]
|
||||
}
|
||||
}
|
||||
p.setSongTitle(currentSong.name)
|
||||
p.setSongTitle(currentSong.Name())
|
||||
|
||||
}
|
||||
|
||||
|
204
playlist.go
204
playlist.go
@ -26,54 +26,6 @@ import (
|
||||
"github.com/issadarkthing/gomu/player"
|
||||
)
|
||||
|
||||
var _ player.Audio = (*AudioFile)(nil)
|
||||
|
||||
// AudioFile represents directories and mp3 files
|
||||
// isAudioFile equals to false if it is a directory
|
||||
type AudioFile struct {
|
||||
name string
|
||||
path string
|
||||
isAudioFile bool
|
||||
length time.Duration
|
||||
node *tview.TreeNode
|
||||
parent *tview.TreeNode
|
||||
}
|
||||
|
||||
// Name return the name of AudioFile
|
||||
func (a *AudioFile) Name() string {
|
||||
return a.name
|
||||
}
|
||||
|
||||
// Path return the path of AudioFile
|
||||
func (a *AudioFile) Path() string {
|
||||
return a.path
|
||||
}
|
||||
|
||||
// IsAudioFile check if the file is song or directory
|
||||
func (a *AudioFile) IsAudioFile() bool {
|
||||
return a.isAudioFile
|
||||
}
|
||||
|
||||
// Len return the length of AudioFile
|
||||
func (a *AudioFile) Len() time.Duration {
|
||||
return a.length
|
||||
}
|
||||
|
||||
// GetParent return the parent directory of AudioFile
|
||||
func (a *AudioFile) GetParent() *AudioFile {
|
||||
if a.parent == nil {
|
||||
return nil
|
||||
}
|
||||
return a.parent.GetReference().(*AudioFile)
|
||||
}
|
||||
|
||||
func (a *AudioFile) String() string {
|
||||
if a == nil {
|
||||
return "nil"
|
||||
}
|
||||
return fmt.Sprintf("%#v", a)
|
||||
}
|
||||
|
||||
// Playlist struct represents playlist panel
|
||||
// that shows the tree of the music directory
|
||||
type Playlist struct {
|
||||
@ -83,7 +35,7 @@ type Playlist struct {
|
||||
// number of downloads
|
||||
download int
|
||||
done chan struct{}
|
||||
yankFile *AudioFile
|
||||
yankFile *player.AudioFile
|
||||
}
|
||||
|
||||
func (p *Playlist) help() []string {
|
||||
@ -152,11 +104,10 @@ func newPlaylist(args Args) *Playlist {
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
|
||||
rootAudioFile := &AudioFile{
|
||||
name: path.Base(rootDir),
|
||||
node: root,
|
||||
path: rootDir,
|
||||
}
|
||||
rootAudioFile := player.NewAudioFile()
|
||||
rootAudioFile.SetName(path.Base(rootDir))
|
||||
rootAudioFile.SetNode(root)
|
||||
rootAudioFile.SetPath(rootDir)
|
||||
|
||||
root.SetReference(rootAudioFile)
|
||||
root.SetColor(gomu.colors.playlistDir)
|
||||
@ -235,16 +186,16 @@ func newPlaylist(args Args) *Playlist {
|
||||
}
|
||||
|
||||
// Returns the current file highlighted in the playlist
|
||||
func (p Playlist) getCurrentFile() *AudioFile {
|
||||
func (p Playlist) getCurrentFile() *player.AudioFile {
|
||||
node := p.GetCurrentNode()
|
||||
if node == nil {
|
||||
return nil
|
||||
}
|
||||
return node.GetReference().(*AudioFile)
|
||||
return node.GetReference().(*player.AudioFile)
|
||||
}
|
||||
|
||||
// Deletes song from filesystem
|
||||
func (p *Playlist) deleteSong(audioFile *AudioFile) {
|
||||
func (p *Playlist) deleteSong(audioFile *player.AudioFile) {
|
||||
|
||||
confirmationPopup(
|
||||
"Are you sure to delete this audio file?", func(_ int, buttonName string) {
|
||||
@ -256,14 +207,14 @@ func (p *Playlist) deleteSong(audioFile *AudioFile) {
|
||||
// hehe we need to move focus to next node before delete it
|
||||
p.InputHandler()(tcell.NewEventKey(tcell.KeyDown, 0, tcell.ModNone), nil)
|
||||
|
||||
err := os.Remove(audioFile.path)
|
||||
err := os.Remove(audioFile.Path())
|
||||
if err != nil {
|
||||
errorPopup(err)
|
||||
return
|
||||
}
|
||||
|
||||
defaultTimedPopup(" Success ",
|
||||
audioFile.name+"\nhas been deleted successfully")
|
||||
audioFile.Name()+"\nhas been deleted successfully")
|
||||
go gomu.app.QueueUpdateDraw(func() {
|
||||
p.refresh()
|
||||
// Here we remove the song from queue
|
||||
@ -276,20 +227,20 @@ func (p *Playlist) deleteSong(audioFile *AudioFile) {
|
||||
}
|
||||
|
||||
// Deletes playlist/dir from filesystem
|
||||
func (p *Playlist) deletePlaylist(audioFile *AudioFile) (err error) {
|
||||
func (p *Playlist) deletePlaylist(audioFile *player.AudioFile) (err error) {
|
||||
|
||||
// here we close the node and then move to next folder before delete
|
||||
p.InputHandler()(tcell.NewEventKey(tcell.KeyRune, 'h', tcell.ModNone), nil)
|
||||
p.InputHandler()(tcell.NewEventKey(tcell.KeyDown, 0, tcell.ModNone), nil)
|
||||
|
||||
err = os.RemoveAll(audioFile.path)
|
||||
err = os.RemoveAll(audioFile.Path())
|
||||
if err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
defaultTimedPopup(
|
||||
" Success ",
|
||||
audioFile.name+"\nhas been deleted successfully")
|
||||
audioFile.Name()+"\nhas been deleted successfully")
|
||||
go gomu.app.QueueUpdateDraw(func() {
|
||||
p.refresh()
|
||||
// Here we remove the song from queue
|
||||
@ -308,13 +259,13 @@ func (p *Playlist) addAllToQueue(root *tview.TreeNode) {
|
||||
childrens = root.GetChildren()
|
||||
|
||||
// gets the parent if the highlighted item is a file
|
||||
if root.GetReference().(*AudioFile).isAudioFile {
|
||||
childrens = root.GetReference().(*AudioFile).parent.GetChildren()
|
||||
if root.GetReference().(*player.AudioFile).IsAudioFile() {
|
||||
childrens = root.GetReference().(*player.AudioFile).ParentNode().GetChildren()
|
||||
}
|
||||
|
||||
for _, v := range childrens {
|
||||
currNode := v.GetReference().(*AudioFile)
|
||||
if currNode.isAudioFile {
|
||||
currNode := v.GetReference().(*player.AudioFile)
|
||||
if currNode.IsAudioFile() {
|
||||
|
||||
currSong := gomu.player.GetCurrentSong()
|
||||
if currSong == nil || (currNode.Name() != currSong.Name()) {
|
||||
@ -331,17 +282,17 @@ func (p *Playlist) refresh() {
|
||||
|
||||
root := gomu.playlist.GetRoot()
|
||||
prevNode := gomu.playlist.GetCurrentNode()
|
||||
prevFilepath := prevNode.GetReference().(*AudioFile).Path()
|
||||
prevFilepath := prevNode.GetReference().(*player.AudioFile).Path()
|
||||
|
||||
root.ClearChildren()
|
||||
node := root.GetReference().(*AudioFile)
|
||||
node := root.GetReference().(*player.AudioFile)
|
||||
|
||||
populate(root, node.path, gomu.anko.GetBool("General.sort_by_mtime"))
|
||||
populate(root, node.Path(), gomu.anko.GetBool("General.sort_by_mtime"))
|
||||
|
||||
root.Walk(func(node, _ *tview.TreeNode) bool {
|
||||
|
||||
// to preserve previously highlighted node
|
||||
if node.GetReference().(*AudioFile).Path() == prevFilepath {
|
||||
if node.GetReference().(*player.AudioFile).Path() == prevFilepath {
|
||||
p.setHighlight(node)
|
||||
return false
|
||||
}
|
||||
@ -371,14 +322,13 @@ func (p *Playlist) addSongToPlaylist(
|
||||
return tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
audioFile := &AudioFile{
|
||||
name: songName,
|
||||
path: audioPath,
|
||||
isAudioFile: true,
|
||||
length: audioLength,
|
||||
node: node,
|
||||
parent: selPlaylist,
|
||||
}
|
||||
var audioFile *player.AudioFile
|
||||
audioFile.SetName(songName)
|
||||
audioFile.SetPath(audioPath)
|
||||
audioFile.SetIsAudioFile(true)
|
||||
audioFile.SetLen(audioLength)
|
||||
audioFile.SetNode(node)
|
||||
audioFile.SetParentNode(selPlaylist)
|
||||
|
||||
displayText := setDisplayText(audioFile)
|
||||
|
||||
@ -390,15 +340,15 @@ func (p *Playlist) addSongToPlaylist(
|
||||
}
|
||||
|
||||
// Gets all audio files walks from music root directory
|
||||
func (p *Playlist) getAudioFiles() []*AudioFile {
|
||||
func (p *Playlist) getAudioFiles() []*player.AudioFile {
|
||||
|
||||
root := p.GetRoot()
|
||||
|
||||
audioFiles := []*AudioFile{}
|
||||
audioFiles := []*player.AudioFile{}
|
||||
|
||||
root.Walk(func(node, _ *tview.TreeNode) bool {
|
||||
|
||||
audioFile := node.GetReference().(*AudioFile)
|
||||
audioFile := node.GetReference().(*player.AudioFile)
|
||||
audioFiles = append(audioFiles, audioFile)
|
||||
|
||||
return true
|
||||
@ -412,7 +362,7 @@ func (p *Playlist) createPlaylist(name string) error {
|
||||
|
||||
selectedNode := p.GetCurrentNode()
|
||||
|
||||
parentNode := selectedNode.GetReference().(*AudioFile).parent
|
||||
parentNode := selectedNode.GetReference().(*player.AudioFile).ParentNode()
|
||||
|
||||
// if the current node is the root
|
||||
// sets the parent to itself
|
||||
@ -420,9 +370,9 @@ func (p *Playlist) createPlaylist(name string) error {
|
||||
parentNode = selectedNode
|
||||
}
|
||||
|
||||
audioFile := parentNode.GetReference().(*AudioFile)
|
||||
audioFile := parentNode.GetReference().(*player.AudioFile)
|
||||
|
||||
err := os.Mkdir(path.Join(audioFile.path, name), 0744)
|
||||
err := os.Mkdir(path.Join(audioFile.Path(), name), 0744)
|
||||
|
||||
if err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
@ -439,7 +389,7 @@ func (p *Playlist) createPlaylist(name string) error {
|
||||
func (p *Playlist) setHighlight(currNode *tview.TreeNode) {
|
||||
|
||||
if p.prevNode != nil {
|
||||
if p.prevNode.GetReference().(*AudioFile).isAudioFile {
|
||||
if p.prevNode.GetReference().(*player.AudioFile).IsAudioFile() {
|
||||
p.prevNode.SetColor(gomu.colors.foreground)
|
||||
} else {
|
||||
p.prevNode.SetColor(gomu.colors.playlistDir)
|
||||
@ -454,17 +404,17 @@ func (p *Playlist) setHighlight(currNode *tview.TreeNode) {
|
||||
|
||||
// Traverses the playlist and finds the AudioFile struct
|
||||
// audioName must be hashed with sha1 first
|
||||
func (p *Playlist) findAudioFile(audioName string) (*AudioFile, error) {
|
||||
func (p *Playlist) findAudioFile(audioName string) (*player.AudioFile, error) {
|
||||
|
||||
root := p.GetRoot()
|
||||
|
||||
var selNode *AudioFile
|
||||
var selNode *player.AudioFile
|
||||
|
||||
root.Walk(func(node, _ *tview.TreeNode) bool {
|
||||
|
||||
audioFile := node.GetReference().(*AudioFile)
|
||||
audioFile := node.GetReference().(*player.AudioFile)
|
||||
|
||||
hashed := sha1Hex(getName(audioFile.name))
|
||||
hashed := sha1Hex(getName(audioFile.Name()))
|
||||
|
||||
if hashed == audioName {
|
||||
selNode = audioFile
|
||||
@ -484,16 +434,16 @@ func (p *Playlist) findAudioFile(audioName string) (*AudioFile, error) {
|
||||
func (p *Playlist) rename(newName string) error {
|
||||
|
||||
currentNode := p.GetCurrentNode()
|
||||
audio := currentNode.GetReference().(*AudioFile)
|
||||
audio := currentNode.GetReference().(*player.AudioFile)
|
||||
|
||||
pathToFile, _ := filepath.Split(audio.path)
|
||||
pathToFile, _ := filepath.Split(audio.Path())
|
||||
var newPath string
|
||||
if audio.isAudioFile {
|
||||
if audio.IsAudioFile() {
|
||||
newPath = pathToFile + newName + ".mp3"
|
||||
} else {
|
||||
newPath = pathToFile + newName
|
||||
}
|
||||
err := os.Rename(audio.path, newPath)
|
||||
err := os.Rename(audio.Path(), newPath)
|
||||
if err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
}
|
||||
@ -553,8 +503,8 @@ func ytdl(url string, selPlaylist *tview.TreeNode) error {
|
||||
return tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
selAudioFile := selPlaylist.GetReference().(*AudioFile)
|
||||
dir := selAudioFile.path
|
||||
selAudioFile := selPlaylist.GetReference().(*player.AudioFile)
|
||||
dir := selAudioFile.Path()
|
||||
|
||||
defaultTimedPopup(" Ytdl ", "Downloading")
|
||||
|
||||
@ -722,20 +672,19 @@ func populate(root *tview.TreeNode, rootPath string, sortMtime bool) error {
|
||||
continue
|
||||
}
|
||||
|
||||
audioFile := &AudioFile{
|
||||
name: songName,
|
||||
path: path,
|
||||
isAudioFile: true,
|
||||
node: child,
|
||||
parent: root,
|
||||
}
|
||||
audioFile := player.NewAudioFile()
|
||||
audioFile.SetName(songName)
|
||||
audioFile.SetPath(path)
|
||||
audioFile.SetIsAudioFile(true)
|
||||
audioFile.SetNode(child)
|
||||
audioFile.SetParentNode(root)
|
||||
|
||||
audioLength, err := getTagLength(audioFile.path)
|
||||
audioLength, err := getTagLength(audioFile.Path())
|
||||
if err != nil {
|
||||
logError(err)
|
||||
}
|
||||
|
||||
audioFile.length = audioLength
|
||||
audioFile.SetLen(audioLength)
|
||||
|
||||
displayText := setDisplayText(audioFile)
|
||||
|
||||
@ -747,13 +696,12 @@ func populate(root *tview.TreeNode, rootPath string, sortMtime bool) error {
|
||||
|
||||
if file.IsDir() || file.Mode()&os.ModeSymlink != 0 {
|
||||
|
||||
audioFile := &AudioFile{
|
||||
name: songName,
|
||||
path: path,
|
||||
isAudioFile: false,
|
||||
node: child,
|
||||
parent: root,
|
||||
}
|
||||
audioFile := player.NewAudioFile()
|
||||
audioFile.SetName(songName)
|
||||
audioFile.SetPath(path)
|
||||
audioFile.SetIsAudioFile(false)
|
||||
audioFile.SetNode(child)
|
||||
audioFile.SetParentNode(root)
|
||||
|
||||
displayText := setDisplayText(audioFile)
|
||||
|
||||
@ -775,10 +723,10 @@ func (p *Playlist) yank() error {
|
||||
if p.yankFile == nil {
|
||||
return errors.New("no file has been yanked")
|
||||
}
|
||||
if p.yankFile.node == p.GetRoot() {
|
||||
if p.yankFile.Node() == p.GetRoot() {
|
||||
return errors.New("please don't yank the root directory")
|
||||
}
|
||||
defaultTimedPopup(" Success ", p.yankFile.name+"\n has been yanked successfully.")
|
||||
defaultTimedPopup(" Success ", p.yankFile.Name()+"\n has been yanked successfully.")
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -789,13 +737,13 @@ func (p *Playlist) paste() error {
|
||||
}
|
||||
|
||||
oldAudio := p.yankFile
|
||||
oldPathDir, oldPathFileName := filepath.Split(p.yankFile.path)
|
||||
oldPathDir, oldPathFileName := filepath.Split(p.yankFile.Path())
|
||||
pasteFile := p.getCurrentFile()
|
||||
var newPathDir string
|
||||
if pasteFile.isAudioFile {
|
||||
newPathDir, _ = filepath.Split(pasteFile.path)
|
||||
if pasteFile.IsAudioFile() {
|
||||
newPathDir, _ = filepath.Split(pasteFile.Path())
|
||||
} else {
|
||||
newPathDir = pasteFile.path
|
||||
newPathDir = pasteFile.Path()
|
||||
}
|
||||
|
||||
if oldPathDir == newPathDir {
|
||||
@ -803,20 +751,20 @@ func (p *Playlist) paste() error {
|
||||
}
|
||||
|
||||
newPathFull := filepath.Join(newPathDir, oldPathFileName)
|
||||
err := os.Rename(p.yankFile.path, newPathFull)
|
||||
err := os.Rename(p.yankFile.Path(), newPathFull)
|
||||
if err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
defaultTimedPopup(" Success ", p.yankFile.name+"\n has been pasted to\n"+newPathDir)
|
||||
defaultTimedPopup(" Success ", p.yankFile.Name()+"\n has been pasted to\n"+newPathDir)
|
||||
|
||||
// keep queue references updated
|
||||
newAudio := oldAudio
|
||||
newAudio.path = newPathFull
|
||||
newAudio.SetPath(newPathFull)
|
||||
|
||||
p.refresh()
|
||||
gomu.queue.updateQueuePath()
|
||||
if p.yankFile.isAudioFile {
|
||||
if p.yankFile.IsAudioFile() {
|
||||
err = gomu.queue.updateCurrentSongName(oldAudio, newAudio)
|
||||
if err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
@ -833,23 +781,23 @@ func (p *Playlist) paste() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func setDisplayText(audioFile *AudioFile) string {
|
||||
func setDisplayText(audioFile *player.AudioFile) string {
|
||||
useEmoji := gomu.anko.GetBool("General.use_emoji")
|
||||
if !useEmoji {
|
||||
return audioFile.name
|
||||
return audioFile.Name()
|
||||
}
|
||||
|
||||
if audioFile.isAudioFile {
|
||||
if audioFile.IsAudioFile() {
|
||||
emojiFile := gomu.anko.GetString("Emoji.file")
|
||||
return fmt.Sprintf(" %s %s", emojiFile, audioFile.name)
|
||||
return fmt.Sprintf(" %s %s", emojiFile, audioFile.Name())
|
||||
}
|
||||
|
||||
emojiDir := gomu.anko.GetString("Emoji.playlist")
|
||||
return fmt.Sprintf(" %s %s", emojiDir, audioFile.name)
|
||||
return fmt.Sprintf(" %s %s", emojiDir, audioFile.Name())
|
||||
}
|
||||
|
||||
// refreshByNode is called after rename of file or folder, to refresh queue info
|
||||
func (p *Playlist) refreshAfterRename(node *AudioFile, newName string) error {
|
||||
func (p *Playlist) refreshAfterRename(node *player.AudioFile, newName string) error {
|
||||
|
||||
root := p.GetRoot()
|
||||
root.Walk(func(node, _ *tview.TreeNode) bool {
|
||||
@ -860,7 +808,7 @@ func (p *Playlist) refreshAfterRename(node *AudioFile, newName string) error {
|
||||
})
|
||||
// update queue
|
||||
newNode := p.getCurrentFile()
|
||||
if node.isAudioFile {
|
||||
if node.IsAudioFile() {
|
||||
err := gomu.queue.renameItem(node, newNode)
|
||||
if err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
|
18
popup.go
18
popup.go
@ -144,7 +144,7 @@ func confirmDeleteAllPopup(selPlaylist *tview.TreeNode) (err error) {
|
||||
gomu.popups.pop()
|
||||
|
||||
if confirmationText == "DELETE" {
|
||||
audioFile := selPlaylist.GetReference().(*AudioFile)
|
||||
audioFile := selPlaylist.GetReference().(*player.AudioFile)
|
||||
err = gomu.playlist.deletePlaylist(audioFile)
|
||||
if err != nil {
|
||||
errorPopup(err)
|
||||
@ -555,10 +555,10 @@ func newInputPopup(popupID, title, label string, text string) *tview.InputField
|
||||
return inputField
|
||||
}
|
||||
|
||||
func renamePopup(node *AudioFile) {
|
||||
func renamePopup(node *player.AudioFile) {
|
||||
|
||||
popupID := "rename-input-popup"
|
||||
input := newInputPopup(popupID, " Rename ", "New name: ", node.name)
|
||||
input := newInputPopup(popupID, " Rename ", "New name: ", node.Name())
|
||||
input.SetInputCapture(func(e *tcell.EventKey) *tcell.EventKey {
|
||||
|
||||
switch e.Key() {
|
||||
@ -831,10 +831,10 @@ func ytSearchPopup() {
|
||||
|
||||
var dir *tview.TreeNode
|
||||
|
||||
if audioFile.isAudioFile {
|
||||
dir = audioFile.parent
|
||||
if audioFile.IsAudioFile() {
|
||||
dir = audioFile.ParentNode()
|
||||
} else {
|
||||
dir = audioFile.node
|
||||
dir = audioFile.Node()
|
||||
}
|
||||
|
||||
go func() {
|
||||
@ -860,14 +860,14 @@ func ytSearchPopup() {
|
||||
})
|
||||
}
|
||||
|
||||
func lyricPopup(lang string, audioFile *AudioFile, wg *sync.WaitGroup) error {
|
||||
func lyricPopup(lang string, audioFile *player.AudioFile, wg *sync.WaitGroup) error {
|
||||
|
||||
var titles []string
|
||||
|
||||
// below we chose LyricFetcher interfaces by language
|
||||
lyricFetcher := lyricLang(lang)
|
||||
|
||||
results, err := lyricFetcher.LyricOptions(audioFile.name)
|
||||
results, err := lyricFetcher.LyricOptions(audioFile.Name())
|
||||
if err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
}
|
||||
@ -905,7 +905,7 @@ func lyricPopup(lang string, audioFile *AudioFile, wg *sync.WaitGroup) error {
|
||||
return
|
||||
}
|
||||
lyric.LangExt = lang
|
||||
err = embedLyric(audioFile.path, &lyric, false)
|
||||
err = embedLyric(audioFile.Path(), &lyric, false)
|
||||
if err != nil {
|
||||
errorPopup(err)
|
||||
gomu.app.Draw()
|
||||
|
74
queue.go
74
queue.go
@ -17,13 +17,15 @@ import (
|
||||
"github.com/gdamore/tcell/v2"
|
||||
"github.com/rivo/tview"
|
||||
"github.com/ztrue/tracerr"
|
||||
|
||||
"github.com/issadarkthing/gomu/player"
|
||||
)
|
||||
|
||||
// Queue shows queued songs for playing
|
||||
type Queue struct {
|
||||
*tview.List
|
||||
savedQueuePath string
|
||||
items []*AudioFile
|
||||
items []*player.AudioFile
|
||||
isLoop bool
|
||||
}
|
||||
|
||||
@ -45,19 +47,19 @@ func (q *Queue) prev() {
|
||||
|
||||
// Usually used with GetCurrentItem which can return -1 if
|
||||
// no item highlighted
|
||||
func (q *Queue) deleteItem(index int) (*AudioFile, error) {
|
||||
func (q *Queue) deleteItem(index int) (*player.AudioFile, error) {
|
||||
|
||||
if index > len(q.items)-1 {
|
||||
return nil, tracerr.New("Index out of range")
|
||||
}
|
||||
|
||||
// deleted audio file
|
||||
var dAudio *AudioFile
|
||||
var dAudio *player.AudioFile
|
||||
|
||||
if index != -1 {
|
||||
q.RemoveItem(index)
|
||||
|
||||
var nItems []*AudioFile
|
||||
var nItems []*player.AudioFile
|
||||
|
||||
for i, v := range q.items {
|
||||
|
||||
@ -87,7 +89,7 @@ func (q *Queue) updateTitle() string {
|
||||
var totalLength time.Duration
|
||||
|
||||
for _, v := range q.items {
|
||||
totalLength += v.length
|
||||
totalLength += v.Len()
|
||||
}
|
||||
|
||||
fmtTime := fmtDurationH(totalLength)
|
||||
@ -127,23 +129,23 @@ func (q *Queue) updateTitle() string {
|
||||
}
|
||||
|
||||
// Add item to the front of the queue
|
||||
func (q *Queue) pushFront(audioFile *AudioFile) {
|
||||
func (q *Queue) pushFront(audioFile *player.AudioFile) {
|
||||
|
||||
q.items = append([]*AudioFile{audioFile}, q.items...)
|
||||
q.items = append([]*player.AudioFile{audioFile}, q.items...)
|
||||
|
||||
songLength := audioFile.length
|
||||
songLength := audioFile.Len()
|
||||
|
||||
queueItemView := fmt.Sprintf(
|
||||
"[ %s ] %s", fmtDuration(songLength), getName(audioFile.name),
|
||||
"[ %s ] %s", fmtDuration(songLength), getName(audioFile.Name()),
|
||||
)
|
||||
|
||||
q.InsertItem(0, queueItemView, audioFile.path, 0, nil)
|
||||
q.InsertItem(0, queueItemView, audioFile.Path(), 0, nil)
|
||||
q.updateTitle()
|
||||
}
|
||||
|
||||
// gets the first item and remove it from the queue
|
||||
// app.Draw() must be called after calling this function
|
||||
func (q *Queue) dequeue() (*AudioFile, error) {
|
||||
func (q *Queue) dequeue() (*player.AudioFile, error) {
|
||||
|
||||
if q.GetItemCount() == 0 {
|
||||
return nil, tracerr.New("Empty list")
|
||||
@ -157,23 +159,23 @@ func (q *Queue) dequeue() (*AudioFile, error) {
|
||||
}
|
||||
|
||||
// Add item to the list and returns the length of the queue
|
||||
func (q *Queue) enqueue(audioFile *AudioFile) (int, error) {
|
||||
func (q *Queue) enqueue(audioFile *player.AudioFile) (int, error) {
|
||||
|
||||
if !audioFile.isAudioFile {
|
||||
if !audioFile.IsAudioFile() {
|
||||
return q.GetItemCount(), nil
|
||||
}
|
||||
|
||||
q.items = append(q.items, audioFile)
|
||||
songLength, err := getTagLength(audioFile.path)
|
||||
songLength, err := getTagLength(audioFile.Path())
|
||||
|
||||
if err != nil {
|
||||
return 0, tracerr.Wrap(err)
|
||||
}
|
||||
|
||||
queueItemView := fmt.Sprintf(
|
||||
"[ %s ] %s", fmtDuration(songLength), getName(audioFile.name),
|
||||
"[ %s ] %s", fmtDuration(songLength), getName(audioFile.Name()),
|
||||
)
|
||||
q.AddItem(queueItemView, audioFile.path, 0, nil)
|
||||
q.AddItem(queueItemView, audioFile.Path(), 0, nil)
|
||||
q.updateTitle()
|
||||
|
||||
return q.GetItemCount(), nil
|
||||
@ -236,7 +238,7 @@ func (q *Queue) saveQueue() error {
|
||||
// Clears current queue
|
||||
func (q *Queue) clearQueue() {
|
||||
|
||||
q.items = []*AudioFile{}
|
||||
q.items = []*player.AudioFile{}
|
||||
q.Clear()
|
||||
q.updateTitle()
|
||||
|
||||
@ -335,13 +337,13 @@ func (q *Queue) shuffle() {
|
||||
q.Clear()
|
||||
|
||||
for _, v := range q.items {
|
||||
audioLen, err := getTagLength(v.path)
|
||||
audioLen, err := getTagLength(v.Path())
|
||||
if err != nil {
|
||||
logError(err)
|
||||
}
|
||||
|
||||
queueText := fmt.Sprintf("[ %s ] %s", fmtDuration(audioLen), v.name)
|
||||
q.AddItem(queueText, v.path, 0, nil)
|
||||
queueText := fmt.Sprintf("[ %s ] %s", fmtDuration(audioLen), v.Name())
|
||||
q.AddItem(queueText, v.Path(), 0, nil)
|
||||
}
|
||||
|
||||
// q.updateTitle()
|
||||
@ -416,9 +418,9 @@ func sha1Hex(input string) string {
|
||||
}
|
||||
|
||||
// Modify the title of songs in queue
|
||||
func (q *Queue) renameItem(oldAudio *AudioFile, newAudio *AudioFile) error {
|
||||
func (q *Queue) renameItem(oldAudio *player.AudioFile, newAudio *player.AudioFile) error {
|
||||
for i, v := range q.items {
|
||||
if v.name != oldAudio.name {
|
||||
if v.Name() != oldAudio.Name() {
|
||||
continue
|
||||
}
|
||||
err := q.insertItem(i, newAudio)
|
||||
@ -449,24 +451,24 @@ func (q *Queue) playQueue() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (q *Queue) insertItem(index int, audioFile *AudioFile) error {
|
||||
func (q *Queue) insertItem(index int, audioFile *player.AudioFile) error {
|
||||
|
||||
if index > len(q.items)-1 {
|
||||
return tracerr.New("Index out of range")
|
||||
}
|
||||
|
||||
if index != -1 {
|
||||
songLength, err := getTagLength(audioFile.path)
|
||||
songLength, err := getTagLength(audioFile.Path())
|
||||
if err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
}
|
||||
queueItemView := fmt.Sprintf(
|
||||
"[ %s ] %s", fmtDuration(songLength), getName(audioFile.name),
|
||||
"[ %s ] %s", fmtDuration(songLength), getName(audioFile.Name()),
|
||||
)
|
||||
|
||||
q.InsertItem(index, queueItemView, audioFile.path, 0, nil)
|
||||
q.InsertItem(index, queueItemView, audioFile.Path(), 0, nil)
|
||||
|
||||
var nItems []*AudioFile
|
||||
var nItems []*player.AudioFile
|
||||
|
||||
for i, v := range q.items {
|
||||
|
||||
@ -493,7 +495,7 @@ func (q *Queue) updateQueuePath() {
|
||||
return
|
||||
}
|
||||
for _, v := range q.items {
|
||||
song := sha1Hex(getName(v.name))
|
||||
song := sha1Hex(getName(v.Name()))
|
||||
songs = append(songs, song)
|
||||
}
|
||||
|
||||
@ -512,7 +514,7 @@ func (q *Queue) updateQueuePath() {
|
||||
}
|
||||
|
||||
// update current playing song name to reflect the changes during rename and paste
|
||||
func (q *Queue) updateCurrentSongName(oldAudio *AudioFile, newAudio *AudioFile) error {
|
||||
func (q *Queue) updateCurrentSongName(oldAudio *player.AudioFile, newAudio *player.AudioFile) error {
|
||||
|
||||
if !gomu.player.IsRunning() && !gomu.player.IsPaused() {
|
||||
return nil
|
||||
@ -522,7 +524,7 @@ func (q *Queue) updateCurrentSongName(oldAudio *AudioFile, newAudio *AudioFile)
|
||||
position := gomu.playingBar.getProgress()
|
||||
paused := gomu.player.IsPaused()
|
||||
|
||||
if oldAudio.name != currentSong.Name() {
|
||||
if oldAudio.Name() != currentSong.Name() {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -542,7 +544,7 @@ func (q *Queue) updateCurrentSongName(oldAudio *AudioFile, newAudio *AudioFile)
|
||||
}
|
||||
|
||||
// update current playing song path to reflect the changes during rename and paste
|
||||
func (q *Queue) updateCurrentSongPath(oldAudio *AudioFile, newAudio *AudioFile) error {
|
||||
func (q *Queue) updateCurrentSongPath(oldAudio *player.AudioFile, newAudio *player.AudioFile) error {
|
||||
|
||||
if !gomu.player.IsRunning() && !gomu.player.IsPaused() {
|
||||
return nil
|
||||
@ -553,7 +555,7 @@ func (q *Queue) updateCurrentSongPath(oldAudio *AudioFile, newAudio *AudioFile)
|
||||
paused := gomu.player.IsPaused()
|
||||
|
||||
// Here we check the situation when currentsong is under oldAudio folder
|
||||
if !strings.Contains(currentSong.Path(), oldAudio.path) {
|
||||
if !strings.Contains(currentSong.Path(), oldAudio.Path()) {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -578,7 +580,7 @@ func (q *Queue) updateCurrentSongPath(oldAudio *AudioFile, newAudio *AudioFile)
|
||||
}
|
||||
|
||||
// update current playing song simply delete it
|
||||
func (q *Queue) updateCurrentSongDelete(oldAudio *AudioFile) {
|
||||
func (q *Queue) updateCurrentSongDelete(oldAudio *player.AudioFile) {
|
||||
if !gomu.player.IsRunning() && !gomu.player.IsPaused() {
|
||||
return
|
||||
}
|
||||
@ -587,12 +589,12 @@ func (q *Queue) updateCurrentSongDelete(oldAudio *AudioFile) {
|
||||
paused := gomu.player.IsPaused()
|
||||
|
||||
var delete bool
|
||||
if oldAudio.isAudioFile {
|
||||
if oldAudio.name == currentSong.Name() {
|
||||
if oldAudio.IsAudioFile() {
|
||||
if oldAudio.Name() == currentSong.Name() {
|
||||
delete = true
|
||||
}
|
||||
} else {
|
||||
if strings.Contains(currentSong.Path(), oldAudio.path) {
|
||||
if strings.Contains(currentSong.Path(), oldAudio.Path()) {
|
||||
delete = true
|
||||
}
|
||||
}
|
||||
|
8
start.go
8
start.go
@ -75,7 +75,7 @@ func defineInternals() {
|
||||
root := gomu.playlist.GetRoot()
|
||||
root.Walk(func(node, _ *tview.TreeNode) bool {
|
||||
|
||||
if node.GetReference().(*AudioFile).Path() == filepath {
|
||||
if node.GetReference().(*player.AudioFile).Path() == filepath {
|
||||
gomu.playlist.setHighlight(node)
|
||||
return false
|
||||
}
|
||||
@ -85,7 +85,7 @@ func defineInternals() {
|
||||
})
|
||||
|
||||
queue, _ := gomu.anko.NewModule("Queue")
|
||||
queue.Define("get_focused", func() *AudioFile {
|
||||
queue.Define("get_focused", func() *player.AudioFile {
|
||||
index := gomu.queue.GetCurrentItem()
|
||||
if index < 0 || index > len(gomu.queue.items)-1 {
|
||||
return nil
|
||||
@ -373,7 +373,7 @@ func start(application *tview.Application, args Args) {
|
||||
}
|
||||
}
|
||||
|
||||
audioFile := audio.(*AudioFile)
|
||||
audioFile := audio.(*player.AudioFile)
|
||||
|
||||
gomu.playingBar.newProgress(audioFile, int(duration.Seconds()))
|
||||
|
||||
@ -404,7 +404,7 @@ func start(application *tview.Application, args Args) {
|
||||
gomu.playingBar.subtitles = nil
|
||||
gomu.playingBar.subtitle = nil
|
||||
if gomu.queue.isLoop {
|
||||
_, err = gomu.queue.enqueue(currAudio.(*AudioFile))
|
||||
_, err = gomu.queue.enqueue(currAudio.(*player.AudioFile))
|
||||
if err != nil {
|
||||
logError(err)
|
||||
}
|
||||
|
55
tageditor.go
55
tageditor.go
@ -5,7 +5,6 @@ package main
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@ -15,6 +14,7 @@ import (
|
||||
"github.com/ztrue/tracerr"
|
||||
|
||||
"github.com/issadarkthing/gomu/lyric"
|
||||
"github.com/issadarkthing/gomu/player"
|
||||
)
|
||||
|
||||
// lyricFlex extend the flex control to modify the Focus item
|
||||
@ -26,10 +26,10 @@ type lyricFlex struct {
|
||||
}
|
||||
|
||||
// tagPopup is used to edit tag, delete and fetch lyrics
|
||||
func tagPopup(node *AudioFile) (err error) {
|
||||
func tagPopup(node *player.AudioFile) (err error) {
|
||||
|
||||
popupID := "tag-editor-input-popup"
|
||||
tag, popupLyricMap, options, err := node.loadTagMap()
|
||||
tag, popupLyricMap, options, err := node.LoadTagMap()
|
||||
if err != nil {
|
||||
return tracerr.Wrap(err)
|
||||
}
|
||||
@ -66,7 +66,7 @@ func tagPopup(node *AudioFile) (err error) {
|
||||
|
||||
leftBox := tview.NewBox().
|
||||
SetBorder(true).
|
||||
SetTitle(node.name).
|
||||
SetTitle(node.Name()).
|
||||
SetBackgroundColor(gomu.colors.popup).
|
||||
SetBorderColor(gomu.colors.accent).
|
||||
SetTitleColor(gomu.colors.accent).
|
||||
@ -77,7 +77,7 @@ func tagPopup(node *AudioFile) (err error) {
|
||||
audioFile := node
|
||||
go func() {
|
||||
var lyricFetcher lyric.LyricFetcherCn
|
||||
results, err := lyricFetcher.LyricOptions(audioFile.name)
|
||||
results, err := lyricFetcher.LyricOptions(audioFile.Name())
|
||||
if err != nil {
|
||||
errorPopup(err)
|
||||
return
|
||||
@ -105,7 +105,7 @@ func tagPopup(node *AudioFile) (err error) {
|
||||
titleInputField.SetText(newTag.Title)
|
||||
albumInputField.SetText(newTag.Album)
|
||||
|
||||
tag, err = id3v2.Open(node.path, id3v2.Options{Parse: true})
|
||||
tag, err = id3v2.Open(node.Path(), id3v2.Options{Parse: true})
|
||||
if err != nil {
|
||||
errorPopup(err)
|
||||
return
|
||||
@ -150,7 +150,10 @@ func tagPopup(node *AudioFile) (err error) {
|
||||
SetTitleColor(gomu.colors.accent)
|
||||
|
||||
saveTagButton.SetSelectedFunc(func() {
|
||||
tag, err = id3v2.Open(node.path, id3v2.Options{Parse: true})
|
||||
tag, err = id3v2.Open(node.Path(), id3v2.Options{
|
||||
Parse: true,
|
||||
ParseFrames: []string{},
|
||||
})
|
||||
if err != nil {
|
||||
errorPopup(err)
|
||||
return
|
||||
@ -213,7 +216,7 @@ func tagPopup(node *AudioFile) (err error) {
|
||||
LangExt: langExt,
|
||||
}
|
||||
if len(options) > 0 {
|
||||
err := embedLyric(node.path, lyric, true)
|
||||
err := embedLyric(node.Path(), lyric, true)
|
||||
if err != nil {
|
||||
errorPopup(err)
|
||||
return
|
||||
@ -278,7 +281,7 @@ func tagPopup(node *AudioFile) (err error) {
|
||||
audioFile := gomu.playlist.getCurrentFile()
|
||||
_, lang := getLyricDropDown.GetCurrentOption()
|
||||
|
||||
if !audioFile.isAudioFile {
|
||||
if !audioFile.IsAudioFile() {
|
||||
errorPopup(errors.New("not an audio file"))
|
||||
return
|
||||
}
|
||||
@ -298,7 +301,7 @@ func tagPopup(node *AudioFile) (err error) {
|
||||
go func() {
|
||||
// This is to ensure that the above go routine finish.
|
||||
wg.Wait()
|
||||
_, popupLyricMap, newOptions, err := audioFile.loadTagMap()
|
||||
_, popupLyricMap, newOptions, err := audioFile.LoadTagMap()
|
||||
if err != nil {
|
||||
errorPopup(err)
|
||||
gomu.app.Draw()
|
||||
@ -481,35 +484,3 @@ func (f *lyricFlex) Focus(delegate func(p tview.Primitive)) {
|
||||
f.Flex.Focus(delegate)
|
||||
}
|
||||
}
|
||||
|
||||
// loadTagMap will load from tag and return a map of langExt to lyrics
|
||||
func (a *AudioFile) loadTagMap() (tag *id3v2.Tag, popupLyricMap map[string]string, options []string, err error) {
|
||||
|
||||
popupLyricMap = make(map[string]string)
|
||||
|
||||
if a.isAudioFile {
|
||||
tag, err = id3v2.Open(a.path, id3v2.Options{Parse: true})
|
||||
if err != nil {
|
||||
return nil, nil, nil, tracerr.Wrap(err)
|
||||
}
|
||||
defer tag.Close()
|
||||
} else {
|
||||
return nil, nil, nil, fmt.Errorf("not an audio file")
|
||||
}
|
||||
usltFrames := tag.GetFrames(tag.CommonID("Unsynchronised lyrics/text transcription"))
|
||||
|
||||
for _, f := range usltFrames {
|
||||
uslf, ok := f.(id3v2.UnsynchronisedLyricsFrame)
|
||||
if !ok {
|
||||
die(errors.New("USLT error"))
|
||||
}
|
||||
res := uslf.Lyrics
|
||||
popupLyricMap[uslf.ContentDescriptor] = res
|
||||
}
|
||||
for option := range popupLyricMap {
|
||||
options = append(options, option)
|
||||
}
|
||||
sort.Strings(options)
|
||||
|
||||
return tag, popupLyricMap, options, err
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user