7f1c3f7c55
This is a very simple Implementation of searching like playlist view and file view there is an boolean value that is checked in the draw function to check if whether or not to draw the Search view Later on I am thinking of rewriting this whole mechanism with pages which will make this more modular. The Boolean values are set and unset by the navigation menu and the done functions.
269 lines
6.1 KiB
Go
269 lines
6.1 KiB
Go
package main
|
|
|
|
import (
|
|
"sort"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/aditya-K2/goMP/config"
|
|
"github.com/aditya-K2/goMP/search"
|
|
"github.com/fhs/gompd/mpd"
|
|
"github.com/gdamore/tcell/v2"
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
var (
|
|
CONN *mpd.Client
|
|
UI *Application
|
|
NOTIFICATION_SERVER *NotificationServer
|
|
Volume int64
|
|
Random bool
|
|
Repeat bool
|
|
InsidePlaylist bool = true
|
|
InsideSearchView bool = false
|
|
ARTIST_TREE map[string]map[string]map[string]string
|
|
)
|
|
|
|
func main() {
|
|
config.ReadConfig()
|
|
// Connect to MPD server
|
|
var mpdConnectionError error
|
|
CONN, mpdConnectionError = mpd.Dial("tcp", "localhost:"+viper.GetString("MPD_PORT"))
|
|
if mpdConnectionError != nil {
|
|
panic(mpdConnectionError)
|
|
}
|
|
defer CONN.Close()
|
|
|
|
r := newRenderer()
|
|
c, _ := CONN.CurrentSong()
|
|
if len(c) != 0 {
|
|
r.Start(c["file"])
|
|
} else {
|
|
r.Start("stop")
|
|
}
|
|
|
|
UI = newApplication(r)
|
|
|
|
fileMap, err := CONN.GetFiles()
|
|
dirTree := generateDirectoryTree(fileMap)
|
|
|
|
UpdatePlaylist(UI.ExpandedView)
|
|
|
|
_v, _ := CONN.Status()
|
|
Volume, _ = strconv.ParseInt(_v["volume"], 10, 64)
|
|
Random, _ = strconv.ParseBool(_v["random"])
|
|
Repeat, _ = strconv.ParseBool(_v["repeat"])
|
|
|
|
ARTIST_TREE, err = GenerateArtistTree()
|
|
NOTIFICATION_SERVER = NewNotificationServer()
|
|
NOTIFICATION_SERVER.Start()
|
|
|
|
var SEARCH_CONTENT_SLICE []interface{}
|
|
|
|
UI.ExpandedView.SetDrawFunc(func(s tcell.Screen, x, y, width, height int) (int, int, int, int) {
|
|
if InsidePlaylist {
|
|
UpdatePlaylist(UI.ExpandedView)
|
|
} else if InsideSearchView {
|
|
UpdateSearchView(UI.ExpandedView, SEARCH_CONTENT_SLICE)
|
|
} else {
|
|
Update(dirTree.children, UI.ExpandedView)
|
|
}
|
|
return UI.ExpandedView.GetInnerRect()
|
|
})
|
|
|
|
var FUNC_MAP = map[string]func(){
|
|
"showChildrenContent": func() {
|
|
r, _ := UI.ExpandedView.GetSelection()
|
|
if !InsidePlaylist && !InsideSearchView {
|
|
if len(dirTree.children[r].children) == 0 {
|
|
id, _ := CONN.AddId(dirTree.children[r].absolutePath, -1)
|
|
CONN.PlayId(id)
|
|
} else {
|
|
Update(dirTree.children[r].children, UI.ExpandedView)
|
|
dirTree = &dirTree.children[r]
|
|
}
|
|
} else if InsidePlaylist {
|
|
CONN.Play(r)
|
|
} else if InsideSearchView {
|
|
r, _ := UI.ExpandedView.GetSelection()
|
|
AddToPlaylist(SEARCH_CONTENT_SLICE[r], true)
|
|
}
|
|
},
|
|
"togglePlayBack": func() {
|
|
togglePlayBack()
|
|
},
|
|
"showParentContent": func() {
|
|
if !InsidePlaylist && !InsideSearchView {
|
|
if dirTree.parent != nil {
|
|
Update(dirTree.parent.children, UI.ExpandedView)
|
|
dirTree = dirTree.parent
|
|
}
|
|
}
|
|
},
|
|
"nextSong": func() {
|
|
CONN.Next()
|
|
},
|
|
"clearPlaylist": func() {
|
|
CONN.Clear()
|
|
NOTIFICATION_SERVER.Send("PlayList Cleared")
|
|
},
|
|
"previousSong": func() {
|
|
CONN.Previous()
|
|
},
|
|
"addToPlaylist": func() {
|
|
if !InsidePlaylist && !InsideSearchView {
|
|
r, _ := UI.ExpandedView.GetSelection()
|
|
CONN.Add(dirTree.children[r].absolutePath)
|
|
} else if InsideSearchView {
|
|
r, _ := UI.ExpandedView.GetSelection()
|
|
AddToPlaylist(SEARCH_CONTENT_SLICE[r], false)
|
|
}
|
|
},
|
|
"toggleRandom": func() {
|
|
err := CONN.Random(!Random)
|
|
if err == nil {
|
|
Random = !Random
|
|
}
|
|
},
|
|
"toggleRepeat": func() {
|
|
err := CONN.Repeat(!Repeat)
|
|
if err == nil {
|
|
Repeat = !Repeat
|
|
}
|
|
},
|
|
"decreaseVolume": func() {
|
|
if Volume <= 0 {
|
|
Volume = 0
|
|
} else {
|
|
Volume -= 10
|
|
}
|
|
CONN.SetVolume(int(Volume))
|
|
},
|
|
"increaseVolume": func() {
|
|
if Volume >= 100 {
|
|
Volume = 100
|
|
} else {
|
|
Volume += 10
|
|
}
|
|
CONN.SetVolume(int(Volume))
|
|
},
|
|
"navigateToFiles": func() {
|
|
InsidePlaylist = false
|
|
InsideSearchView = false
|
|
UI.Navbar.Select(1, 0)
|
|
Update(dirTree.children, UI.ExpandedView)
|
|
},
|
|
"navigateToPlaylist": func() {
|
|
InsidePlaylist = true
|
|
InsideSearchView = false
|
|
UI.Navbar.Select(0, 0)
|
|
UpdatePlaylist(UI.ExpandedView)
|
|
},
|
|
"navigateToMostPlayed": func() {
|
|
InsideSearchView = false
|
|
InsidePlaylist = false
|
|
UI.Navbar.Select(2, 0)
|
|
},
|
|
"navigateToSearch": func() {
|
|
InsideSearchView = true
|
|
InsidePlaylist = false
|
|
UI.Navbar.Select(3, 0)
|
|
},
|
|
"quit": func() {
|
|
UI.App.Stop()
|
|
},
|
|
"stop": func() {
|
|
CONN.Stop()
|
|
NOTIFICATION_SERVER.Send("Playback Stopped")
|
|
},
|
|
"updateDB": func() {
|
|
_, err = CONN.Update("")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
NOTIFICATION_SERVER.Send("Database Updated")
|
|
},
|
|
"deleteSongFromPlaylist": func() {
|
|
if InsidePlaylist {
|
|
r, _ := UI.ExpandedView.GetSelection()
|
|
CONN.Delete(r, -1)
|
|
}
|
|
},
|
|
"FocusSearch": func() {
|
|
UI.App.SetFocus(UI.SearchBar)
|
|
},
|
|
}
|
|
|
|
config.GenerateKeyMap(FUNC_MAP)
|
|
|
|
UI.SearchBar.SetAutocompleteFunc(func(c string) []string {
|
|
if c != "" && c != " " && c != " " {
|
|
var p search.PairList
|
|
for k2, v := range ARTIST_TREE {
|
|
p = append(p, search.Pair{Key: k2, Value: search.GetLevenshteinDistance(c, k2)})
|
|
for k1, v1 := range v {
|
|
p = append(p, search.Pair{Key: k1, Value: search.GetLevenshteinDistance(c, k1)})
|
|
for k := range v1 {
|
|
p = append(p, search.Pair{Key: k, Value: search.GetLevenshteinDistance(c, k)})
|
|
}
|
|
}
|
|
}
|
|
sort.Sort(p)
|
|
var suggestions []string
|
|
i := 0
|
|
for _, k := range p {
|
|
if i == 10 {
|
|
break
|
|
}
|
|
_, _, w, _ := UI.SearchBar.GetRect()
|
|
suggestions = append(suggestions, getFormattedString(k.Key, w-2))
|
|
i++
|
|
}
|
|
return suggestions
|
|
} else {
|
|
return make([]string, 0)
|
|
}
|
|
})
|
|
|
|
UI.ExpandedView.SetInputCapture(func(e *tcell.EventKey) *tcell.EventKey {
|
|
if val, ok := config.KEY_MAP[int(e.Rune())]; ok {
|
|
FUNC_MAP[val]()
|
|
return nil
|
|
} else {
|
|
return e
|
|
}
|
|
})
|
|
|
|
UI.SearchBar.SetDoneFunc(func(e tcell.Key) {
|
|
if e == tcell.KeyEnter {
|
|
UI.ExpandedView.Select(0, 0)
|
|
InsideSearchView = true
|
|
InsidePlaylist = false
|
|
SEARCH_CONTENT_SLICE = nil
|
|
SEARCH_CONTENT_SLICE, err = GenerateContentSlice(UI.SearchBar.GetText())
|
|
if err != nil {
|
|
NOTIFICATION_SERVER.Send("Could Not Retrieve the Results")
|
|
} else {
|
|
UI.SearchBar.SetText("")
|
|
UI.App.SetFocus(UI.ExpandedView)
|
|
UI.Navbar.Select(3, 0)
|
|
}
|
|
}
|
|
if e == tcell.KeyEscape {
|
|
InsideSearchView = false
|
|
UI.App.SetFocus(UI.ExpandedView)
|
|
}
|
|
})
|
|
|
|
go func() {
|
|
for {
|
|
UI.App.Draw()
|
|
time.Sleep(time.Second)
|
|
}
|
|
}()
|
|
|
|
if err := UI.App.Run(); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|