uplink/plugins/icecast/output/instance.go

104 lines
2.8 KiB
Go
Raw Normal View History

package icecast_output
import (
2018-04-11 15:55:15 +00:00
"fmt"
"io"
2018-04-11 15:55:15 +00:00
"log"
"git.icedream.tech/icedream/uplink/app/authentication"
"git.icedream.tech/icedream/uplink/app/channels"
"git.icedream.tech/icedream/uplink/app/servers/http"
2018-04-11 15:55:15 +00:00
"git.icedream.tech/icedream/uplink/app/streams"
"github.com/gin-gonic/gin"
)
type pluginInstance struct {
server *httpserver.Server
authenticator authentication.Authenticator
channelManager *channels.ChannelManager
}
func (instance *pluginInstance) SetAuthenticator(authenticator authentication.Authenticator) {
instance.authenticator = authenticator
}
func (instance *pluginInstance) SetChannelManager(channelManager *channels.ChannelManager) {
instance.channelManager = channelManager
2018-04-11 15:55:15 +00:00
// TODO - handle channel and container closure
}
func (instance *pluginInstance) SetServer(server *httpserver.Server) {
instance.server = server
2018-04-11 15:55:15 +00:00
}
func (instance *pluginInstance) Init() {
router := instance.server.Router
2018-04-11 15:55:15 +00:00
router.GET("/:channel/:container", func(ctx *gin.Context) {
r := ctx.Request
var mw *streams.MetadataInjector
channelId := ctx.Param("channel")
containerId := ctx.Param("container")
sendMetadata := r.Header.Get("icy-metadata") == "1"
metaInt := 16 * 1024
channel := instance.channelManager.Channel(channelId)
if channel == nil {
ctx.Status(404)
return
}
2018-04-11 15:55:15 +00:00
container, ok := channel.OutputContainers[containerId]
if !ok {
ctx.Status(404)
}
ctx.Writer.Header().Set("content-type", "audio/mpeg") // TODO
if sendMetadata {
ctx.Writer.Header().Set("icy-metadata", "1")
ctx.Writer.Header().Set("icy-metaint", fmt.Sprintf("%d", metaInt))
}
ctx.Writer.Header().Set("icy-name", "Channel name") // TODO
ctx.Writer.Header().Set("icy-pub", "0") // TODO
ctx.Writer.Header().Set("Server", "Uplink/0.0.0; Icecast 2.4.0 compatible")
ctx.Writer.Header().Set("Cache-Control", "no-cache, no-store")
ctx.Writer.Header().Set("Access-Control-Allow-Origin", "*")
ctx.Writer.Header().Set("Access-Control-Allow-Headers", "Origin, Accept, X-Requested-With, Content-Type")
ctx.Writer.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS, HEAD")
2018-04-11 15:55:15 +00:00
ctx.Writer.WriteHeader(200)
w := ctx.Writer
var nw io.Writer = w
sr := container.Sub()
defer sr.Close()
if sendMetadata {
mw = streams.NewMetadataInjector(w, metaInt)
nw = mw
2018-07-02 06:09:47 +00:00
metadataChan := channel.Metadata()
2018-07-02 06:30:11 +00:00
defer func() { metadataChan <- nil }()
2018-07-02 06:09:47 +00:00
go func() {
for metadata := range metadataChan {
metadataToWrite := streams.Metadata{}
if value, ok := metadata["StreamTitle"]; ok {
metadataToWrite["StreamTitle"] = value
}
mw.SetMetadata(metadataToWrite)
}
}()
2018-04-11 15:55:15 +00:00
}
_, err := io.Copy(nw, sr)
if err != nil {
2018-07-02 06:09:47 +00:00
log.Println("copying stream to output failed:", err)
}
})
2018-04-11 15:55:15 +00:00
// TODO - output streams
// TODO - dynamic transcoding targets
}