mirror of
https://github.com/issadarkthing/gomu.git
synced 2025-05-08 19:29:50 +08:00
implement ytdl
This commit is contained in:
parent
ca92b98583
commit
be28266224
17
playlist.go
17
playlist.go
@ -78,6 +78,21 @@ func InitPlaylist() *Playlist {
|
||||
audioFile := currNode.GetReference().(*AudioFile)
|
||||
|
||||
switch e.Rune() {
|
||||
case 'Y':
|
||||
|
||||
if pages.HasPage("download-popup") {
|
||||
pages.RemovePage("download-popup")
|
||||
} else {
|
||||
|
||||
if audioFile.IsAudioFile {
|
||||
downloadMusic(currNode)
|
||||
} else {
|
||||
downloadMusic(audioFile.Parent)
|
||||
}
|
||||
|
||||
downloadMusic(playlist.GetCurrentNode())
|
||||
}
|
||||
|
||||
case 'l':
|
||||
|
||||
playlist.addToQueue(audioFile)
|
||||
@ -228,7 +243,7 @@ func (playlist *Playlist) addAllToQueue(root *tview.TreeNode) {
|
||||
for _, v := range childrens {
|
||||
currNode := v.GetReference().(*AudioFile)
|
||||
|
||||
playlist.addToQueue(currNode)
|
||||
go playlist.addToQueue(currNode)
|
||||
}
|
||||
|
||||
}
|
||||
|
44
popup.go
44
popup.go
@ -55,7 +55,6 @@ func topRight(p tview.Primitive, width, height int) tview.Primitive {
|
||||
|
||||
func timeoutPopup(title string, desc string, timeout time.Duration) {
|
||||
|
||||
|
||||
textView := tview.NewTextView().
|
||||
SetText(fmt.Sprintf("%s", desc)).
|
||||
SetTextColor(accentColor)
|
||||
@ -66,6 +65,7 @@ func timeoutPopup(title string, desc string, timeout time.Duration) {
|
||||
box.SetTitle(title).SetBorder(true).SetBackgroundColor(popupBg)
|
||||
|
||||
popupId := fmt.Sprintf("%s %d", "timeout-popup", popupCounter)
|
||||
popupCounter++
|
||||
|
||||
pages.AddPage(popupId, topRight(box, 70, 7), true, true)
|
||||
app.SetFocus(prevPanel.(tview.Primitive))
|
||||
@ -77,10 +77,9 @@ func timeoutPopup(title string, desc string, timeout time.Duration) {
|
||||
}()
|
||||
}
|
||||
|
||||
|
||||
func volumePopup(volume float64) {
|
||||
|
||||
vol := int(volume * 10) + 50
|
||||
vol := int(volume*10) + 50
|
||||
|
||||
progress := fmt.Sprintf("\n%d |%s%s| %s",
|
||||
vol,
|
||||
@ -89,7 +88,7 @@ func volumePopup(volume float64) {
|
||||
"50",
|
||||
)
|
||||
|
||||
timeoutPopup(" Volume ", progress, time.Second * 5)
|
||||
timeoutPopup(" Volume ", progress, time.Second*5)
|
||||
|
||||
}
|
||||
|
||||
@ -109,19 +108,19 @@ func helpPopup() {
|
||||
"+ volume up",
|
||||
"- volume down",
|
||||
"? toggle help",
|
||||
"Y download audio",
|
||||
}
|
||||
|
||||
list := tview.NewList().ShowSecondaryText(false)
|
||||
list.SetBackgroundColor(popupBg).SetTitle(" Help ").
|
||||
SetBorder(true)
|
||||
SetBorder(true)
|
||||
list.SetSelectedBackgroundColor(popupBg).
|
||||
SetSelectedTextColor(accentColor)
|
||||
SetSelectedTextColor(accentColor)
|
||||
|
||||
for _, v := range helpText {
|
||||
list.AddItem(v, "", 0, nil)
|
||||
}
|
||||
|
||||
|
||||
prev := func() {
|
||||
currIndex := list.GetCurrentItem()
|
||||
list.SetCurrentItem(currIndex - 1)
|
||||
@ -143,8 +142,6 @@ func helpPopup() {
|
||||
next()
|
||||
case 'k':
|
||||
prev()
|
||||
case 'd':
|
||||
queue.deleteItem(queue.GetCurrentItem())
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -153,3 +150,32 @@ func helpPopup() {
|
||||
pages.AddPage("help-page", center(list, 50, 30), true, true)
|
||||
app.SetFocus(list)
|
||||
}
|
||||
|
||||
func downloadMusic(selPlaylist *tview.TreeNode) {
|
||||
|
||||
inputField := tview.NewInputField().
|
||||
SetLabel("Enter a url: ").
|
||||
SetFieldWidth(0).
|
||||
SetAcceptanceFunc(tview.InputFieldMaxLength(50))
|
||||
|
||||
inputField.SetBackgroundColor(popupBg).SetBorder(true).SetTitle(" Ytdl ")
|
||||
inputField.SetFieldBackgroundColor(accentColor).SetFieldTextColor(tcell.ColorBlack)
|
||||
|
||||
inputField.SetDoneFunc(func(key tcell.Key) {
|
||||
|
||||
switch key {
|
||||
case tcell.KeyEnter:
|
||||
url := inputField.GetText()
|
||||
Ytdl(url, selPlaylist)
|
||||
pages.RemovePage("download-popup")
|
||||
|
||||
case tcell.KeyEscape:
|
||||
pages.RemovePage("download-popup")
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
pages.AddPage("download-popup", center(inputField, 50, 4), true, true)
|
||||
app.SetFocus(inputField)
|
||||
|
||||
}
|
||||
|
104
utils.go
104
utils.go
@ -3,13 +3,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/faiface/beep/mp3"
|
||||
"github.com/rivo/tview"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func log(text string) {
|
||||
@ -112,3 +118,101 @@ func GetFileContentType(out *os.File) (string, error) {
|
||||
func GetName(fn string) string {
|
||||
return strings.TrimSuffix(path.Base(fn), path.Ext(fn))
|
||||
}
|
||||
|
||||
// download audio from youtube audio and adds the song to the selected playlist
|
||||
func Ytdl(url string, selPlaylist *tview.TreeNode) {
|
||||
|
||||
dir := viper.GetString("music_dir")
|
||||
|
||||
selAudioFile := selPlaylist.GetReference().(*AudioFile)
|
||||
selPlaylistName := selAudioFile.Name
|
||||
|
||||
timeoutPopup(" Ytdl ", "Downloading", time.Second*5)
|
||||
|
||||
// specify the output path for ytdl
|
||||
outputDir := fmt.Sprintf(
|
||||
"%s/%s/%%(artist)s - %%(track)s.%%(ext)s",
|
||||
dir,
|
||||
selPlaylistName)
|
||||
|
||||
args := []string{
|
||||
"--extract-audio",
|
||||
"--audio-format",
|
||||
"mp3",
|
||||
"--output",
|
||||
outputDir,
|
||||
url,
|
||||
}
|
||||
|
||||
cmd := exec.Command("youtube-dl", args...)
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
go func() {
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
timeoutPopup(" Error ", "An error occured when downloading", time.Second*5)
|
||||
return
|
||||
}
|
||||
|
||||
if cmd.Stderr != nil {
|
||||
timeoutPopup(" Error ", "An error occured when downloading", time.Second*5)
|
||||
return
|
||||
}
|
||||
|
||||
playlistPath := fmt.Sprintf("%s/%s", expandTilde(dir), selPlaylistName)
|
||||
|
||||
downloadedAudioPath := downloadedFilePath(
|
||||
stdout.Bytes(), playlistPath)
|
||||
|
||||
f, err := os.Open(downloadedAudioPath)
|
||||
|
||||
if err != nil {
|
||||
log(err.Error())
|
||||
}
|
||||
|
||||
defer f.Close()
|
||||
|
||||
node := tview.NewTreeNode(path.Base(f.Name()))
|
||||
|
||||
audioFile := &AudioFile{
|
||||
Name: f.Name(),
|
||||
Path: downloadedAudioPath,
|
||||
IsAudioFile: true,
|
||||
Parent: selPlaylist,
|
||||
}
|
||||
|
||||
node.SetReference(audioFile)
|
||||
selPlaylist.AddChild(node)
|
||||
app.Draw()
|
||||
|
||||
timeoutPopup(
|
||||
" Ytdl ",
|
||||
fmt.Sprintf("Finished downloading\n%s",
|
||||
path.Base(downloadedAudioPath)), time.Second*5)
|
||||
|
||||
}()
|
||||
|
||||
}
|
||||
|
||||
// this just parsing the output from the ytdl to get the audio path
|
||||
// this is used because we need to get the song name
|
||||
// example ~/path/to/song/song.mp3
|
||||
func downloadedFilePath(output []byte, dir string) string {
|
||||
|
||||
regexSearch := fmt.Sprintf(`\[ffmpeg\] Destination: %s\/.*.mp3`,
|
||||
escapeBackSlash(dir))
|
||||
|
||||
parseAudioPathOnly := regexp.MustCompile(`\/.*mp3$`)
|
||||
|
||||
re := regexp.MustCompile(regexSearch)
|
||||
|
||||
return string(parseAudioPathOnly.Find(re.Find(output)))
|
||||
|
||||
}
|
||||
|
||||
func escapeBackSlash(input string) string {
|
||||
return strings.ReplaceAll(input, "/", `\/`)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user