func (s *Players) Get(key string) Player {
	s.RLock()
	defer s.RUnlock()
	return s.m[key]
}
Get the Player identified by the key.
package player
import (
	"encoding/json"
	"fmt"
	"sync"
)
type Action string
const (
	ActionPlay            Action = "play"
	ActionPause                  = "pause"
	ActionNext                   = "next"
	ActionPrev                   = "prev"
	ActionTogglePlayPause        = "togglePlayPause"
	ActionToggleRepeat           = "toggleRepeat"
	ActionToggleMute             = "toggleMute"
)
const (
	ActionSetVolume Action = "setVolume"
	ActionSetMute          = "setMute"
	ActionSetRepeat        = "setRepeat"
	ActionSetTime          = "setTime"
)
type Player interface {
	Key() string
	Do(a Action) error
	SetMute(bool) error
	SetRepeat(bool) error
	SetVolume(float64) error
	SetTime(float64) error
}
type multi struct {
	key     string
	players []Player
}
func Multi(key string, players ...Player) Player {
	return multi{
		key:     key,
		players: players,
	}
}
type setFloatFn func(Player, float64) error
type setBoolFn func(Player, bool) error
func (m multi) applySetFloatFn(fn setFloatFn, f float64) error {
	for _, p := range m.players {
		err := fn(p, f)
		if err != nil {
			return err
		}
	}
	return nil
}
func (m multi) applySetBoolFn(fn setBoolFn, v bool) error {
	for _, p := range m.players {
		err := fn(p, v)
		if err != nil {
			return err
		}
	}
	return nil
}
func (m multi) Key() string { return m.key }
func (m multi) Do(a Action) error {
	for _, p := range m.players {
		err := p.Do(a)
		if err != nil {
			return err
		}
	}
	return nil
}
func (m multi) SetVolume(f float64) error { return m.applySetFloatFn(Player.SetVolume, f) }
func (m multi) SetTime(f float64) error   { return m.applySetFloatFn(Player.SetTime, f) }
func (m multi) SetMute(v bool) error      { return m.applySetBoolFn(Player.SetMute, v) }
func (m multi) SetRepeat(v bool) error    { return m.applySetBoolFn(Player.SetRepeat, v) }
func (m multi) MarshalJSON() ([]byte, error) {
	playerKeys := make([]string, len(m.players))
	for i, p := range m.players {
		playerKeys[i] = p.Key()
	}
	rep := struct {
		Key        string   `json:"key"`
		PlayerKeys []string `json:"playerKeys"`
	}{
		m.key,
		playerKeys,
	}
	return json.Marshal(rep)
}
func Validated(p Player) Player {
	return validated{
		Player: p,
	}
}
type validated struct {
	Player
}
type InvalidValueError string
func (v InvalidValueError) Error() string { return string(v) }
func (v validated) SetVolume(f float64) error {
	if f < 0.0 || f > 1.0 {
		return InvalidValueError(fmt.Sprintf("invalid volume value '%v': must be between 0.0 and 1.0", f))
	}
	return v.Player.SetVolume(f)
}
func (v validated) SetTime(f float64) error {
	if f < 0.0 {
		return InvalidValueError(fmt.Sprintf("invalid time value '%v': must be greater than 0.0", f))
	}
	return v.Player.SetTime(f)
}
func (v validated) MarshalJSON() ([]byte, error) {
	if m, ok := v.Player.(json.Marshaler); ok {
		return m.MarshalJSON()
	}
	return nil, nil
}
type Players struct {
	sync.RWMutex
	m map[string]Player
}
func NewPlayers() *Players {
	return &Players{m: make(map[string]Player)}
}
func (s *Players) Add(p Player) {
	s.Lock()
	defer s.Unlock()
	s.m[p.Key()] = p
}
func (s *Players) Remove(key string) {
	s.Lock()
	defer s.Unlock()
	delete(s.m, key)
}