From 4d55f233d0c78d6656cf372aac6c8a7cf13d9c58 Mon Sep 17 00:00:00 2001 From: aditya-K2 Date: Thu, 9 Dec 2021 02:25:46 +0530 Subject: [PATCH 01/13] Better Way of Caching Instead of Caching by maintaining a cache file as mentioned here https://github.com/aditya-K2/goMP/issues/14#issuecomment-989141798 We can directly check if the file exists if it exists then we can just pass the path to it else we can copy the default image to the path of the imagePath --- cache/cache.go | 60 +++++++++----------------------------------------- 1 file changed, 10 insertions(+), 50 deletions(-) diff --git a/cache/cache.go b/cache/cache.go index 80eba89..cb9228f 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -3,70 +3,30 @@ package cache import ( "errors" "fmt" - "io/ioutil" "os" "strings" ) var ( - USER_CACHE_DIR, err = os.UserCacheDir() - CACHE_LIST map[[2]string]string = make(map[[2]string]string) - CACHE_DIR string = USER_CACHE_DIR - DEFAULT_IMG string + CACHE_DIR string + DEFAULT_IMG string ) func SetCacheDir(path string) { CACHE_DIR = path } -func SetDefaultPath(path string) { - DEFAULT_IMG = path -} - -func LoadCache(path string) error { - cacheFileContent, err := ioutil.ReadFile(path) - if err != nil { - return errors.New("Could Not Read From Cache File") - } - lineSlice := strings.Split(string(cacheFileContent), "\n") - for _, line := range lineSlice { - if len(line) != 0 { - param := strings.Split(line, "\t") - if len(param) == 3 { - CACHE_LIST[[2]string{param[0], param[1]}] = param[2] - } - } - } - return nil -} - -func GetFromCache(artist, album string) (string, error) { - if val, ok := CACHE_LIST[[2]string{artist, album}]; ok { - return val, nil +func Exists(artist, album string) bool { + if _, err := os.Stat(GenerateName(artist, album)); errors.Is(err, os.ErrNotExist) { + return false } else { - return "", errors.New("Element Not In Cache") - } -} - -func PointToDefault(artist, album string) { - CACHE_LIST[[2]string{artist, album}] = DEFAULT_IMG -} - -func AddToCache(artist, album string) string { - fileName := CACHE_DIR + GenerateName(artist, album) - CACHE_LIST[[2]string{artist, album}] = fileName - return fileName -} - -func WriteCache(path string) { - b, err := os.Create(path) - if err == nil { - for k, v := range CACHE_LIST { - b.Write([]byte(fmt.Sprintf("%s\t%s\t%s\n", k[0], k[1], v))) - } + return true } } func GenerateName(artist, album string) string { - return strings.Replace(strings.Replace(fmt.Sprintf("%s-%s.jpg", artist, album), " ", "_", -1), "/", "_", -1) + if (artist == "" && album == "") || (artist == " " && album == " ") { + return CACHE_DIR + "UnknownArtist-UnknownAlbum.jpg" + } + return CACHE_DIR + strings.Replace(strings.Replace(fmt.Sprintf("%s-%s.jpg", artist, album), " ", "_", -1), "/", "_", -1) } From 62bcda33cbd4e844c0fbf2171c551fbedc0716e4 Mon Sep 17 00:00:00 2001 From: aditya-K2 Date: Thu, 9 Dec 2021 02:28:42 +0530 Subject: [PATCH 02/13] Setting up Defaults --- config/config.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/config/config.go b/config/config.go index c98ee95..a8b3a77 100644 --- a/config/config.go +++ b/config/config.go @@ -10,8 +10,9 @@ import ( ) var ( - HOME_DIR, _ = os.UserHomeDir() - defaults = map[string]interface{}{ + HOME_DIR, _ = os.UserHomeDir() + USER_CACHE_DIR, _ = os.UserCacheDir() + defaults = map[string]interface{}{ "ADDITIONAL_PADDING_X": 12, "ADDITIONAL_PADDING_Y": 16, "IMAGE_WIDTH_EXTRA_X": -1.5, @@ -19,7 +20,7 @@ var ( "MUSIC_DIRECTORY": getMusicDirectory() + "/", "PORT": "6600", "DEFAULT_IMAGE_PATH": "default.jpg", - "COVER_IMAGE_PATH": "cover.jpg", + "CACHE_DIR": USER_CACHE_DIR + "/", } ) From 1d9fe23b0092a10613bef1ac472b5fb561177960 Mon Sep 17 00:00:00 2001 From: aditya-K2 Date: Thu, 9 Dec 2021 02:29:53 +0530 Subject: [PATCH 03/13] if the image is not extracted copy the default image to the image path and return the path to the default image for checking the lastfm api --- imageUtils.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/imageUtils.go b/imageUtils.go index 86f0fd6..9213897 100644 --- a/imageUtils.go +++ b/imageUtils.go @@ -65,23 +65,24 @@ func GetFlacImage(songPath, imagePath string) string { } func extractImageFromFile(uri string, imagePath string) string { + _i := imagePath if strings.HasSuffix(uri, ".mp3") { imagePath := GetMp3Image(uri, imagePath) if imagePath == "" { + Copy(viper.GetString("DEFAULT_IMAGE_PATH"), _i) return viper.GetString("DEFAULT_IMAGE_PATH") - } else { - return imagePath } } else if strings.HasSuffix(uri, ".flac") { imagePath := GetFlacImage(uri, imagePath) if imagePath == "" { + Copy(viper.GetString("DEFAULT_IMAGE_PATH"), _i) return viper.GetString("DEFAULT_IMAGE_PATH") - } else { - return imagePath } } else { + Copy(viper.GetString("DEFAULT_IMAGE_PATH"), _i) return viper.GetString("DEFAULT_IMAGE_PATH") } + return imagePath } func getImg(uri string) (image.Image, error) { From 10566d87a1ce742bf6fe3f3b7414e827a513f593 Mon Sep 17 00:00:00 2001 From: aditya-K2 Date: Thu, 9 Dec 2021 02:30:59 +0530 Subject: [PATCH 04/13] No Need to Load and Write Cache now. --- main.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/main.go b/main.go index 0b82f93..a8069ff 100644 --- a/main.go +++ b/main.go @@ -34,8 +34,6 @@ func main() { } defer CONN.Close() cache.SetCacheDir(viper.GetString("CACHE_DIR")) - cache.SetDefaultPath(viper.GetString("DEFAULT_IMAGE_PATH")) - cache.LoadCache(viper.GetString("CACHE_FILE")) r := newRenderer() c, _ := CONN.CurrentSong() if len(c) != 0 { @@ -256,5 +254,4 @@ func main() { if err := UI.App.Run(); err != nil { panic(err) } - cache.WriteCache(viper.GetString("CACHE_FILE")) } From 13b07bf7f7781bb2a952f9c9e98802d398bc1ab5 Mon Sep 17 00:00:00 2001 From: aditya-K2 Date: Thu, 9 Dec 2021 02:32:02 +0530 Subject: [PATCH 05/13] Update in the Rendering Routine With the updates in the caching mechanism we check if the file exists in cache if yes then extractedImagePath now points to that path else we generate the name for the image and pass the image to extractImage and it passes the default value if no embedded image was found and checks in the lastfm api and the rest works the same. --- render.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/render.go b/render.go index b7797ee..d85b7ee 100644 --- a/render.go +++ b/render.go @@ -75,10 +75,10 @@ func getImagePath(path string) string { a, err := CONN.ListInfo(path) var extractedImage string if err == nil && len(a) != 0 { - if val, err := cache.GetFromCache(a[0]["artist"], a[0]["album"]); err == nil { - extractedImage = val + if cache.Exists(a[0]["artist"], a[0]["album"]) { + extractedImage = cache.GenerateName(a[0]["artist"], a[0]["album"]) } else { - imagePath := cache.AddToCache(a[0]["artist"], a[0]["album"]) + imagePath := cache.GenerateName(a[0]["artist"], a[0]["album"]) absPath := viper.GetString("MUSIC_DIRECTORY") + path extractedImage = extractImageFromFile(absPath, imagePath) if extractedImage == viper.GetString("DEFAULT_IMAGE_PATH") && viper.GetString("GET_COVER_ART_FROM_LAST_FM") == "TRUE" { @@ -88,7 +88,6 @@ func getImagePath(path string) string { extractedImage = downloadedImage } else { NOTIFICATION_SERVER.Send("Falling Back to Default Image.") - cache.PointToDefault(a[0]["artist"], a[0]["album"]) } } else { NOTIFICATION_SERVER.Send("Extracted Image Successfully") From 0bd47c5d3f03ceabbaf6abed07304206f6042709 Mon Sep 17 00:00:00 2001 From: aditya-K2 Date: Thu, 9 Dec 2021 02:34:49 +0530 Subject: [PATCH 06/13] New Copy Function --- utils.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/utils.go b/utils.go index 6f18fc1..1ceb0de 100644 --- a/utils.go +++ b/utils.go @@ -1,6 +1,7 @@ package main import ( + "io/ioutil" "strconv" "strings" "syscall" @@ -94,3 +95,16 @@ func formatString(a interface{}) string { return "Paused" } } + +func Copy(sourceImage, destinationImage string) error { + source, err := ioutil.ReadFile(sourceImage) + if err != nil { + return err + } else { + err = ioutil.WriteFile(destinationImage, source, 0644) + if err != nil { + return err + } + return nil + } +} From 73aebcd0a0bd36a2dd0a3425297236ced9754cf2 Mon Sep 17 00:00:00 2001 From: aditya-K2 Date: Mon, 13 Dec 2021 00:13:16 +0530 Subject: [PATCH 07/13] Added Check for / at the end in directory names --- config/config.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/config/config.go b/config/config.go index a8b3a77..9a57ff4 100644 --- a/config/config.go +++ b/config/config.go @@ -17,10 +17,10 @@ var ( "ADDITIONAL_PADDING_Y": 16, "IMAGE_WIDTH_EXTRA_X": -1.5, "IMAGE_WIDTH_EXTRA_Y": -3.75, - "MUSIC_DIRECTORY": getMusicDirectory() + "/", + "MUSIC_DIRECTORY": CheckDirectoryFmt(getMusicDirectory()), "PORT": "6600", "DEFAULT_IMAGE_PATH": "default.jpg", - "CACHE_DIR": USER_CACHE_DIR + "/", + "CACHE_DIR": CheckDirectoryFmt(USER_CACHE_DIR), } ) @@ -73,3 +73,11 @@ func getMusicDirectory() string { } return "" } + +func CheckDirectoryFmt(path string) string { + if strings.HasSuffix(path, "/") { + return path + } else { + return path + "/" + } +} From 75d5d13fbed2f124e2a6ba98ce1ac71941e59958 Mon Sep 17 00:00:00 2001 From: aditya-K2 Date: Mon, 13 Dec 2021 00:15:16 +0530 Subject: [PATCH 08/13] Checking for the / at the back --- cache/cache.go | 4 +++- render.go | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cache/cache.go b/cache/cache.go index cb9228f..aed1312 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -5,6 +5,8 @@ import ( "fmt" "os" "strings" + + "github.com/aditya-K2/goMP/config" ) var ( @@ -13,7 +15,7 @@ var ( ) func SetCacheDir(path string) { - CACHE_DIR = path + CACHE_DIR = config.CheckDirectoryFmt(path) } func Exists(artist, album string) bool { diff --git a/render.go b/render.go index d85b7ee..f31cefe 100644 --- a/render.go +++ b/render.go @@ -2,6 +2,7 @@ package main import ( "github.com/aditya-K2/goMP/cache" + "github.com/aditya-K2/goMP/config" "github.com/spf13/viper" "gitlab.com/diamondburned/ueberzug-go" ) @@ -79,7 +80,7 @@ func getImagePath(path string) string { extractedImage = cache.GenerateName(a[0]["artist"], a[0]["album"]) } else { imagePath := cache.GenerateName(a[0]["artist"], a[0]["album"]) - absPath := viper.GetString("MUSIC_DIRECTORY") + path + absPath := config.CheckDirectoryFmt(viper.GetString("MUSIC_DIRECTORY")) + path extractedImage = extractImageFromFile(absPath, imagePath) if extractedImage == viper.GetString("DEFAULT_IMAGE_PATH") && viper.GetString("GET_COVER_ART_FROM_LAST_FM") == "TRUE" { downloadedImage, err := getImageFromLastFM(a[0]["artist"], a[0]["album"], imagePath) From bc3e5b6741887c466b236d299944230a65ac4b64 Mon Sep 17 00:00:00 2001 From: aditya-K2 Date: Mon, 13 Dec 2021 00:15:53 +0530 Subject: [PATCH 09/13] Updated Documentation --- docs/settingup.md | 4 ++-- sample_config.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/settingup.md b/docs/settingup.md index 486825c..ad7034f 100644 --- a/docs/settingup.md +++ b/docs/settingup.md @@ -46,7 +46,7 @@ the `music_directory` option ( It is to be noted that goMP assumes that your mpd `$HOME/.config/mpd/mpd.conf` ```yml -MUSIC_DIRECTORY : "~/Music" # Adding the / at the end is neccessary +MUSIC_DIRECTORY : "~/Music" ``` The reason why you need to setup `MUSIC_DIRECTORY` manually because the paths to the songs received from mpd are relative the `MUSIC_DIRECTORY`. @@ -119,7 +119,7 @@ Please change the configuration according to your needs. By Default Images are cached to avoid re-extracting images and making redundant API Calls. The Extracted Images are copied to the `CACHE_DIR` and a reference is added to the `CACHE_FILE` ```yml -CACHE_DIR : "/path/to/the/cache/Directory/" # Adding the / at the end is neccessary +CACHE_DIR : "/path/to/the/cache/Directory/" CACHE_FILE : "/path/to/the/cache/file" # Cache file stores the path to all the images ( think of it like a database. ) ``` diff --git a/sample_config.yml b/sample_config.yml index a2d0677..98858ab 100644 --- a/sample_config.yml +++ b/sample_config.yml @@ -76,7 +76,7 @@ togglePlayBack : [ "p", "SPACE", "]" ] # using the quotes is neccessary. # 3. Fallback to the default image. # # -CACHE_DIR : "/path/to/the/cache/Directory" # for e.g "~/.config/goMP/cache/" Please Note that adding a / at the end is neccessary. +CACHE_DIR : "/path/to/the/cache/Directory" # for e.g "~/.config/goMP/cache/" # You will have to manually create this directory. CACHE_FILE : "/path/to/the/cache/file" # Cache file stores the path to all the images ( think of it like a database. ) # Soon will be deprecated. From 9b60cbc98e2e8f970ecfa1de91b2739058d0bb1f Mon Sep 17 00:00:00 2001 From: aditya-K2 Date: Mon, 13 Dec 2021 01:35:40 +0530 Subject: [PATCH 10/13] Moving utils.go to utils package --- cache/cache.go | 4 +-- client.go | 41 ++++++++---------------------- config/config.go | 13 +++------- imageUtils.go | 10 +++++--- main.go | 6 +++-- notification.go | 4 ++- progressBar.go | 12 +++++---- render.go | 6 ++--- utils.go => utils/utils.go | 52 +++++++++++++++++++++++++++++--------- 9 files changed, 79 insertions(+), 69 deletions(-) rename utils.go => utils/utils.go (60%) diff --git a/cache/cache.go b/cache/cache.go index aed1312..4f10ee2 100644 --- a/cache/cache.go +++ b/cache/cache.go @@ -6,7 +6,7 @@ import ( "os" "strings" - "github.com/aditya-K2/goMP/config" + "github.com/aditya-K2/goMP/utils" ) var ( @@ -15,7 +15,7 @@ var ( ) func SetCacheDir(path string) { - CACHE_DIR = config.CheckDirectoryFmt(path) + CACHE_DIR = utils.CheckDirectoryFmt(path) } func Exists(artist, album string) bool { diff --git a/client.go b/client.go index 48ca4b9..00243cd 100644 --- a/client.go +++ b/client.go @@ -5,6 +5,7 @@ import ( "fmt" "strings" + "github.com/aditya-K2/goMP/utils" "github.com/aditya-K2/tview" ) @@ -12,16 +13,6 @@ var ( WHITE_AND_BOLD string = "[#ffffff::b]" ) -func getFormattedString(s string, width int) string { - if len(s) < width { - s += strings.Repeat(" ", (width - len(s))) - } else { - s = s[:(width - 2)] - s += " " - } - return s -} - func togglePlayBack() error { status, err := CONN.Status() if status["state"] == "play" && err == nil { @@ -39,10 +30,10 @@ func UpdatePlaylist(inputTable *tview.Table) { for i, j := range _playlistAttr { _, _, w, _ := inputTable.GetInnerRect() if j["Title"] == "" || j["Artist"] == "" || j["Album"] == "" { - inputTable.SetCell(i, 0, tview.NewTableCell(getFormattedString(j["file"], w/3))) + inputTable.SetCell(i, 0, tview.NewTableCell(utils.GetFormattedString(j["file"], w/3))) } else { - inputTable.SetCell(i, 0, tview.NewTableCell(getFormattedString("[green]"+j["Title"], w/3))) - inputTable.SetCell(i, 1, tview.NewTableCell(getFormattedString("[magenta]"+j["Artist"], w/3))) + inputTable.SetCell(i, 0, tview.NewTableCell(utils.GetFormattedString("[green]"+j["Title"], w/3))) + inputTable.SetCell(i, 1, tview.NewTableCell(utils.GetFormattedString("[magenta]"+j["Artist"], w/3))) inputTable.SetCell(i, 2, tview.NewTableCell("[yellow]"+j["Album"])) } } @@ -106,14 +97,14 @@ func UpdateSearchView(inputTable *tview.Table, c []interface{}) { switch content.(type) { case [3]string: { - inputTable.SetCell(i, 0, tview.NewTableCell(getFormattedString("[green]"+content.([3]string)[0], width/3))) - inputTable.SetCell(i, 1, tview.NewTableCell(getFormattedString("[magenta]"+content.([3]string)[1], width/3))) - inputTable.SetCell(i, 2, tview.NewTableCell(getFormattedString("[yellow]"+content.([3]string)[2], width/3))) + inputTable.SetCell(i, 0, tview.NewTableCell(utils.GetFormattedString("[green]"+content.([3]string)[0], width/3))) + inputTable.SetCell(i, 1, tview.NewTableCell(utils.GetFormattedString("[magenta]"+content.([3]string)[1], width/3))) + inputTable.SetCell(i, 2, tview.NewTableCell(utils.GetFormattedString("[yellow]"+content.([3]string)[2], width/3))) } case [2]string: { - inputTable.SetCell(i, 0, tview.NewTableCell(getFormattedString("[green]"+content.([2]string)[0], width/3))) - inputTable.SetCell(i, 1, tview.NewTableCell(getFormattedString("[magenta]"+content.([2]string)[1], width/3))) + inputTable.SetCell(i, 0, tview.NewTableCell(utils.GetFormattedString("[green]"+content.([2]string)[0], width/3))) + inputTable.SetCell(i, 1, tview.NewTableCell(utils.GetFormattedString("[magenta]"+content.([2]string)[1], width/3))) } case string: { @@ -128,16 +119,6 @@ func UpdateSearchView(inputTable *tview.Table, c []interface{}) { } } -func join(stringSlice []string) string { - var _s string = stringSlice[0] - for i := 1; i < len(stringSlice); i++ { - if _s != "" { - _s += ("/" + stringSlice[i]) - } - } - return _s -} - func Update(f []FileNode, inputTable *tview.Table) { inputTable.Clear() for i, j := range f { @@ -146,11 +127,11 @@ func Update(f []FileNode, inputTable *tview.Table) { if err == nil && _songAttributes[0]["Title"] != "" { _, _, w, _ := inputTable.GetInnerRect() inputTable.SetCell(i, 0, - tview.NewTableCell("[green]"+getFormattedString(_songAttributes[0]["Title"], w/3)). + tview.NewTableCell("[green]"+utils.GetFormattedString(_songAttributes[0]["Title"], w/3)). SetAlign(tview.AlignLeft)) inputTable.SetCell(i, 1, - tview.NewTableCell("[magenta]"+getFormattedString(_songAttributes[0]["Artist"], w/3)). + tview.NewTableCell("[magenta]"+utils.GetFormattedString(_songAttributes[0]["Artist"], w/3)). SetAlign(tview.AlignLeft)) inputTable.SetCell(i, 2, diff --git a/config/config.go b/config/config.go index 9a57ff4..c5dc1c0 100644 --- a/config/config.go +++ b/config/config.go @@ -6,6 +6,7 @@ import ( "os" "strings" + "github.com/aditya-K2/goMP/utils" "github.com/spf13/viper" ) @@ -17,10 +18,10 @@ var ( "ADDITIONAL_PADDING_Y": 16, "IMAGE_WIDTH_EXTRA_X": -1.5, "IMAGE_WIDTH_EXTRA_Y": -3.75, - "MUSIC_DIRECTORY": CheckDirectoryFmt(getMusicDirectory()), + "MUSIC_DIRECTORY": utils.CheckDirectoryFmt(getMusicDirectory()), "PORT": "6600", "DEFAULT_IMAGE_PATH": "default.jpg", - "CACHE_DIR": CheckDirectoryFmt(USER_CACHE_DIR), + "CACHE_DIR": utils.CheckDirectoryFmt(USER_CACHE_DIR), } ) @@ -73,11 +74,3 @@ func getMusicDirectory() string { } return "" } - -func CheckDirectoryFmt(path string) string { - if strings.HasSuffix(path, "/") { - return path - } else { - return path + "/" - } -} diff --git a/imageUtils.go b/imageUtils.go index 9213897..920bd9a 100644 --- a/imageUtils.go +++ b/imageUtils.go @@ -5,6 +5,8 @@ import ( "os" "strings" + "github.com/aditya-K2/goMP/utils" + "github.com/bogem/id3v2" "github.com/mewkiz/flac" "github.com/mewkiz/flac/meta" @@ -69,17 +71,17 @@ func extractImageFromFile(uri string, imagePath string) string { if strings.HasSuffix(uri, ".mp3") { imagePath := GetMp3Image(uri, imagePath) if imagePath == "" { - Copy(viper.GetString("DEFAULT_IMAGE_PATH"), _i) + utils.Copy(viper.GetString("DEFAULT_IMAGE_PATH"), _i) return viper.GetString("DEFAULT_IMAGE_PATH") } } else if strings.HasSuffix(uri, ".flac") { imagePath := GetFlacImage(uri, imagePath) if imagePath == "" { - Copy(viper.GetString("DEFAULT_IMAGE_PATH"), _i) + utils.Copy(viper.GetString("DEFAULT_IMAGE_PATH"), _i) return viper.GetString("DEFAULT_IMAGE_PATH") } } else { - Copy(viper.GetString("DEFAULT_IMAGE_PATH"), _i) + utils.Copy(viper.GetString("DEFAULT_IMAGE_PATH"), _i) return viper.GetString("DEFAULT_IMAGE_PATH") } return imagePath @@ -95,7 +97,7 @@ func getImg(uri string) (image.Image, error) { if err != nil { return nil, err } - fw, fh := getFontWidth() + fw, fh := utils.GetFontWidth() img = resize.Resize( uint(float32(IMG_W)*(fw+float32(viper.GetFloat64("IMAGE_WIDTH_EXTRA_X")))), uint(float32(IMG_H)*(fh+float32(viper.GetFloat64("IMAGE_WIDTH_EXTRA_Y")))), img, diff --git a/main.go b/main.go index a8069ff..dcd8aa4 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,8 @@ import ( "strconv" "time" + "github.com/aditya-K2/goMP/utils" + "github.com/aditya-K2/fuzzy" "github.com/aditya-K2/goMP/cache" "github.com/aditya-K2/goMP/config" @@ -55,7 +57,7 @@ func main() { Repeat, _ = strconv.ParseBool(_v["repeat"]) ARTIST_TREE, err = GenerateArtistTree() - ARTIST_TREE_CONTENT := ConvertToArray() + ARTIST_TREE_CONTENT := utils.ConvertToArray(ARTIST_TREE) NOTIFICATION_SERVER = NewNotificationServer() NOTIFICATION_SERVER.Start() @@ -206,7 +208,7 @@ func main() { if i == 10 { break } - suggestions = append(suggestions, getFormattedString(match.Str, w-2)) + suggestions = append(suggestions, utils.GetFormattedString(match.Str, w-2)) } return suggestions } else { diff --git a/notification.go b/notification.go index 15fa3e1..3013627 100644 --- a/notification.go +++ b/notification.go @@ -3,6 +3,8 @@ package main import ( "time" + "github.com/aditya-K2/goMP/utils" + "github.com/aditya-K2/tview" "github.com/gdamore/tcell/v2" ) @@ -23,7 +25,7 @@ func NewNotification(s string) *Notification { /* Draw Function for the Notification Primitive */ func (self *Notification) Draw(screen tcell.Screen) { - termDetails := getWidth() + termDetails := utils.GetWidth() var ( COL int = int(termDetails.Col) diff --git a/progressBar.go b/progressBar.go index 69f5575..46b0e0e 100644 --- a/progressBar.go +++ b/progressBar.go @@ -4,6 +4,8 @@ import ( "fmt" "strconv" + "github.com/aditya-K2/goMP/utils" + "github.com/aditya-K2/tview" "github.com/gdamore/tcell/v2" ) @@ -69,14 +71,14 @@ func (s *progressBar) updateProgress() { if du != 0 { percentage := el / du * 100 if err == nil && err1 == nil { - s.t.SetTitle(fmt.Sprintf("[[::i] %s [-:-:-]Shuffle: %s Repeat: %s Volume: %s ]", formatString(_status["state"]), formatString(_status["random"]), formatString(_status["repeat"]), _status["volume"])).SetTitleAlign(tview.AlignRight) - s.t.GetCell(2, 0).Text = getText(float64(_width), percentage, strTime(el)+"/"+strTime(du)+"("+strconv.FormatFloat(percentage, 'f', 2, 32)+"%"+")") + s.t.SetTitle(fmt.Sprintf("[[::i] %s [-:-:-]Shuffle: %s Repeat: %s Volume: %s ]", utils.FormatString(_status["state"]), utils.FormatString(_status["random"]), utils.FormatString(_status["repeat"]), _status["volume"])).SetTitleAlign(tview.AlignRight) + s.t.GetCell(2, 0).Text = utils.GetText(float64(_width), percentage, utils.StrTime(el)+"/"+utils.StrTime(du)+"("+strconv.FormatFloat(percentage, 'f', 2, 32)+"%"+")") } else { - s.t.SetTitle(fmt.Sprintf("[[::i] %s [-:-:-]Shuffle: %s Repeat: %s]", formatString(_status["state"]), formatString(_status["random"]), formatString(_status["repeat"]))).SetTitleAlign(tview.AlignRight) + s.t.SetTitle(fmt.Sprintf("[[::i] %s [-:-:-]Shuffle: %s Repeat: %s]", utils.FormatString(_status["state"]), utils.FormatString(_status["random"]), utils.FormatString(_status["repeat"]))).SetTitleAlign(tview.AlignRight) s.t.GetCell(2, 0).Text = "" } } else { - s.t.SetTitle(fmt.Sprintf("[[::i] %s [-:-:-]Shuffle: %s Repeat: %s Volume: %s ]", formatString(_status["state"]), formatString(_status["random"]), formatString(_status["repeat"]), _status["volume"])).SetTitleAlign(tview.AlignRight) - s.t.GetCell(2, 0).Text = getText(float64(_width), 0, " ---:---") + s.t.SetTitle(fmt.Sprintf("[[::i] %s [-:-:-]Shuffle: %s Repeat: %s Volume: %s ]", utils.FormatString(_status["state"]), utils.FormatString(_status["random"]), utils.FormatString(_status["repeat"]), _status["volume"])).SetTitleAlign(tview.AlignRight) + s.t.GetCell(2, 0).Text = utils.GetText(float64(_width), 0, " ---:---") } } diff --git a/render.go b/render.go index f31cefe..fbbc222 100644 --- a/render.go +++ b/render.go @@ -2,7 +2,7 @@ package main import ( "github.com/aditya-K2/goMP/cache" - "github.com/aditya-K2/goMP/config" + "github.com/aditya-K2/goMP/utils" "github.com/spf13/viper" "gitlab.com/diamondburned/ueberzug-go" ) @@ -42,7 +42,7 @@ func (self *Renderer) Send(path string) { */ func openImage(path string, c chan string) { - fw, fh := getFontWidth() + fw, fh := utils.GetFontWidth() var im *ueberzug.Image if path != "stop" { extractedImage := getImagePath(path) @@ -80,7 +80,7 @@ func getImagePath(path string) string { extractedImage = cache.GenerateName(a[0]["artist"], a[0]["album"]) } else { imagePath := cache.GenerateName(a[0]["artist"], a[0]["album"]) - absPath := config.CheckDirectoryFmt(viper.GetString("MUSIC_DIRECTORY")) + path + absPath := utils.CheckDirectoryFmt(viper.GetString("MUSIC_DIRECTORY")) + path extractedImage = extractImageFromFile(absPath, imagePath) if extractedImage == viper.GetString("DEFAULT_IMAGE_PATH") && viper.GetString("GET_COVER_ART_FROM_LAST_FM") == "TRUE" { downloadedImage, err := getImageFromLastFM(a[0]["artist"], a[0]["album"], imagePath) diff --git a/utils.go b/utils/utils.go similarity index 60% rename from utils.go rename to utils/utils.go index 1ceb0de..ee88706 100644 --- a/utils.go +++ b/utils/utils.go @@ -1,4 +1,4 @@ -package main +package utils import ( "io/ioutil" @@ -15,7 +15,7 @@ type winsize struct { Ypixel uint16 } -func getWidth() *winsize { +func GetWidth() *winsize { ws := &winsize{} retCode, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(syscall.Stdin), @@ -28,14 +28,14 @@ func getWidth() *winsize { return ws } -func getFontWidth() (float32, float32) { - g := getWidth() +func GetFontWidth() (float32, float32) { + g := GetWidth() fw := (float32(g.Xpixel) / float32(g.Col)) fh := (float32(g.Ypixel) / float32(g.Row)) return fw, fh } -func strTime(e float64) string { +func StrTime(e float64) string { a := int(e) var min, seconds string if a/60 < 10 { @@ -53,24 +53,24 @@ func strTime(e float64) string { return min + ":" + seconds } -func insertAt(inputString, stringTobeInserted string, index int) string { +func InsertAt(inputString, stringTobeInserted string, index int) string { s := inputString[:index] + stringTobeInserted + inputString[index:] return s } -func getText(width, percentage float64, eta string) string { +func GetText(width, percentage float64, eta string) string { q := "[#000000:#ffffff:b]" var a string a += strings.Repeat(" ", int(width)-len(eta)) - a = insertAt(a, eta, int(width/2)-10) - a = insertAt(a, "[-:-:-]", int(width*percentage/100)) + a = InsertAt(a, eta, int(width/2)-10) + a = InsertAt(a, "[-:-:-]", int(width*percentage/100)) q += a return q } -func ConvertToArray() []string { +func ConvertToArray(ArtistTree map[string]map[string]map[string]string) []string { var p []string - for k2, v := range ARTIST_TREE { + for k2, v := range ArtistTree { p = append(p, k2) for k1, v1 := range v { p = append(p, k1) @@ -82,7 +82,7 @@ func ConvertToArray() []string { return p } -func formatString(a interface{}) string { +func FormatString(a interface{}) string { if a == "play" { return "Playing" } else if a == "1" { @@ -108,3 +108,31 @@ func Copy(sourceImage, destinationImage string) error { return nil } } + +func Join(stringSlice []string) string { + var _s string = stringSlice[0] + for i := 1; i < len(stringSlice); i++ { + if _s != "" { + _s += ("/" + stringSlice[i]) + } + } + return _s +} + +func GetFormattedString(s string, width int) string { + if len(s) < width { + s += strings.Repeat(" ", (width - len(s))) + } else { + s = s[:(width - 2)] + s += " " + } + return s +} + +func CheckDirectoryFmt(path string) string { + if strings.HasSuffix(path, "/") { + return path + } else { + return path + "/" + } +} From da47c9b10ca2746dd87d009b53aa2a721280cfa1 Mon Sep 17 00:00:00 2001 From: aditya-K2 Date: Mon, 13 Dec 2021 01:43:20 +0530 Subject: [PATCH 11/13] Moving imageUtils.go to utils package --- render.go | 27 +++++++++++++++++++++-- imageUtils.go => utils/imageUtils.go | 33 +++++----------------------- 2 files changed, 30 insertions(+), 30 deletions(-) rename imageUtils.go => utils/imageUtils.go (67%) diff --git a/render.go b/render.go index fbbc222..6008b05 100644 --- a/render.go +++ b/render.go @@ -1,8 +1,12 @@ package main import ( + "image" + "os" + "github.com/aditya-K2/goMP/cache" "github.com/aditya-K2/goMP/utils" + "github.com/nfnt/resize" "github.com/spf13/viper" "gitlab.com/diamondburned/ueberzug-go" ) @@ -46,7 +50,7 @@ func openImage(path string, c chan string) { var im *ueberzug.Image if path != "stop" { extractedImage := getImagePath(path) - img2, _ := getImg(extractedImage) + img2, _ := GetImg(extractedImage) im, _ = ueberzug.NewImage(img2, int(float32(IMG_X)*fw)+viper.GetInt("ADDITIONAL_PADDING_X"), int(float32(IMG_Y)*fh)+viper.GetInt("ADDITIONAL_PADDING_Y")) } d := <-c @@ -81,7 +85,7 @@ func getImagePath(path string) string { } else { imagePath := cache.GenerateName(a[0]["artist"], a[0]["album"]) absPath := utils.CheckDirectoryFmt(viper.GetString("MUSIC_DIRECTORY")) + path - extractedImage = extractImageFromFile(absPath, imagePath) + extractedImage = utils.ExtractImageFromFile(absPath, imagePath) if extractedImage == viper.GetString("DEFAULT_IMAGE_PATH") && viper.GetString("GET_COVER_ART_FROM_LAST_FM") == "TRUE" { downloadedImage, err := getImageFromLastFM(a[0]["artist"], a[0]["album"], imagePath) if err == nil { @@ -97,3 +101,22 @@ func getImagePath(path string) string { } return extractedImage } + +func GetImg(uri string) (image.Image, error) { + f, err := os.Open(uri) + if err != nil { + return nil, err + } + defer f.Close() + img, _, err := image.Decode(f) + if err != nil { + return nil, err + } + fw, fh := utils.GetFontWidth() + img = resize.Resize( + uint(float32(IMG_W)*(fw+float32(viper.GetFloat64("IMAGE_WIDTH_EXTRA_X")))), uint(float32(IMG_H)*(fh+float32(viper.GetFloat64("IMAGE_WIDTH_EXTRA_Y")))), + img, + resize.Bilinear, + ) + return img, nil +} diff --git a/imageUtils.go b/utils/imageUtils.go similarity index 67% rename from imageUtils.go rename to utils/imageUtils.go index 920bd9a..ce3dfee 100644 --- a/imageUtils.go +++ b/utils/imageUtils.go @@ -1,16 +1,12 @@ -package main +package utils import ( - "image" "os" "strings" - "github.com/aditya-K2/goMP/utils" - "github.com/bogem/id3v2" "github.com/mewkiz/flac" "github.com/mewkiz/flac/meta" - "github.com/nfnt/resize" "github.com/spf13/viper" ) @@ -66,42 +62,23 @@ func GetFlacImage(songPath, imagePath string) string { return "" } -func extractImageFromFile(uri string, imagePath string) string { +func ExtractImageFromFile(uri string, imagePath string) string { _i := imagePath if strings.HasSuffix(uri, ".mp3") { imagePath := GetMp3Image(uri, imagePath) if imagePath == "" { - utils.Copy(viper.GetString("DEFAULT_IMAGE_PATH"), _i) + Copy(viper.GetString("DEFAULT_IMAGE_PATH"), _i) return viper.GetString("DEFAULT_IMAGE_PATH") } } else if strings.HasSuffix(uri, ".flac") { imagePath := GetFlacImage(uri, imagePath) if imagePath == "" { - utils.Copy(viper.GetString("DEFAULT_IMAGE_PATH"), _i) + Copy(viper.GetString("DEFAULT_IMAGE_PATH"), _i) return viper.GetString("DEFAULT_IMAGE_PATH") } } else { - utils.Copy(viper.GetString("DEFAULT_IMAGE_PATH"), _i) + Copy(viper.GetString("DEFAULT_IMAGE_PATH"), _i) return viper.GetString("DEFAULT_IMAGE_PATH") } return imagePath } - -func getImg(uri string) (image.Image, error) { - f, err := os.Open(uri) - if err != nil { - return nil, err - } - defer f.Close() - img, _, err := image.Decode(f) - if err != nil { - return nil, err - } - fw, fh := utils.GetFontWidth() - img = resize.Resize( - uint(float32(IMG_W)*(fw+float32(viper.GetFloat64("IMAGE_WIDTH_EXTRA_X")))), uint(float32(IMG_H)*(fh+float32(viper.GetFloat64("IMAGE_WIDTH_EXTRA_Y")))), - img, - resize.Bilinear, - ) - return img, nil -} From b59f0ada12412b446183f3e6d59d2b5ddece9b96 Mon Sep 17 00:00:00 2001 From: aditya-K2 Date: Mon, 13 Dec 2021 01:46:49 +0530 Subject: [PATCH 12/13] Rename App.go -> app.go --- App.go => app.go | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename App.go => app.go (100%) diff --git a/App.go b/app.go similarity index 100% rename from App.go rename to app.go From 65182b2b429abc2fdd89a27043b32c91a4ee0ee1 Mon Sep 17 00:00:00 2001 From: aditya-K2 Date: Tue, 14 Dec 2021 14:30:31 +0530 Subject: [PATCH 13/13] minor changes --- docs/settingup.md | 203 ---------------------------------------------- 1 file changed, 203 deletions(-) delete mode 100644 docs/settingup.md diff --git a/docs/settingup.md b/docs/settingup.md deleted file mode 100644 index ad7034f..0000000 --- a/docs/settingup.md +++ /dev/null @@ -1,203 +0,0 @@ -* [Prerequisites](#prerequisites) -* [Installing / Building](#installing--building) -* [Configuration](#configuration) - * [MPD Port](#mpd-port) - * [Music Directory](#music-directory) - * [Default Image Path](#default-image-path) - * [Additional Padding and Extra Image Width](#additional-padding-and-extra-image-width) - * [Image Rendering](#image-rendering) - * [Cache Directory](#cache-directory) - * [Key Mappings](#key-mappings) - * [Getting Album Art from LastFm API](#getting-album-art-from-lastfm-api) - -# Prerequisites - -- Music Player Daemon must be setup and Running -- Go Should Be Installed ( For Building ) -- After Reading this it is highly recommended to read the [sample_config](https://github.com/aditya-K2/goMP/blob/master/sample_config.yml) - -# Installing / Building - -```bash -git clone https://github.com/aditya-K2/goMP && -cd goMP && -go build -``` - -# Configuration - -Configuration of goMP is done through a `config.yml` file in `$HOME/config/goMP/` - -It is essential to have some config options defined in order to have a smooth experience. - -## MPD Port - -This is the port where your Music Player Daemon Is Running - -```yml -MPD_PORT : "6600" -``` - -## Music Directory - -The Most Essential config option is `MUSIC_DIRECTORY` It is the path to your Music Folder that you have provided to mpd -in the `mpd.conf` file. If you do not provide the path to the `MUSIC_DIRECTORY` then goMP parses the mpd.conf file for -the `music_directory` option ( It is to be noted that goMP assumes that your mpd.conf file is at -`$HOME/.config/mpd/mpd.conf` - -```yml -MUSIC_DIRECTORY : "~/Music" -``` - -The reason why you need to setup `MUSIC_DIRECTORY` manually because the paths to the songs received from mpd are relative the `MUSIC_DIRECTORY`. - -## Default Image Path - -This is the Fallback Image that will be rendered if goMP doesn't find the embedded cover art or LastFM Cover Art. - -```yml -DEFAULT_IMAGE_PATH : "/path/to/default/image" -``` - -## Additional Padding and Extra Image Width - -### Image Rendering - -The Default Position of the Image without any configuration assumes that you have no font or terminal padding or margin so Image will -be rendered at different places in different terminals, Also the TUIs calculates positions with the according to rows and columns -and the image is rendered at pixel positions so the exact position can't be defined [ the app tries its best by calculating -the font width and then predicting the position but it is best that you define some extra padding and your own image width ratio -in config.yml. Please Read more about it in the [sample_config](https://github.com/aditya-K2/goMP/blob/master/sample_config.yml) - -for e.g - -```yml -# Default Values. Might be different than sample_config.yml -ADDITIONAL_PADDING_X : 11 -ADDITIONAL_PADDING_Y : 18 - -IMAGE_WIDTH_EXTRA_X : -0.7 -IMAGE_WIDTH_EXTRA_Y : -2.6 -``` -![Cover Art Position](./assets/default.png) - -Let's say upon opening goMP for the first time and your image is rendered this way. - -Here the `Y` Position is too low hence we have to decrease the `ADDITIONAL_PADDING_Y` so that image will be rendered -in a better position so we decrement the `ADDITIONAL_PADDING_Y` by `9` - -Now the configuration becomes -```yml -ADDITIONAL_PADDING_Y : 9 -``` - -and the image appears like this: - -![Padding](./assets/padding.png) - -One might be happy the way things turn out but for the perfectionist like me this is not enough. -You can notice that the Height of the image is a little bit more than the box height and hence the image is flowing outside the box. Now it's time to change the `WIDTH_Y`. - -Width can be changed by defining the `IMAGE_WIDTH_EXTRA_Y` and `IMAGE_WIDTH_EXTRA_X` it act's a little differently think of it like a chunk which is either added or subtracted from the image's original width. We can look at the configuration and realize that the chunk `IMAGE_WIDTH_EXTRA_Y` when subtracted from the original `IMAGE_WIDTH` doesn't get us the proper result and is a little to low. We need to subtract a more bigger chunk, Hence we will increase the magnitude of `IMAGE_WIDTH_EXTRA_Y` or decrease `IMAGE_WIDTH_EXTRA_Y` - -Now the Configuration becomes: -```yml -IMAGE_WIDTH_EXTRA_Y : - 3.2 -``` -and the image appears like this: - -![Width](./assets/width.png) - -Which looks perfect. 🎉 - -Read More about Additional Padding and Image Width in the [sample_config](https://github.com/aditya-K2/goMP/blob/master/sample_config.yml) - -Please change the configuration according to your needs. - -## Cache Directory - -By Default Images are cached to avoid re-extracting images and making redundant API Calls. The Extracted Images are copied to the `CACHE_DIR` and a reference is added to the `CACHE_FILE` - -```yml -CACHE_DIR : "/path/to/the/cache/Directory/" -CACHE_FILE : "/path/to/the/cache/file" # Cache file stores the path to all the images ( think of it like a database. ) -``` - -This Technique has some drawbacks and the `CACHE_FILE` mechanism will soon be deprecated but for now add this lines to your `config.yml`. Don't Worry after changing the mechanism you won't have to make a single change to `config.yml` file the changes would be under the hood ( you won't even notice ). - -Read More about Caching in the [sample_config](https://github.com/aditya-K2/goMP/blob/master/sample_config.yml) - -## Key Mappings - -Following Keys can be used for Mappings - -| Keys | Using them in Config | -|-----------------|-----------------------| -| a-z | a-z | -| A-Z | A-z | -| {,},(,),[,],<,> | {,},(,),[,],<,> | -| Enter(Return) | ENTER/RETURN | -| Tab | TAB | -| Space | SPACE | - -See config/kMap.go for more information - -For mapping a key to some function use the following format: - - -```yml -Function: [ firstMapping, secondMapping, thirdMapping] -``` -for.eg - - -```yml -togglePlayBack : [ "p", "TAB", "[" ] # using the quotes is neccessary. -``` - -Following functions are provided : - -| Functions | -|------------------------------------| -| showChildrenContent | -| togglePlayBack | -| showParentContent | -| nextSong | -| clearPlaylist | -| previousSong | -| addToPlaylist | -| toggleRandom | -| toggleRepeat | -| decreaseVolume | -| increaseVolume | -| navigateToFiles | -| navigateToPlaylist | -| navigateToMostPlayed | -| navigateToSearch | -| quit | -| stop | -| updateDB | -| deleteSongFromPlaylist | -| FocusSearch | - -## Getting Album Art from [LastFm API](https://www.last.fm/api) - -1. Generate API Key [here](https://www.last.fm/login?next=%2Fapi%2Faccount%2Fcreate%3F_pjax%3D%2523content) - - ![Screenshot from 2021-11-13 21-54-54](https://user-images.githubusercontent.com/51816057/141651276-f76a5c7f-65fe-4a1a-b130-18cdf67dd471.png) - -2. Add the api key and api secret to config.yml - -```yml -GET_COVER_ART_FROM_LAST_FM : "TRUE" # Turn On Getting Album art from lastfm api -LASTFM_API_KEY: "YOUR API KEY HERE" -LASTFM_API_SECRET: "YOUR API SECRET HERE" -``` -3. Auto correct - -![Screenshot from 2021-11-13 21-59-46](https://user-images.githubusercontent.com/51816057/141651414-1586577a-cab2-48e2-a24b-1053f8634fbe.png) -: - -```yml -LASTFM_AUTO_CORRECT: 1 # 0 means it is turned off -```