parent
e05777a01a
commit
c50589ef5f
6 changed files with 104 additions and 24 deletions
|
@ -1,3 +1,7 @@
|
|||
0.1.5:
|
||||
- Add initial volume configuration option and flag
|
||||
- Use default terminal colors
|
||||
|
||||
0.1.4:
|
||||
- Add --fd and --restrict-library options
|
||||
- Add keybind to toggle hidden folder visibility
|
||||
|
|
|
@ -25,6 +25,8 @@ configuration options and their defaults.
|
|||
# Default ~/.config/ditty/config.yaml
|
||||
|
||||
```yaml
|
||||
volume: 75
|
||||
|
||||
input:
|
||||
select:
|
||||
- 'Enter'
|
||||
|
|
33
audio.go
33
audio.go
|
@ -23,6 +23,9 @@ import (
|
|||
const defaultBufferSize = 500 * time.Millisecond
|
||||
|
||||
var (
|
||||
startingVolumeLevel float64
|
||||
startingVolumeSilent bool
|
||||
|
||||
playingFileName string
|
||||
playingFileInfo string
|
||||
playingFileID int64
|
||||
|
@ -30,9 +33,8 @@ var (
|
|||
playingFormat beep.Format
|
||||
playingSampleRate beep.SampleRate
|
||||
|
||||
volume *effects.Volume
|
||||
ctrl *beep.Ctrl
|
||||
|
||||
volume *effects.Volume
|
||||
ctrl *beep.Ctrl
|
||||
audioLock = new(sync.Mutex)
|
||||
)
|
||||
|
||||
|
@ -135,8 +137,8 @@ func play(audioFile *audioFile) {
|
|||
volume = &effects.Volume{
|
||||
Streamer: streamer,
|
||||
Base: volumeBase,
|
||||
Volume: 0.0,
|
||||
Silent: false,
|
||||
Volume: startingVolumeLevel,
|
||||
Silent: startingVolumeSilent,
|
||||
}
|
||||
|
||||
ctrl = &beep.Ctrl{
|
||||
|
@ -260,6 +262,9 @@ func adjustVolume(adjustment float64) {
|
|||
defer audioLock.Unlock()
|
||||
|
||||
if volume == nil {
|
||||
startingVolumeLevel += adjustment
|
||||
startingVolumeUpdated()
|
||||
go app.QueueUpdateDraw(updateStatus)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -276,6 +281,9 @@ func setVolume(vol float64) {
|
|||
defer audioLock.Unlock()
|
||||
|
||||
if volume == nil {
|
||||
startingVolumeLevel = vol
|
||||
startingVolumeUpdated()
|
||||
go app.QueueUpdateDraw(updateStatus)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -308,11 +316,26 @@ func volumeUpdated() {
|
|||
}
|
||||
}
|
||||
|
||||
func startingVolumeUpdated() {
|
||||
if startingVolumeLevel <= -7.5 {
|
||||
startingVolumeLevel = -7.5
|
||||
startingVolumeSilent = true
|
||||
} else {
|
||||
startingVolumeSilent = false
|
||||
|
||||
if startingVolumeLevel > 0 {
|
||||
startingVolumeLevel = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func toggleMute() {
|
||||
audioLock.Lock()
|
||||
defer audioLock.Unlock()
|
||||
|
||||
if volume == nil {
|
||||
startingVolumeSilent = !startingVolumeSilent
|
||||
go app.QueueUpdateDraw(updateStatus)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
10
config.go
10
config.go
|
@ -10,10 +10,13 @@ import (
|
|||
)
|
||||
|
||||
type appConfig struct {
|
||||
Input map[string][]string
|
||||
Input map[string][]string // Keybinds
|
||||
Volume int // Starting volume
|
||||
}
|
||||
|
||||
var config = &appConfig{}
|
||||
var config = &appConfig{
|
||||
Volume: 75,
|
||||
}
|
||||
|
||||
func defaultConfigPath() string {
|
||||
homedir, err := os.UserHomeDir()
|
||||
|
@ -40,6 +43,9 @@ func readConfig(configPath string) error {
|
|||
}
|
||||
|
||||
err = yaml.Unmarshal(configData, config)
|
||||
if err == nil && (config.Volume < 0 || config.Volume > 100) {
|
||||
err = fmt.Errorf("invalid volume (must be between 0 and 100): %d", config.Volume)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse file: %s", err)
|
||||
}
|
||||
|
|
44
gui.go
44
gui.go
|
@ -263,12 +263,17 @@ func updateStatus() {
|
|||
statusLock.Lock()
|
||||
defer statusLock.Unlock()
|
||||
|
||||
var sampleRate beep.SampleRate
|
||||
var p time.Duration
|
||||
var l time.Duration
|
||||
var v float64
|
||||
var paused bool
|
||||
var silent bool
|
||||
var (
|
||||
sampleRate beep.SampleRate
|
||||
p time.Duration
|
||||
l time.Duration
|
||||
v float64
|
||||
paused bool
|
||||
silent bool
|
||||
|
||||
progressFormatted string
|
||||
durationFormatted string
|
||||
)
|
||||
if playingStreamer != nil && volume != nil && ctrl != nil {
|
||||
audioLock.Lock()
|
||||
speaker.Lock()
|
||||
|
@ -281,6 +286,9 @@ func updateStatus() {
|
|||
speaker.Unlock()
|
||||
audioLock.Unlock()
|
||||
|
||||
progressFormatted = formatDuration(p)
|
||||
durationFormatted = formatDuration(l)
|
||||
|
||||
statusBuffer.Reset()
|
||||
|
||||
if paused {
|
||||
|
@ -316,6 +324,26 @@ func updateStatus() {
|
|||
statusBuffer.WriteString(topStatusExtra)
|
||||
}
|
||||
|
||||
topstatusbuf.SetText(statusBuffer.String())
|
||||
} else {
|
||||
v = startingVolumeLevel
|
||||
silent = startingVolumeSilent
|
||||
|
||||
progressFormatted = "--:--"
|
||||
durationFormatted = "--:--"
|
||||
|
||||
statusBuffer.Reset()
|
||||
|
||||
trackInfo := fmt.Sprintf("ditty %s", version)
|
||||
|
||||
topStatusMaxLength := screenWidth - 2
|
||||
padding := (topStatusMaxLength - runewidth.StringWidth(trackInfo)) + 1
|
||||
for i := 0; i < padding; i++ {
|
||||
statusBuffer.WriteRune(' ')
|
||||
}
|
||||
|
||||
statusBuffer.WriteString(trackInfo)
|
||||
|
||||
topstatusbuf.SetText(statusBuffer.String())
|
||||
}
|
||||
|
||||
|
@ -339,7 +367,7 @@ func updateStatus() {
|
|||
}
|
||||
}
|
||||
|
||||
bottomStatus := fmt.Sprintf("%s %s", formatDuration(l), statusBuffer.String())
|
||||
bottomStatus := fmt.Sprintf("%s %s", durationFormatted, statusBuffer.String())
|
||||
statusBuffer.Reset()
|
||||
|
||||
var progressIndicator string
|
||||
|
@ -372,7 +400,7 @@ func updateStatus() {
|
|||
volumeStart = seekEnd + len(formatDuration(l)) + 4
|
||||
volumeEnd = screenWidth - 2
|
||||
|
||||
bottomstatusbuf.SetText(" " + formatDuration(p) + " " + statusBuffer.String() + " " + bottomStatus)
|
||||
bottomstatusbuf.SetText(" " + progressFormatted + " " + statusBuffer.String() + " " + bottomStatus)
|
||||
statusBuffer.Reset()
|
||||
}
|
||||
|
||||
|
|
35
main.go
35
main.go
|
@ -26,15 +26,16 @@ Copyright (c) 2020 Trevor Slocum <trevor@rocketnine.space>
|
|||
)
|
||||
|
||||
var (
|
||||
configPath string
|
||||
printVersionInfo bool
|
||||
bufferSize time.Duration
|
||||
debugAddress string
|
||||
cpuProfile string
|
||||
streamFdInt int
|
||||
streamFd *os.File
|
||||
restrictLibrary string
|
||||
showHiddenFolders bool
|
||||
configPath string
|
||||
printVersionInfo bool
|
||||
bufferSize time.Duration
|
||||
debugAddress string
|
||||
cpuProfile string
|
||||
streamFdInt int
|
||||
streamFd *os.File
|
||||
restrictLibrary string
|
||||
showHiddenFolders bool
|
||||
startingVolumeFlag int
|
||||
|
||||
version = "0.0.0"
|
||||
done = make(chan bool)
|
||||
|
@ -50,6 +51,7 @@ func main() {
|
|||
flag.StringVar(&configPath, "config", "", "path to configuration file")
|
||||
flag.BoolVar(&printVersionInfo, "version", false, "print version information and exit")
|
||||
flag.IntVar(&streamFdInt, "fd", -1, "stream audio to file descriptor")
|
||||
flag.IntVar(&startingVolumeFlag, "volume", -1, "initial volume level 0-100")
|
||||
flag.StringVar(&restrictLibrary, "restrict-library", "", "restrict library to path")
|
||||
flag.DurationVar(&bufferSize, "buffer-size", defaultBufferSize, "audio buffer size")
|
||||
flag.StringVar(&debugAddress, "debug-address", "", "address to serve debug info")
|
||||
|
@ -94,6 +96,10 @@ func main() {
|
|||
log.Fatalf("failed to read configuration file: %s", err)
|
||||
}
|
||||
|
||||
if startingVolumeFlag >= 0 {
|
||||
config.Volume = startingVolumeFlag
|
||||
}
|
||||
|
||||
err = setKeyBinds()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to set keybinds: %s", err)
|
||||
|
@ -123,6 +129,17 @@ func main() {
|
|||
done <- true
|
||||
}()
|
||||
|
||||
var vol float64
|
||||
if config.Volume == 0 {
|
||||
vol = -7.5
|
||||
} else {
|
||||
vol = -7.5 + float64(7.5)*(float64(config.Volume)/float64(100))
|
||||
if vol < -7.0 {
|
||||
vol = -7.0
|
||||
}
|
||||
}
|
||||
setVolume(roundUnit(vol, 0.5))
|
||||
|
||||
startPath := strings.Join(flag.Args(), " ")
|
||||
if startPath == "" {
|
||||
if restrictLibrary == "" {
|
||||
|
|
Loading…
Reference in a new issue