2022-02-06 00:34:05 +01:00
|
|
|
package gstreamer
|
|
|
|
|
|
|
|
import (
|
2022-02-07 11:20:50 +01:00
|
|
|
"context"
|
2022-02-06 00:34:05 +01:00
|
|
|
"errors"
|
2023-02-05 14:01:12 +01:00
|
|
|
|
2022-02-06 00:34:05 +01:00
|
|
|
"github.com/tinyzimmer/go-glib/glib"
|
|
|
|
"github.com/tinyzimmer/go-gst/gst"
|
|
|
|
)
|
|
|
|
|
|
|
|
var gstreamer *Gstreamer
|
|
|
|
|
|
|
|
func Init() *Gstreamer {
|
|
|
|
gst.Init(nil)
|
2022-02-07 11:20:50 +01:00
|
|
|
mainLoop := glib.NewMainLoop(glib.MainContextDefault(), false)
|
|
|
|
go mainLoop.Run()
|
|
|
|
decklink := &Decklink{
|
|
|
|
Slots: map[string]string{"one": ""},
|
|
|
|
}
|
|
|
|
gstreamer = &Gstreamer{
|
2022-02-09 00:04:00 +01:00
|
|
|
ctx: context.Background(),
|
|
|
|
Pipelines: map[string]*Pipeline{},
|
|
|
|
pipelineSlots: make(map[string][]string),
|
|
|
|
notifyOnUpdate: map[string][]NotifyOnPipelineUpdate{},
|
|
|
|
Decklink: decklink,
|
2022-02-07 11:20:50 +01:00
|
|
|
}
|
2022-02-06 00:34:05 +01:00
|
|
|
return gstreamer
|
|
|
|
}
|
|
|
|
|
2022-02-09 00:04:00 +01:00
|
|
|
func (g *Gstreamer) AddPipeline(pipeline *Pipeline) {
|
|
|
|
g.Lock()
|
|
|
|
defer g.Unlock()
|
2023-02-05 14:01:12 +01:00
|
|
|
|
2022-02-09 00:04:00 +01:00
|
|
|
if _, ok := g.pipelineSlots[pipeline.Name]; ok {
|
|
|
|
g.pipelineSlots[pipeline.Name] = append(g.pipelineSlots[pipeline.Name], pipeline.ID)
|
|
|
|
} else {
|
|
|
|
g.pipelineSlots[pipeline.Name] = []string{pipeline.ID}
|
|
|
|
}
|
|
|
|
g.Pipelines[pipeline.ID] = pipeline
|
|
|
|
pipeline.SubscribeToUpdates(g.notifySlotSubscriber())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g *Gstreamer) DeletePipeline(id string) error {
|
2022-02-06 00:34:05 +01:00
|
|
|
g.Lock()
|
2022-02-07 11:20:50 +01:00
|
|
|
defer g.Unlock()
|
|
|
|
if pipeline, err := g.getPipeline(id); err == nil {
|
2022-02-09 00:04:00 +01:00
|
|
|
var i int
|
|
|
|
for i := range g.pipelineSlots[pipeline.Name] {
|
|
|
|
if g.pipelineSlots[pipeline.Name][i] == pipeline.ID {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g.pipelineSlots[pipeline.Name] = append(g.pipelineSlots[pipeline.Name][:i], g.pipelineSlots[pipeline.Name][i+1:]...)
|
|
|
|
|
2022-02-06 00:34:05 +01:00
|
|
|
delete(g.Pipelines, id)
|
|
|
|
pipeline.ctxCancel()
|
2022-02-09 00:04:00 +01:00
|
|
|
return nil
|
2022-02-06 00:34:05 +01:00
|
|
|
}
|
2022-02-09 00:04:00 +01:00
|
|
|
return errors.New("pipeline not found")
|
2022-02-06 00:34:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (g *Gstreamer) GetPipeline(id string) (*Pipeline, error) {
|
|
|
|
g.RLock()
|
2022-02-07 11:20:50 +01:00
|
|
|
defer g.RUnlock()
|
|
|
|
return g.getPipeline(id)
|
|
|
|
}
|
|
|
|
|
2023-02-05 14:01:12 +01:00
|
|
|
// only use this if ressource is locked
|
2022-02-07 11:20:50 +01:00
|
|
|
func (g *Gstreamer) getPipeline(id string) (*Pipeline, error) {
|
2022-02-06 00:34:05 +01:00
|
|
|
if pipeline, ok := g.Pipelines[id]; ok {
|
|
|
|
return pipeline, nil
|
|
|
|
}
|
|
|
|
return nil, errors.New("Pipeline not found")
|
|
|
|
}
|
2022-02-09 00:04:00 +01:00
|
|
|
|
|
|
|
func (g *Gstreamer) SubscribeToSlotUpdates(slot string, callback NotifyOnPipelineUpdate) {
|
|
|
|
g.Lock()
|
|
|
|
defer g.Unlock()
|
|
|
|
if _, ok := g.notifyOnUpdate[slot]; ok {
|
|
|
|
g.notifyOnUpdate[slot] = append(g.notifyOnUpdate[slot], callback)
|
|
|
|
} else {
|
|
|
|
g.notifyOnUpdate[slot] = []NotifyOnPipelineUpdate{callback}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g *Gstreamer) notifySlotSubscriber() NotifyOnPipelineUpdate {
|
|
|
|
return func(pipeline *Pipeline) {
|
|
|
|
for _, callback := range g.notifyOnUpdate[pipeline.Name] {
|
|
|
|
callback(pipeline)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|