77 lines
2.1 KiB
Go
77 lines
2.1 KiB
Go
package app
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/acaloiaro/di-tui/components"
|
|
"github.com/acaloiaro/di-tui/context"
|
|
"github.com/acaloiaro/di-tui/difm"
|
|
"github.com/faiface/beep/speaker"
|
|
)
|
|
|
|
// PlayChannel begins streaming the provided channel after fetching its playlist
|
|
// If a channel is already playing, the old stream is stopped first, clearing up resources.
|
|
// This function is *asynchronous* and creates a single streaming resource: the audio stream held by the application
|
|
// context. To clean up resources created by this function, Close() the application's audio stream.
|
|
func PlayChannel(chn *components.ChannelItem, ctx *context.AppContext) {
|
|
|
|
// when other channels are already playing, close their stream before playing a new one
|
|
if ctx.AudioStream != nil {
|
|
ctx.AudioStream.Close()
|
|
}
|
|
|
|
go func() {
|
|
client := &http.Client{}
|
|
req, _ := http.NewRequest("GET", chn.Playlist, nil)
|
|
resp, err := client.Do(req)
|
|
if err != nil || resp.StatusCode != 200 {
|
|
ctx.SetStatusMessage(fmt.Sprintf("Unable to stream channel: %s", chn.Name))
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
if streamURL, ok := difm.GetStreamURL(body); ok {
|
|
format := difm.Stream(streamURL, ctx)
|
|
|
|
if !ctx.SpeakerInitialized {
|
|
speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
|
|
ctx.SpeakerInitialized = true
|
|
}
|
|
|
|
speaker.Play(ctx.AudioStream)
|
|
ctx.IsPlaying = true
|
|
|
|
UpdateNowPlaying(chn, ctx)
|
|
}
|
|
}()
|
|
}
|
|
|
|
// TogglePause pauses/unpauses audio when a channel is playing
|
|
func TogglePause(ctx *context.AppContext) {
|
|
|
|
// nothing to do if nothing has been streamed
|
|
if ctx.AudioStream == nil {
|
|
return
|
|
}
|
|
|
|
ctx.AudioStream.Close()
|
|
if !ctx.IsPlaying {
|
|
PlayChannel(ctx.CurrentChannel, ctx)
|
|
}
|
|
|
|
ctx.IsPlaying = !ctx.IsPlaying
|
|
}
|
|
|
|
// UpdateNowPlaying updates the application's now playing view with the currently playing channel
|
|
func UpdateNowPlaying(chn *components.ChannelItem, ctx *context.AppContext) {
|
|
ctx.CurrentChannel = chn
|
|
cp := difm.GetCurrentlyPlaying(ctx)
|
|
|
|
ctx.View.App.QueueUpdateDraw(func() {
|
|
ctx.View.NowPlaying.Channel = chn
|
|
ctx.View.NowPlaying.Track = cp.Track
|
|
})
|
|
}
|