diff --git a/CONFIGURATION.md b/CONFIGURATION.md index 5899d0a..a3b0c0a 100644 --- a/CONFIGURATION.md +++ b/CONFIGURATION.md @@ -3,9 +3,11 @@ configuration options and their defaults. # Options -* **--buffer-size** Audio buffer size (default 500ms) -* **--fd** Write audio in WAV format to the specified file descriptor. This allows ditty to be used over ssh: +* **--buffer-size** Audio buffer size, defaults to 500ms. +* **--restrict-library** Restrict access to a folder and its subfolders. +* **--fd** Write audio in WAV format to the specified file descriptor instead. This allows ditty to be used over ssh: * `ssh ditty.rocketnine.space -t 'ditty --fd=2' 2> >(aplay --quiet)` + * Note: Writing to a file descriptor disables pause support. # Default keybindings diff --git a/audio.go b/audio.go index 8278e00..f94d7c0 100644 --- a/audio.go +++ b/audio.go @@ -30,10 +30,6 @@ var ( playingFormat beep.Format playingSampleRate beep.SampleRate - nextStreamer beep.StreamSeekCloser - nextFormat beep.Format - nextFileName string - volume *effects.Volume ctrl *beep.Ctrl @@ -155,8 +151,9 @@ func play(audioFile *audioFile) { streamFd = os.NewFile(uintptr(streamFdInt), "out") go func() { + rateLimitedStreamer := NewRateLimitedStreamer(ctrl, bufferSize/64) for { - _ = wav.Encode(streamFd, ctrl, playingFormat) + _ = wav.Encode(streamFd, rateLimitedStreamer, playingFormat) time.Sleep(250 * time.Millisecond) } }() diff --git a/gui_list.go b/gui_list.go index a8845d8..2f134e0 100644 --- a/gui_list.go +++ b/gui_list.go @@ -3,8 +3,6 @@ package main import ( "path" "time" - - "github.com/faiface/beep" ) func listPrevious() { @@ -34,8 +32,6 @@ func listSelect() { browseFolder(path.Join(mainBufferDirectory, "..")) return } - nextStreamer = nil - nextFormat = beep.Format{} entry := selectedEntry() if entry.File.IsDir() { diff --git a/streamer.go b/streamer.go new file mode 100644 index 0000000..d4a5f5e --- /dev/null +++ b/streamer.go @@ -0,0 +1,31 @@ +package main + +import ( + "time" + + "github.com/faiface/beep" +) + +type RateLimitedStreamer struct { + streamer beep.Streamer + rate time.Duration + last time.Time +} + +func NewRateLimitedStreamer(streamer beep.Streamer, rate time.Duration) *RateLimitedStreamer { + s := RateLimitedStreamer{streamer: streamer, rate: rate} + return &s +} + +func (s *RateLimitedStreamer) Stream(samples [][2]float64) (n int, ok bool) { + if time.Since(s.last) < s.rate { + time.Sleep(time.Until(s.last.Add(s.rate))) + } + s.last = time.Now() + + return s.streamer.Stream(samples) +} + +func (s *RateLimitedStreamer) Err() error { + return s.streamer.Err() +}