on progresse
This commit is contained in:
16
upnp/devices/device.go
Normal file
16
upnp/devices/device.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package devices
|
||||
|
||||
type Device struct {
|
||||
deviceType string
|
||||
friendlyName string
|
||||
manufacturer string
|
||||
manufacturerURL string
|
||||
modelDescription string
|
||||
modelName string
|
||||
modelNumber string
|
||||
modelURL string
|
||||
serialNumber string
|
||||
specVersion string
|
||||
presentationURL string
|
||||
UDN string
|
||||
}
|
||||
17
upnp/devices/mediarenderer/AVTransport/avtransport.go
Normal file
17
upnp/devices/mediarenderer/AVTransport/avtransport.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package mediarenderer
|
||||
|
||||
import "gargoton.petite-maison-orange.fr/eric/pmomusic/upnp/devices/services"
|
||||
|
||||
var AVTransport = func() *services.Service {
|
||||
svc := services.NewService("AVTransport")
|
||||
|
||||
svc.AddVariable(AVTransportURI)
|
||||
svc.AddVariable(AVTransportURIMetaData)
|
||||
svc.AddVariable(CurrentTrackDuration)
|
||||
svc.AddVariable(SeekMode)
|
||||
svc.AddVariable(TransportPlaySpeed)
|
||||
svc.AddVariable(TransportState)
|
||||
svc.AddVariable(TransportStatus)
|
||||
|
||||
return svc
|
||||
}()
|
||||
10
upnp/devices/mediarenderer/AVTransport/sv_AVTransportURI.go
Normal file
10
upnp/devices/mediarenderer/AVTransport/sv_AVTransportURI.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package mediarenderer
|
||||
|
||||
import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/upnp/devices/services/statevariables"
|
||||
|
||||
var AVTransportURI = func() *sv.StateVariable {
|
||||
|
||||
ts := sv.StateType_String.NewStateValue("AVTransportURI")
|
||||
|
||||
return ts
|
||||
}()
|
||||
@@ -0,0 +1,10 @@
|
||||
package mediarenderer
|
||||
|
||||
import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/upnp/devices/services/statevariables"
|
||||
|
||||
var AVTransportURIMetaData = func() *sv.StateVariable {
|
||||
|
||||
ts := sv.StateType_String.NewStateValue("AVTransportURIMetaData")
|
||||
|
||||
return ts
|
||||
}()
|
||||
@@ -0,0 +1,10 @@
|
||||
package mediarenderer
|
||||
|
||||
import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/upnp/devices/services/statevariables"
|
||||
|
||||
var CurrentTrackDuration = func() *sv.StateVariable {
|
||||
|
||||
ts := sv.StateType_String.NewStateValue("CurrentTrackDuration")
|
||||
|
||||
return ts
|
||||
}()
|
||||
10
upnp/devices/mediarenderer/AVTransport/sv_SeekMode.go
Normal file
10
upnp/devices/mediarenderer/AVTransport/sv_SeekMode.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package mediarenderer
|
||||
|
||||
import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/upnp/devices/services/statevariables"
|
||||
|
||||
var SeekMode = func() *sv.StateVariable {
|
||||
|
||||
ts := sv.StateType_String.NewStateValue("SeekMode")
|
||||
|
||||
return ts
|
||||
}()
|
||||
@@ -0,0 +1,10 @@
|
||||
package mediarenderer
|
||||
|
||||
import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/upnp/devices/services/statevariables"
|
||||
|
||||
var TransportPlaySpeed = func() *sv.StateVariable {
|
||||
|
||||
ts := sv.StateType_String.NewStateValue("TransportPlaySpeed")
|
||||
|
||||
return ts
|
||||
}()
|
||||
20
upnp/devices/mediarenderer/AVTransport/sv_TransportState.go
Normal file
20
upnp/devices/mediarenderer/AVTransport/sv_TransportState.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package mediarenderer
|
||||
|
||||
import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/upnp/devices/services/statevariables"
|
||||
|
||||
var TransportState = func() *sv.StateVariable {
|
||||
|
||||
ts := sv.StateType_String.NewStateValue("TransportState")
|
||||
|
||||
ts.SetAllowedValues(
|
||||
"STOPPED",
|
||||
"PLAYING",
|
||||
"PAUSED_PLAYBACK",
|
||||
"TRANSITIONING",
|
||||
"NO_MEDIA_PRESENT",
|
||||
)
|
||||
|
||||
ts.SetSendingEvents()
|
||||
|
||||
return ts
|
||||
}()
|
||||
17
upnp/devices/mediarenderer/AVTransport/sv_TransportStatus.go
Normal file
17
upnp/devices/mediarenderer/AVTransport/sv_TransportStatus.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package mediarenderer
|
||||
|
||||
import sv "gargoton.petite-maison-orange.fr/eric/pmomusic/upnp/devices/services/statevariables"
|
||||
|
||||
var TransportStatus = func() *sv.StateVariable {
|
||||
|
||||
ts := sv.StateType_String.NewStateValue("TransportStatus")
|
||||
|
||||
ts.SetAllowedValues(
|
||||
"OK",
|
||||
"ERROR_OCCURRED",
|
||||
)
|
||||
|
||||
ts.SetSendingEvents()
|
||||
|
||||
return ts
|
||||
}()
|
||||
@@ -0,0 +1 @@
|
||||
package connectionmanager
|
||||
39
upnp/devices/services/actions/action.go
Normal file
39
upnp/devices/services/actions/action.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package actions
|
||||
|
||||
import "github.com/beevik/etree"
|
||||
|
||||
type Action struct {
|
||||
name string
|
||||
|
||||
arguments ArgumentSet
|
||||
}
|
||||
|
||||
func NewAction(name string) *Action {
|
||||
ac := &Action{
|
||||
name: name,
|
||||
}
|
||||
|
||||
return ac
|
||||
}
|
||||
|
||||
func (a *Action) Name() string {
|
||||
return a.name
|
||||
}
|
||||
|
||||
func (a *Action) TypeID() string {
|
||||
return "Action"
|
||||
}
|
||||
|
||||
func (a *Action) AddArgument(arg *Argument) {
|
||||
a.arguments.Insert(arg)
|
||||
}
|
||||
|
||||
func (a *Action) ToXMLElement() *etree.Element {
|
||||
elem := etree.NewElement("action")
|
||||
|
||||
name := elem.CreateElement("name")
|
||||
name.SetText(a.Name())
|
||||
|
||||
elem.AddChild(a.arguments.ToXMLElement())
|
||||
return elem
|
||||
}
|
||||
32
upnp/devices/services/actions/actionset.go
Normal file
32
upnp/devices/services/actions/actionset.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package actions
|
||||
|
||||
import (
|
||||
"iter"
|
||||
|
||||
"gargoton.petite-maison-orange.fr/eric/pmomusic/upnp/objectstore"
|
||||
"github.com/beevik/etree"
|
||||
)
|
||||
|
||||
type ActionSet objectstore.ObjectSet[*Action]
|
||||
|
||||
func (m *ActionSet) Insert(obj *Action) {
|
||||
(*objectstore.ObjectSet[*Action])(m).Insert(obj)
|
||||
}
|
||||
|
||||
func (set *ActionSet) Contains(obj *Action) bool {
|
||||
return (*objectstore.ObjectSet[*Action])(set).Contains(obj)
|
||||
}
|
||||
|
||||
func (m *ActionSet) All() iter.Seq[*Action] {
|
||||
return (*objectstore.ObjectSet[*Action])(m).All()
|
||||
}
|
||||
|
||||
func (m *ActionSet) ToXMLElement() *etree.Element {
|
||||
elem := etree.NewElement("ActionList")
|
||||
|
||||
for sv := range m.All() {
|
||||
elem.AddChild(sv.ToXMLElement())
|
||||
}
|
||||
|
||||
return elem
|
||||
}
|
||||
100
upnp/devices/services/actions/argument.go
Normal file
100
upnp/devices/services/actions/argument.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package actions
|
||||
|
||||
import (
|
||||
"gargoton.petite-maison-orange.fr/eric/pmomusic/upnp/devices/services/statevariables"
|
||||
"github.com/beevik/etree"
|
||||
)
|
||||
|
||||
type Argument struct {
|
||||
name string
|
||||
statevariables *statevariables.StateVariable
|
||||
in bool
|
||||
out bool
|
||||
}
|
||||
|
||||
func newArgument(name string, statevariable *statevariables.StateVariable) *Argument {
|
||||
arg := &Argument{
|
||||
name: name,
|
||||
statevariables: statevariable,
|
||||
}
|
||||
return arg
|
||||
}
|
||||
|
||||
func NewInArgument(name string, statevariable *statevariables.StateVariable) *Argument {
|
||||
arg := newArgument(name, statevariable)
|
||||
arg.in = true
|
||||
return arg
|
||||
}
|
||||
|
||||
func NewOutArgument(name string, statevariable *statevariables.StateVariable) *Argument {
|
||||
arg := newArgument(name, statevariable)
|
||||
arg.out = true
|
||||
return arg
|
||||
}
|
||||
|
||||
func NewInOutArgument(name string, statevariable *statevariables.StateVariable) *Argument {
|
||||
arg := newArgument(name, statevariable)
|
||||
arg.in = true
|
||||
arg.out = true
|
||||
return arg
|
||||
}
|
||||
|
||||
func (a *Argument) Name() string {
|
||||
return a.name
|
||||
}
|
||||
|
||||
func (sv Argument) TypeID() string {
|
||||
return "Argument"
|
||||
}
|
||||
|
||||
func (a *Argument) StateVariable() *statevariables.StateVariable {
|
||||
return a.statevariables
|
||||
}
|
||||
|
||||
func (a *Argument) IsIn() bool {
|
||||
return a.in
|
||||
}
|
||||
|
||||
func (a *Argument) IsOut() bool {
|
||||
return a.out
|
||||
}
|
||||
|
||||
func (a *Argument) ToXMLElement() *etree.Element {
|
||||
var elem, arg *etree.Element
|
||||
|
||||
if a.IsIn() && a.IsOut() {
|
||||
elem = etree.NewElement("")
|
||||
arg = elem.CreateElement("argument")
|
||||
} else {
|
||||
elem = etree.NewElement("argument")
|
||||
arg = elem
|
||||
}
|
||||
|
||||
if a.IsIn() {
|
||||
name := arg.CreateElement("name")
|
||||
name.SetText(a.Name())
|
||||
|
||||
direction := arg.CreateElement("direction")
|
||||
direction.SetText("in")
|
||||
|
||||
relatedStateVariable := arg.CreateElement("relatedStateVariable")
|
||||
relatedStateVariable.SetText(a.StateVariable().Name())
|
||||
}
|
||||
|
||||
if a.IsIn() && a.IsOut() {
|
||||
arg = elem.CreateElement("argument")
|
||||
}
|
||||
|
||||
if a.IsOut() {
|
||||
name := arg.CreateElement("name")
|
||||
name.SetText(a.Name())
|
||||
|
||||
direction := arg.CreateElement("direction")
|
||||
direction.SetText("out")
|
||||
|
||||
relatedStateVariable := arg.CreateElement("relatedStateVariable")
|
||||
relatedStateVariable.SetText(a.StateVariable().Name())
|
||||
}
|
||||
|
||||
return elem
|
||||
}
|
||||
32
upnp/devices/services/actions/argumentset.go
Normal file
32
upnp/devices/services/actions/argumentset.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package actions
|
||||
|
||||
import (
|
||||
"iter"
|
||||
|
||||
"gargoton.petite-maison-orange.fr/eric/pmomusic/upnp/objectstore"
|
||||
"github.com/beevik/etree"
|
||||
)
|
||||
|
||||
type ArgumentSet objectstore.ObjectSet[*Argument]
|
||||
|
||||
func (m *ArgumentSet) Insert(obj *Argument) {
|
||||
(*objectstore.ObjectSet[*Argument])(m).Insert(obj)
|
||||
}
|
||||
|
||||
func (set *ArgumentSet) Contains(obj *Argument) bool {
|
||||
return (*objectstore.ObjectSet[*Argument])(set).Contains(obj)
|
||||
}
|
||||
|
||||
func (m *ArgumentSet) All() iter.Seq[*Argument] {
|
||||
return (*objectstore.ObjectSet[*Argument])(m).All()
|
||||
}
|
||||
|
||||
func (m *ArgumentSet) ToXMLElement() *etree.Element {
|
||||
elem := etree.NewElement("argumentList")
|
||||
|
||||
for sv := range m.All() {
|
||||
elem.AddChild(sv.ToXMLElement())
|
||||
}
|
||||
|
||||
return elem
|
||||
}
|
||||
129
upnp/devices/services/service.go
Normal file
129
upnp/devices/services/service.go
Normal file
@@ -0,0 +1,129 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"iter"
|
||||
|
||||
"github.com/beevik/etree"
|
||||
|
||||
"gargoton.petite-maison-orange.fr/eric/pmomusic/upnp/devices/services/actions"
|
||||
sv "gargoton.petite-maison-orange.fr/eric/pmomusic/upnp/devices/services/statevariables"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
name string
|
||||
identifier string
|
||||
version int
|
||||
|
||||
controlURL string
|
||||
eventSubURL string
|
||||
scpdURL string
|
||||
|
||||
actions actions.ActionSet
|
||||
stateTable sv.StateVariableSet
|
||||
}
|
||||
|
||||
func NewService(name string) *Service {
|
||||
svc := &Service{
|
||||
name: name,
|
||||
identifier: name,
|
||||
controlURL: "/service/" + name + "/control",
|
||||
eventSubURL: "/service/" + name + "/event",
|
||||
scpdURL: "/service/" + name + "/desc.xml",
|
||||
version: 1,
|
||||
}
|
||||
|
||||
return svc
|
||||
}
|
||||
|
||||
func (svc *Service) Name() string {
|
||||
return svc.name
|
||||
}
|
||||
|
||||
func (svc *Service) TypeID() string {
|
||||
return "Service"
|
||||
}
|
||||
|
||||
func (svc *Service) ServiceType() string {
|
||||
return fmt.Sprintf("urn:schemas-upnp-org:service:%s:%d", svc.name, svc.version)
|
||||
}
|
||||
|
||||
func (svc *Service) ServiceId() string {
|
||||
return fmt.Sprintf("urn:upnp-org:serviceId:%s", svc.identifier)
|
||||
}
|
||||
|
||||
func (svc *Service) SetIdentifier(id string) {
|
||||
svc.identifier = id
|
||||
}
|
||||
|
||||
func (svc *Service) ControlURL() string {
|
||||
return svc.controlURL
|
||||
}
|
||||
|
||||
func (svc *Service) SetControlURL(url string) {
|
||||
svc.controlURL = url
|
||||
}
|
||||
|
||||
func (svc *Service) EventSubURL() string {
|
||||
return svc.eventSubURL
|
||||
}
|
||||
|
||||
func (svc *Service) SetEventSubURL(url string) {
|
||||
svc.eventSubURL = url
|
||||
}
|
||||
|
||||
func (svc *Service) SCPDURL() string {
|
||||
return svc.scpdURL
|
||||
}
|
||||
|
||||
func (svc *Service) SetSCPDURL(url string) {
|
||||
svc.scpdURL = url
|
||||
}
|
||||
|
||||
func (svc *Service) SetVersion(version int) error {
|
||||
if version < 1 {
|
||||
return fmt.Errorf("%s", "version must be greater than or equal to 1")
|
||||
}
|
||||
svc.version = version
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc *Service) Version() int {
|
||||
return svc.version
|
||||
}
|
||||
|
||||
func (svc *Service) AddVariable(sv *sv.StateVariable) {
|
||||
svc.stateTable.Insert(sv)
|
||||
}
|
||||
|
||||
func (svc *Service) ContaintsVariable(sv *sv.StateVariable) bool {
|
||||
return svc.stateTable.Contains(sv)
|
||||
}
|
||||
|
||||
func (svc *Service) Variables() iter.Seq[*sv.StateVariable] {
|
||||
return svc.stateTable.All()
|
||||
}
|
||||
|
||||
func (svc *Service) AddAction(ac *actions.Action) {
|
||||
}
|
||||
|
||||
func (svc *Service) ToXMLElement() *etree.Element {
|
||||
elem := etree.NewElement("service")
|
||||
|
||||
st := elem.CreateElement("serviceType")
|
||||
st.SetText(svc.ServiceType())
|
||||
|
||||
sid := elem.CreateElement("serviceId")
|
||||
sid.SetText(svc.ServiceId())
|
||||
|
||||
spcd := elem.CreateElement("SCPDURL")
|
||||
spcd.SetText(svc.SCPDURL())
|
||||
|
||||
ctrl := elem.CreateElement("controlURL")
|
||||
ctrl.SetText(svc.ControlURL())
|
||||
|
||||
event := elem.CreateElement("eventSubURL")
|
||||
event.SetText(svc.EventSubURL())
|
||||
|
||||
return elem
|
||||
}
|
||||
32
upnp/devices/services/serviceset.go
Normal file
32
upnp/devices/services/serviceset.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"iter"
|
||||
|
||||
"gargoton.petite-maison-orange.fr/eric/pmomusic/upnp/objectstore"
|
||||
"github.com/beevik/etree"
|
||||
)
|
||||
|
||||
type ServiceSet objectstore.ObjectSet[*Service]
|
||||
|
||||
func (m *ServiceSet) Insert(obj *Service) {
|
||||
(*objectstore.ObjectSet[*Service])(m).Insert(obj)
|
||||
}
|
||||
|
||||
func (set *ServiceSet) Contains(obj *Service) bool {
|
||||
return (*objectstore.ObjectSet[*Service])(set).Contains(obj)
|
||||
}
|
||||
|
||||
func (m *ServiceSet) All() iter.Seq[*Service] {
|
||||
return (*objectstore.ObjectSet[*Service])(m).All()
|
||||
}
|
||||
|
||||
func (m *ServiceSet) ToXMLElement() *etree.Element {
|
||||
elem := etree.NewElement("ServiceList")
|
||||
|
||||
for sv := range m.All() {
|
||||
elem.AddChild(sv.ToXMLElement())
|
||||
}
|
||||
|
||||
return elem
|
||||
}
|
||||
@@ -49,6 +49,10 @@ func (sv StateVariable) Name() string {
|
||||
return sv.name
|
||||
}
|
||||
|
||||
func (sv StateVariable) TypeID() string {
|
||||
return "StateVariable"
|
||||
}
|
||||
|
||||
// Type returns the UPnP data type of the state variable.
|
||||
func (state *StateVariable) Type() StateVarType {
|
||||
return state.valueType
|
||||
@@ -431,7 +435,6 @@ func (state *StateVariable) NewInstance() *StateVarInstance {
|
||||
func (sv *StateVariable) ToXMLElement() *etree.Element {
|
||||
// Create root <stateVariable> element
|
||||
elem := etree.NewElement("stateVariable")
|
||||
elem.CreateAttr("name", sv.name)
|
||||
|
||||
// Add sendEvents attribute (UPnP eventing capability)
|
||||
if sv.sendEvents {
|
||||
@@ -440,6 +443,9 @@ func (sv *StateVariable) ToXMLElement() *etree.Element {
|
||||
elem.CreateAttr("sendEvents", "no") // Disable event notifications
|
||||
}
|
||||
|
||||
name := elem.CreateElement("name")
|
||||
name.SetText(sv.Name())
|
||||
|
||||
// Add data type element
|
||||
dataType := elem.CreateElement("dataType")
|
||||
dataType.SetText(sv.valueType.String()) // Set UPnP type name (e.g., "ui1", "boolean")
|
||||
32
upnp/devices/services/statevariables/statevariableset.go
Normal file
32
upnp/devices/services/statevariables/statevariableset.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package statevariables
|
||||
|
||||
import (
|
||||
"iter"
|
||||
|
||||
"gargoton.petite-maison-orange.fr/eric/pmomusic/upnp/objectstore"
|
||||
"github.com/beevik/etree"
|
||||
)
|
||||
|
||||
type StateVariableSet objectstore.ObjectSet[*StateVariable]
|
||||
|
||||
func (m *StateVariableSet) Insert(obj *StateVariable) {
|
||||
(*objectstore.ObjectSet[*StateVariable])(m).Insert(obj)
|
||||
}
|
||||
|
||||
func (set *StateVariableSet) Contains(obj *StateVariable) bool {
|
||||
return (*objectstore.ObjectSet[*StateVariable])(set).Contains(obj)
|
||||
}
|
||||
|
||||
func (m *StateVariableSet) All() iter.Seq[*StateVariable] {
|
||||
return (*objectstore.ObjectSet[*StateVariable])(m).All()
|
||||
}
|
||||
|
||||
func (m *StateVariableSet) ToXMLElement() *etree.Element {
|
||||
elem := etree.NewElement("serviceStateTable")
|
||||
|
||||
for sv := range m.All() {
|
||||
elem.AddChild(sv.ToXMLElement())
|
||||
}
|
||||
|
||||
return elem
|
||||
}
|
||||
@@ -55,7 +55,7 @@ func toTime(v interface{}) (time.Time, error) {
|
||||
func parseUPnPTime(t StateVarType, s string) (time.Time, error) {
|
||||
s = strings.TrimSpace(s)
|
||||
|
||||
layouts := []string{}
|
||||
var layouts []string = nil
|
||||
|
||||
switch t {
|
||||
case StateType_Date:
|
||||
@@ -86,6 +86,7 @@ func parseUPnPTime(t StateVarType, s string) (time.Time, error) {
|
||||
return ts, nil
|
||||
}
|
||||
}
|
||||
|
||||
return time.Time{}, fmt.Errorf("invalid %v value: %q", t, s)
|
||||
}
|
||||
|
||||
69
upnp/objectstore/object.go
Normal file
69
upnp/objectstore/object.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package objectstore
|
||||
|
||||
import (
|
||||
"iter"
|
||||
|
||||
"github.com/google/uuid"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type ObjectIdSet map[uuid.UUID]struct{}
|
||||
|
||||
func (set ObjectIdSet) Contains(id uuid.UUID) bool {
|
||||
_, ok := set[id]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (set ObjectIdSet) Add(id uuid.UUID) {
|
||||
set[id] = struct{}{}
|
||||
}
|
||||
|
||||
func (set ObjectIdSet) Remove(id uuid.UUID) {
|
||||
delete(set, id)
|
||||
}
|
||||
|
||||
func (set ObjectIdSet) Clear() {
|
||||
for k := range set {
|
||||
delete(set, k)
|
||||
}
|
||||
}
|
||||
|
||||
func (set ObjectIdSet) Len() int {
|
||||
return len(set)
|
||||
}
|
||||
|
||||
func (set ObjectIdSet) All() iter.Seq[uuid.UUID] {
|
||||
return func(yield func(uuid.UUID) bool) {
|
||||
for uuid := range set {
|
||||
if !yield(uuid) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var objectstore = make(map[uuid.UUID]Object)
|
||||
|
||||
func RegisterObject(o Object) uuid.UUID {
|
||||
id := uuid.New()
|
||||
objectstore[id] = o
|
||||
|
||||
return id
|
||||
}
|
||||
|
||||
func GetObject(id uuid.UUID) (Object, bool) {
|
||||
o, ok := objectstore[id]
|
||||
return o, ok
|
||||
}
|
||||
|
||||
func RemoveObject(id uuid.UUID) {
|
||||
if _, ok := objectstore[id]; !ok {
|
||||
delete(objectstore, id)
|
||||
return
|
||||
}
|
||||
log.Warnf("Object %s not found in objectstore", id)
|
||||
}
|
||||
|
||||
func CountOfStoredObjects() int {
|
||||
return len(objectstore)
|
||||
}
|
||||
29
upnp/objectstore/objectset.go
Normal file
29
upnp/objectstore/objectset.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package objectstore
|
||||
|
||||
import "iter"
|
||||
|
||||
type Object interface {
|
||||
Name() string
|
||||
TypeID() string
|
||||
}
|
||||
|
||||
type ObjectSet[T Object] map[string]T
|
||||
|
||||
func (m *ObjectSet[T]) Insert(obj T) {
|
||||
(*m)[obj.Name()] = obj
|
||||
}
|
||||
|
||||
func (set *ObjectSet[T]) Contains(obj T) bool {
|
||||
_, ok := (*set)[obj.Name()]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (m *ObjectSet[T]) All() iter.Seq[T] {
|
||||
return func(yield func(T) bool) {
|
||||
for _, sv := range *m {
|
||||
if !yield(sv) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user