2020-06-22 00:05:56 +08:00
|
|
|
// Copyright (C) 2020 Raziman
|
|
|
|
|
2020-06-19 16:29:51 +08:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2020-08-18 12:26:45 +08:00
|
|
|
"errors"
|
2020-07-18 15:43:20 +08:00
|
|
|
"flag"
|
2020-07-21 20:51:10 +08:00
|
|
|
"fmt"
|
2020-08-02 16:01:18 +08:00
|
|
|
"io/ioutil"
|
2020-06-25 10:46:45 +08:00
|
|
|
"os"
|
2020-08-18 12:26:45 +08:00
|
|
|
"os/signal"
|
2020-07-01 21:21:46 +08:00
|
|
|
"strings"
|
2020-08-18 12:26:45 +08:00
|
|
|
"syscall"
|
2020-06-25 10:46:45 +08:00
|
|
|
|
2021-01-21 01:30:16 +08:00
|
|
|
"github.com/gdamore/tcell/v2"
|
2020-06-19 16:29:51 +08:00
|
|
|
"github.com/rivo/tview"
|
2021-02-12 10:58:40 +08:00
|
|
|
"github.com/ztrue/tracerr"
|
|
|
|
|
|
|
|
"github.com/mattn/anko/vm"
|
2020-06-19 16:29:51 +08:00
|
|
|
)
|
|
|
|
|
2021-02-04 12:23:32 +08:00
|
|
|
// Panel is used to keep track of childrens in slices
|
2020-07-06 17:02:59 +08:00
|
|
|
type Panel interface {
|
|
|
|
HasFocus() bool
|
|
|
|
SetBorderColor(color tcell.Color) *tview.Box
|
|
|
|
SetTitleColor(color tcell.Color) *tview.Box
|
|
|
|
SetTitle(s string) *tview.Box
|
|
|
|
GetTitle() string
|
2020-07-23 15:15:39 +08:00
|
|
|
help() []string
|
2020-07-06 17:02:59 +08:00
|
|
|
}
|
2020-07-04 16:16:57 +08:00
|
|
|
|
2020-08-11 14:36:20 +08:00
|
|
|
const (
|
2021-02-06 00:18:31 +08:00
|
|
|
configPath = ".config/gomu/config"
|
|
|
|
musicPath = "~/music"
|
2020-08-11 14:36:20 +08:00
|
|
|
)
|
|
|
|
|
2021-02-12 10:58:40 +08:00
|
|
|
func execConfig() error {
|
|
|
|
|
|
|
|
gomu.env.Define("echo", func(text string) {
|
|
|
|
defaultTimedPopup(" Debug ", text)
|
|
|
|
})
|
2020-07-06 17:02:59 +08:00
|
|
|
|
2021-02-12 10:58:40 +08:00
|
|
|
content, err := ioutil.ReadFile("/home/terra/.config/gomu/config.anko")
|
2020-07-23 15:15:39 +08:00
|
|
|
if err != nil {
|
2021-02-12 10:58:40 +08:00
|
|
|
return tracerr.Wrap(err)
|
2020-07-23 15:15:39 +08:00
|
|
|
}
|
2020-07-06 17:02:59 +08:00
|
|
|
|
2021-02-12 10:58:40 +08:00
|
|
|
_, err = vm.Execute(gomu.env, nil, string(content))
|
2020-07-23 15:15:39 +08:00
|
|
|
if err != nil {
|
2021-02-12 10:58:40 +08:00
|
|
|
return tracerr.Wrap(err)
|
2020-07-23 15:15:39 +08:00
|
|
|
}
|
2020-07-06 17:02:59 +08:00
|
|
|
|
2021-02-12 10:58:40 +08:00
|
|
|
return nil
|
|
|
|
}
|
2020-08-02 16:01:18 +08:00
|
|
|
|
2020-07-06 17:02:59 +08:00
|
|
|
|
|
|
|
|
2020-07-23 15:15:39 +08:00
|
|
|
type Args struct {
|
|
|
|
config *string
|
2020-08-11 13:39:02 +08:00
|
|
|
empty *bool
|
2020-07-23 15:15:39 +08:00
|
|
|
music *string
|
|
|
|
version *bool
|
2020-07-06 17:02:59 +08:00
|
|
|
}
|
|
|
|
|
2020-07-23 15:15:39 +08:00
|
|
|
func getArgs() Args {
|
|
|
|
ar := Args{
|
2021-02-06 00:18:31 +08:00
|
|
|
config: flag.String("config", configPath, "Specify config file"),
|
2020-08-11 13:39:02 +08:00
|
|
|
empty: flag.Bool("empty", false, "Open gomu with empty queue. Does not override previous queue"),
|
2021-02-06 00:18:31 +08:00
|
|
|
music: flag.String("music", musicPath, "Specify music directory"),
|
2020-08-11 12:56:06 +08:00
|
|
|
version: flag.Bool("version", false, "Print gomu version"),
|
2020-07-23 13:10:29 +08:00
|
|
|
}
|
2020-07-23 15:15:39 +08:00
|
|
|
flag.Parse()
|
|
|
|
return ar
|
2020-07-23 13:10:29 +08:00
|
|
|
}
|
|
|
|
|
2020-07-23 15:15:39 +08:00
|
|
|
// Sets the layout of the application
|
|
|
|
func layout(gomu *Gomu) *tview.Flex {
|
|
|
|
flex := tview.NewFlex().
|
|
|
|
AddItem(gomu.playlist, 0, 1, false).
|
|
|
|
AddItem(tview.NewFlex().SetDirection(tview.FlexRow).
|
|
|
|
AddItem(gomu.queue, 0, 5, false).
|
|
|
|
AddItem(gomu.playingBar, 0, 1, false), 0, 3, false)
|
2020-07-23 13:10:29 +08:00
|
|
|
|
2020-07-23 15:15:39 +08:00
|
|
|
return flex
|
2020-07-04 16:16:57 +08:00
|
|
|
}
|
|
|
|
|
2020-07-23 15:15:39 +08:00
|
|
|
// Initialize
|
2020-07-18 15:43:20 +08:00
|
|
|
func start(application *tview.Application, args Args) {
|
|
|
|
|
2020-07-23 15:15:39 +08:00
|
|
|
// Print version and exit
|
2020-07-21 20:51:10 +08:00
|
|
|
if *args.version {
|
|
|
|
fmt.Printf("Gomu %s\n", VERSION)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-22 14:41:03 +08:00
|
|
|
// Assigning to global variable gomu
|
|
|
|
gomu = newGomu()
|
2021-02-12 10:58:40 +08:00
|
|
|
err := execConfig()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2020-08-25 18:17:54 +08:00
|
|
|
gomu.args = args
|
2021-02-12 10:58:40 +08:00
|
|
|
gomu.colors = newColor()
|
2020-08-22 14:41:03 +08:00
|
|
|
|
2020-06-19 16:29:51 +08:00
|
|
|
// override default border
|
|
|
|
// change double line border to one line border when focused
|
2020-08-22 14:41:03 +08:00
|
|
|
tview.Borders.HorizontalFocus = tview.Borders.Horizontal
|
|
|
|
tview.Borders.VerticalFocus = tview.Borders.Vertical
|
|
|
|
tview.Borders.TopLeftFocus = tview.Borders.TopLeft
|
|
|
|
tview.Borders.TopRightFocus = tview.Borders.TopRight
|
|
|
|
tview.Borders.BottomLeftFocus = tview.Borders.BottomLeft
|
2020-07-06 18:58:27 +08:00
|
|
|
tview.Borders.BottomRightFocus = tview.Borders.BottomRight
|
2020-08-22 14:41:03 +08:00
|
|
|
tview.Styles.PrimitiveBackgroundColor = gomu.colors.background
|
2020-07-28 11:24:58 +08:00
|
|
|
|
2020-08-11 13:39:02 +08:00
|
|
|
gomu.initPanels(application, args)
|
2020-08-25 18:17:54 +08:00
|
|
|
gomu.command.defineCommands()
|
2020-06-19 16:29:51 +08:00
|
|
|
|
2020-07-23 15:15:39 +08:00
|
|
|
flex := layout(gomu)
|
|
|
|
gomu.pages.AddPage("main", flex, true, true)
|
2020-06-25 14:12:19 +08:00
|
|
|
|
2020-07-18 15:43:20 +08:00
|
|
|
// sets the first focused panel
|
2020-07-23 15:15:39 +08:00
|
|
|
gomu.setFocusPanel(gomu.playlist)
|
|
|
|
gomu.prevPanel = gomu.playlist
|
2020-06-25 14:12:19 +08:00
|
|
|
|
2021-02-10 15:06:08 +08:00
|
|
|
gomu.playingBar.setDefault()
|
|
|
|
|
2021-02-12 10:58:40 +08:00
|
|
|
isQueueLoop, err := getBool(gomu.env, "queue_loop")
|
|
|
|
if err != nil {
|
|
|
|
logError(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
gomu.player.isLoop = isQueueLoop
|
2021-02-03 10:50:01 +08:00
|
|
|
gomu.queue.isLoop = gomu.player.isLoop
|
2021-01-31 22:38:49 +08:00
|
|
|
|
2021-02-12 10:58:40 +08:00
|
|
|
loadQueue, err := getBool(gomu.env, "load_prev_queue")
|
|
|
|
if err != nil {
|
|
|
|
logError(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if !*args.empty && loadQueue {
|
2020-08-18 12:26:45 +08:00
|
|
|
// load saved queue from previous session
|
2020-07-23 15:15:39 +08:00
|
|
|
if err := gomu.queue.loadQueue(); err != nil {
|
|
|
|
logError(err)
|
2020-07-18 15:43:20 +08:00
|
|
|
}
|
2020-07-10 16:52:37 +08:00
|
|
|
}
|
|
|
|
|
2020-08-18 12:26:45 +08:00
|
|
|
sigs := make(chan os.Signal, 1)
|
2021-02-03 10:50:01 +08:00
|
|
|
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
2020-08-18 12:26:45 +08:00
|
|
|
go func() {
|
|
|
|
sig := <-sigs
|
|
|
|
errMsg := fmt.Sprintf("Received %s. Exiting program", sig.String())
|
|
|
|
logError(errors.New(errMsg))
|
|
|
|
err := gomu.quit(args)
|
|
|
|
if err != nil {
|
2021-02-03 10:50:01 +08:00
|
|
|
logError(errors.New("unable to quit program"))
|
2020-08-18 12:26:45 +08:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
// global keybindings are handled here
|
2020-08-25 18:17:54 +08:00
|
|
|
application.SetInputCapture(func(e *tcell.EventKey) *tcell.EventKey {
|
2020-06-19 16:29:51 +08:00
|
|
|
|
2020-07-24 15:22:50 +08:00
|
|
|
popupName, _ := gomu.pages.GetFrontPage()
|
|
|
|
|
|
|
|
// disables keybindings when writing in input fields
|
|
|
|
if strings.Contains(popupName, "-input-") {
|
2020-08-25 18:17:54 +08:00
|
|
|
return e
|
2020-07-24 15:22:50 +08:00
|
|
|
}
|
|
|
|
|
2020-08-25 18:17:54 +08:00
|
|
|
switch e.Key() {
|
2020-06-19 16:29:51 +08:00
|
|
|
// cycle through each section
|
|
|
|
case tcell.KeyTAB:
|
2020-07-24 15:22:50 +08:00
|
|
|
if strings.Contains(popupName, "confirmation-") {
|
2020-08-25 18:17:54 +08:00
|
|
|
return e
|
2020-07-24 14:51:45 +08:00
|
|
|
}
|
2021-01-28 14:50:05 +08:00
|
|
|
gomu.cyclePanels2()
|
2020-06-19 16:29:51 +08:00
|
|
|
}
|
|
|
|
|
2020-08-25 18:17:54 +08:00
|
|
|
cmds := map[rune]string{
|
|
|
|
'q': "quit",
|
|
|
|
' ': "toggle_pause",
|
|
|
|
'+': "volume_up",
|
2021-01-27 01:10:48 +08:00
|
|
|
'=': "volume_up",
|
2020-08-25 18:17:54 +08:00
|
|
|
'-': "volume_down",
|
2021-01-27 01:10:48 +08:00
|
|
|
'_': "volume_down",
|
2020-08-25 18:17:54 +08:00
|
|
|
'n': "skip",
|
|
|
|
':': "command_search",
|
|
|
|
'?': "toggle_help",
|
2021-01-27 01:10:48 +08:00
|
|
|
'f': "forward",
|
|
|
|
'F': "forward_fast",
|
|
|
|
'b': "rewind",
|
|
|
|
'B': "rewind_fast",
|
2020-08-25 18:17:54 +08:00
|
|
|
}
|
2020-06-21 23:47:12 +08:00
|
|
|
|
2020-08-25 18:17:54 +08:00
|
|
|
for key, cmd := range cmds {
|
|
|
|
if e.Rune() != key {
|
|
|
|
continue
|
2020-06-26 17:09:15 +08:00
|
|
|
}
|
2020-08-25 18:17:54 +08:00
|
|
|
fn, err := gomu.command.getFn(cmd)
|
|
|
|
if err != nil {
|
|
|
|
logError(err)
|
|
|
|
return e
|
2020-06-27 00:09:59 +08:00
|
|
|
}
|
2020-08-25 18:17:54 +08:00
|
|
|
fn()
|
2020-06-19 16:29:51 +08:00
|
|
|
}
|
|
|
|
|
2020-08-25 18:17:54 +08:00
|
|
|
return e
|
2020-06-19 16:29:51 +08:00
|
|
|
})
|
|
|
|
|
|
|
|
// fix transparent background issue
|
2020-06-26 12:54:48 +08:00
|
|
|
application.SetBeforeDrawFunc(func(screen tcell.Screen) bool {
|
2020-06-19 16:29:51 +08:00
|
|
|
screen.Clear()
|
|
|
|
return false
|
|
|
|
})
|
|
|
|
|
2021-02-03 10:50:01 +08:00
|
|
|
go populateAudioLength(gomu.playlist.GetRoot())
|
2020-06-19 16:29:51 +08:00
|
|
|
// main loop
|
2020-07-23 15:15:39 +08:00
|
|
|
if err := application.SetRoot(gomu.pages, true).SetFocus(gomu.playlist).Run(); err != nil {
|
|
|
|
logError(err)
|
2020-06-19 16:29:51 +08:00
|
|
|
}
|
2021-01-31 19:12:15 +08:00
|
|
|
|
2020-06-19 16:29:51 +08:00
|
|
|
}
|