2022-06-22 20:51:25 +01:00
|
|
|
package voicemeeter
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2022-09-29 18:02:11 +01:00
|
|
|
"os"
|
2022-09-14 16:05:15 +01:00
|
|
|
"time"
|
2022-09-29 18:02:11 +01:00
|
|
|
|
|
|
|
log "github.com/sirupsen/logrus"
|
2022-06-22 20:51:25 +01:00
|
|
|
)
|
|
|
|
|
2022-10-10 18:51:30 +01:00
|
|
|
// Remote represents the API for a kind
|
2022-07-09 19:01:58 +01:00
|
|
|
type Remote struct {
|
2022-07-18 16:23:15 +01:00
|
|
|
Kind *kind
|
2022-07-10 23:08:14 +01:00
|
|
|
Strip []iStrip
|
|
|
|
Bus []iBus
|
2022-06-28 14:34:03 +01:00
|
|
|
Button []button
|
|
|
|
Command *command
|
|
|
|
Vban *vban
|
2022-06-28 16:29:13 +01:00
|
|
|
Device *device
|
2022-06-28 14:34:03 +01:00
|
|
|
Recorder *recorder
|
2022-08-22 22:33:22 +01:00
|
|
|
Midi *midi_t
|
2022-06-25 20:11:15 +01:00
|
|
|
|
2022-06-26 01:41:05 +01:00
|
|
|
pooler *pooler
|
2022-06-22 20:51:25 +01:00
|
|
|
}
|
|
|
|
|
2022-06-26 01:36:32 +01:00
|
|
|
// String implements the fmt.stringer interface
|
2022-07-09 19:01:58 +01:00
|
|
|
func (r *Remote) String() string {
|
2022-07-18 16:23:15 +01:00
|
|
|
return fmt.Sprintf("Voicemeeter %s", r.Kind)
|
2022-06-22 20:51:25 +01:00
|
|
|
}
|
|
|
|
|
2022-06-26 01:36:32 +01:00
|
|
|
// Login logs into the API
|
|
|
|
// then it intializes the pooler
|
2022-09-07 20:59:55 +01:00
|
|
|
func (r *Remote) Login() error {
|
|
|
|
err := login(r.Kind.Name)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-12-08 10:50:00 +00:00
|
|
|
r.InitPooler()
|
2022-09-07 20:59:55 +01:00
|
|
|
return nil
|
2022-06-22 20:51:25 +01:00
|
|
|
}
|
|
|
|
|
2022-06-26 01:36:32 +01:00
|
|
|
// Logout logs out of the API
|
|
|
|
// it also terminates the pooler
|
2022-09-07 20:59:55 +01:00
|
|
|
func (r *Remote) Logout() error {
|
2022-06-26 01:41:05 +01:00
|
|
|
r.pooler.run = false
|
2022-09-07 20:59:55 +01:00
|
|
|
err := logout(r.Kind.Name)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
2022-06-22 20:51:25 +01:00
|
|
|
}
|
|
|
|
|
2022-12-08 10:50:00 +00:00
|
|
|
// InitPooler initiates the Pooler
|
|
|
|
func (r *Remote) InitPooler() {
|
|
|
|
r.pooler = newPooler(r.Kind)
|
|
|
|
}
|
|
|
|
|
2022-12-15 00:00:20 +00:00
|
|
|
// Run launches the Voicemeeter GUI for a kind.
|
|
|
|
func (r *Remote) Run(kindId string) error {
|
|
|
|
err := runVoicemeeter(kindId)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
clear()
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-07-10 23:35:56 +01:00
|
|
|
// Type returns the type of Voicemeeter (basic, banana, potato)
|
2022-07-09 19:01:58 +01:00
|
|
|
func (r *Remote) Type() string {
|
2022-09-07 20:59:55 +01:00
|
|
|
val, err := getVMType()
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err)
|
|
|
|
}
|
|
|
|
return val
|
2022-06-22 20:51:25 +01:00
|
|
|
}
|
|
|
|
|
2022-07-10 23:35:56 +01:00
|
|
|
// Version returns the version of Voicemeeter as a string
|
2022-07-09 19:01:58 +01:00
|
|
|
func (r *Remote) Version() string {
|
2022-09-07 20:59:55 +01:00
|
|
|
val, err := getVersion()
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println(err)
|
|
|
|
}
|
|
|
|
return val
|
2022-06-22 20:51:25 +01:00
|
|
|
}
|
|
|
|
|
2022-06-30 23:08:35 +01:00
|
|
|
// Pdirty returns true iff a parameter value has changed
|
2022-12-08 10:50:00 +00:00
|
|
|
func (r *Remote) Pdirty() (bool, error) {
|
|
|
|
pdirty, err := pdirty()
|
|
|
|
return pdirty, err
|
2022-06-30 23:08:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Mdirty returns true iff a macrobutton value has changed
|
2022-12-08 10:50:00 +00:00
|
|
|
func (r *Remote) Mdirty() (bool, error) {
|
|
|
|
mdirty, err := mdirty()
|
|
|
|
return mdirty, err
|
2022-06-30 23:08:35 +01:00
|
|
|
}
|
|
|
|
|
2022-09-14 00:58:05 +01:00
|
|
|
// Sync is a helper method that waits for dirty parameters to clear
|
|
|
|
func (r *Remote) Sync() {
|
2022-09-14 16:05:15 +01:00
|
|
|
time.Sleep(time.Duration(vmdelay) * time.Millisecond)
|
2022-12-08 10:50:00 +00:00
|
|
|
clear()
|
2022-09-14 00:58:05 +01:00
|
|
|
}
|
|
|
|
|
2022-10-10 18:51:30 +01:00
|
|
|
// GetFloat gets a float parameter value
|
2022-09-18 05:35:04 +01:00
|
|
|
func (r *Remote) GetFloat(name string) (float64, error) {
|
2022-09-07 20:59:55 +01:00
|
|
|
val, err := getParameterFloat(name)
|
|
|
|
if err != nil {
|
2022-09-18 05:35:04 +01:00
|
|
|
return 0, err
|
2022-09-07 20:59:55 +01:00
|
|
|
}
|
2022-09-18 05:35:04 +01:00
|
|
|
return val, nil
|
2022-08-22 22:33:22 +01:00
|
|
|
}
|
|
|
|
|
2022-10-10 18:51:30 +01:00
|
|
|
// SetFloat sets a float paramter value
|
2022-09-18 05:35:04 +01:00
|
|
|
func (r *Remote) SetFloat(name string, value float64) error {
|
|
|
|
err := setParameterFloat(name, value)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
2022-08-22 22:33:22 +01:00
|
|
|
}
|
|
|
|
|
2022-10-10 18:51:30 +01:00
|
|
|
// GetString gets a string parameter value
|
2022-09-18 05:35:04 +01:00
|
|
|
func (r *Remote) GetString(name string) (string, error) {
|
2022-09-07 20:59:55 +01:00
|
|
|
val, err := getParameterString(name)
|
|
|
|
if err != nil {
|
2022-09-18 05:35:04 +01:00
|
|
|
return "", err
|
2022-09-07 20:59:55 +01:00
|
|
|
}
|
2022-09-18 05:35:04 +01:00
|
|
|
return val, nil
|
2022-08-22 22:33:22 +01:00
|
|
|
}
|
|
|
|
|
2022-10-10 18:51:30 +01:00
|
|
|
// SetString sets a string parameter value
|
2022-09-18 05:35:04 +01:00
|
|
|
func (r *Remote) SetString(name, value string) error {
|
|
|
|
err := setParameterString(name, value)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
2022-08-22 22:33:22 +01:00
|
|
|
}
|
|
|
|
|
2022-07-10 23:35:56 +01:00
|
|
|
// SendText sets multiple parameters by script
|
2022-09-18 05:35:04 +01:00
|
|
|
func (r *Remote) SendText(script string) error {
|
|
|
|
err := setParametersMulti(script)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
2022-06-22 20:51:25 +01:00
|
|
|
}
|
|
|
|
|
2022-06-26 01:36:32 +01:00
|
|
|
// Register forwards the register method to Pooler
|
2022-12-08 10:50:00 +00:00
|
|
|
func (r *Remote) Register(channel chan string) {
|
|
|
|
r.pooler.Register(channel)
|
2022-06-26 01:36:32 +01:00
|
|
|
}
|
|
|
|
|
2022-10-10 18:51:30 +01:00
|
|
|
// EventAdd adds events to the Pooler
|
|
|
|
func (r *Remote) EventAdd(events ...string) {
|
|
|
|
r.pooler.event.Add(events...)
|
2022-08-22 22:33:22 +01:00
|
|
|
}
|
|
|
|
|
2022-10-10 18:51:30 +01:00
|
|
|
// EventRemove removes events from the Pooler
|
|
|
|
func (r *Remote) EventRemove(events ...string) {
|
|
|
|
r.pooler.event.Remove(events...)
|
2022-08-22 22:33:22 +01:00
|
|
|
}
|
|
|
|
|
2022-07-10 23:35:56 +01:00
|
|
|
// remoteBuilder defines the interface builder types must satisfy
|
2022-06-25 16:22:16 +01:00
|
|
|
type remoteBuilder interface {
|
|
|
|
setKind() remoteBuilder
|
|
|
|
makeStrip() remoteBuilder
|
|
|
|
makeBus() remoteBuilder
|
|
|
|
makeButton() remoteBuilder
|
|
|
|
makeCommand() remoteBuilder
|
|
|
|
makeVban() remoteBuilder
|
2022-06-28 16:29:13 +01:00
|
|
|
makeDevice() remoteBuilder
|
2022-06-28 14:34:03 +01:00
|
|
|
makeRecorder() remoteBuilder
|
2022-08-22 22:33:22 +01:00
|
|
|
makeMidi() remoteBuilder
|
2022-06-28 14:34:03 +01:00
|
|
|
Build() remoteBuilder
|
2022-07-09 19:01:58 +01:00
|
|
|
Get() *Remote
|
2022-06-25 16:22:16 +01:00
|
|
|
}
|
|
|
|
|
2022-10-10 18:51:30 +01:00
|
|
|
// director is responsible for directing the genericBuilder
|
2022-06-25 16:22:16 +01:00
|
|
|
type director struct {
|
|
|
|
builder remoteBuilder
|
|
|
|
}
|
|
|
|
|
2022-06-26 01:36:32 +01:00
|
|
|
// SetBuilder sets the appropriate builder type for a kind
|
2022-06-25 16:22:16 +01:00
|
|
|
func (d *director) SetBuilder(b remoteBuilder) {
|
|
|
|
d.builder = b
|
|
|
|
}
|
2022-06-22 20:51:25 +01:00
|
|
|
|
2022-06-28 14:34:03 +01:00
|
|
|
// Construct calls the build function for the specific builder
|
2022-06-25 16:22:16 +01:00
|
|
|
func (d *director) Construct() {
|
2022-06-28 14:34:03 +01:00
|
|
|
d.builder.Build()
|
2022-06-25 16:22:16 +01:00
|
|
|
}
|
|
|
|
|
2022-06-26 01:36:32 +01:00
|
|
|
// Get forwards the Get method to the builder
|
2022-07-09 19:01:58 +01:00
|
|
|
func (d *director) Get() *Remote {
|
2022-06-25 16:22:16 +01:00
|
|
|
return d.builder.Get()
|
|
|
|
}
|
|
|
|
|
2022-07-10 23:35:56 +01:00
|
|
|
// genericBuilder represents a generic builder type
|
2022-06-25 16:22:16 +01:00
|
|
|
type genericBuilder struct {
|
|
|
|
k *kind
|
2022-07-09 19:01:58 +01:00
|
|
|
r Remote
|
2022-06-25 16:22:16 +01:00
|
|
|
}
|
|
|
|
|
2022-07-10 23:35:56 +01:00
|
|
|
// setKind sets the kind for a builder of a kind
|
2022-06-25 16:22:16 +01:00
|
|
|
func (b *genericBuilder) setKind() remoteBuilder {
|
2022-07-18 16:23:15 +01:00
|
|
|
b.r.Kind = b.k
|
2022-06-25 16:22:16 +01:00
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
2022-06-26 01:36:32 +01:00
|
|
|
// makeStrip makes a strip slice and assigns it to remote.Strip
|
2022-07-10 23:08:14 +01:00
|
|
|
// []iStrip comprises of both physical and virtual strip types
|
2022-06-25 16:22:16 +01:00
|
|
|
func (b *genericBuilder) makeStrip() remoteBuilder {
|
2022-09-29 18:02:11 +01:00
|
|
|
log.Info("building strip")
|
2022-12-08 19:45:02 +00:00
|
|
|
strip := make([]iStrip, b.k.NumStrip())
|
2022-07-18 16:23:15 +01:00
|
|
|
for i := 0; i < b.k.NumStrip(); i++ {
|
|
|
|
if i < b.k.PhysIn {
|
2022-12-08 19:45:02 +00:00
|
|
|
strip[i] = newPhysicalStrip(i, b.k)
|
2022-06-23 10:42:11 +01:00
|
|
|
} else {
|
2022-12-08 19:45:02 +00:00
|
|
|
strip[i] = newVirtualStrip(i, b.k)
|
2022-06-23 10:42:11 +01:00
|
|
|
}
|
2022-06-22 20:51:25 +01:00
|
|
|
}
|
2022-12-08 19:45:02 +00:00
|
|
|
b.r.Strip = strip
|
2022-06-25 16:22:16 +01:00
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
2022-06-26 01:36:32 +01:00
|
|
|
// makeBus makes a bus slice and assigns it to remote.Bus
|
|
|
|
// []t_bus comprises of both physical and virtual bus types
|
2022-06-25 16:22:16 +01:00
|
|
|
func (b *genericBuilder) makeBus() remoteBuilder {
|
2022-09-29 18:02:11 +01:00
|
|
|
log.Info("building bus")
|
2022-12-08 19:45:02 +00:00
|
|
|
bus := make([]iBus, b.k.NumBus())
|
2022-07-18 16:23:15 +01:00
|
|
|
for i := 0; i < b.k.NumBus(); i++ {
|
|
|
|
if i < b.k.PhysOut {
|
2022-12-08 19:45:02 +00:00
|
|
|
bus[i] = newPhysicalBus(i, b.k)
|
2022-06-23 10:42:11 +01:00
|
|
|
} else {
|
2022-12-08 19:45:02 +00:00
|
|
|
bus[i] = newVirtualBus(i, b.k)
|
2022-06-23 10:42:11 +01:00
|
|
|
}
|
2022-06-22 20:51:25 +01:00
|
|
|
}
|
2022-12-08 19:45:02 +00:00
|
|
|
b.r.Bus = bus
|
2022-06-25 16:22:16 +01:00
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
2022-06-26 01:36:32 +01:00
|
|
|
// makeButton makes a button slice and assigns it to remote.Button
|
2022-06-25 16:22:16 +01:00
|
|
|
func (b *genericBuilder) makeButton() remoteBuilder {
|
2022-09-29 18:02:11 +01:00
|
|
|
log.Info("building button")
|
2022-12-08 19:45:02 +00:00
|
|
|
button := make([]button, 80)
|
2022-06-22 20:51:25 +01:00
|
|
|
for i := 0; i < 80; i++ {
|
2022-12-08 19:45:02 +00:00
|
|
|
button[i] = newButton(i)
|
2022-06-22 20:51:25 +01:00
|
|
|
}
|
2022-12-08 19:45:02 +00:00
|
|
|
b.r.Button = button
|
2022-06-25 16:22:16 +01:00
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
2022-07-09 19:01:58 +01:00
|
|
|
// makeCommand makes a command type and assigns it to remote.Command
|
2022-06-25 16:22:16 +01:00
|
|
|
func (b *genericBuilder) makeCommand() remoteBuilder {
|
2022-09-29 18:02:11 +01:00
|
|
|
log.Info("building command")
|
2022-06-25 20:11:15 +01:00
|
|
|
b.r.Command = newCommand()
|
2022-06-25 16:22:16 +01:00
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
2022-07-09 19:01:58 +01:00
|
|
|
// makeVban makes a vban type and assigns it to remote.Vban
|
2022-06-25 16:22:16 +01:00
|
|
|
func (b *genericBuilder) makeVban() remoteBuilder {
|
2022-09-29 18:02:11 +01:00
|
|
|
log.Info("building vban")
|
2022-06-25 20:11:15 +01:00
|
|
|
b.r.Vban = newVban(b.k)
|
2022-06-25 16:22:16 +01:00
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
2022-07-09 19:01:58 +01:00
|
|
|
// makeDevice makes a device type and assigns it to remote.Device
|
2022-06-28 16:29:13 +01:00
|
|
|
func (b *genericBuilder) makeDevice() remoteBuilder {
|
2022-09-29 18:02:11 +01:00
|
|
|
log.Info("building device")
|
2022-06-28 16:29:13 +01:00
|
|
|
b.r.Device = newDevice()
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
2022-07-09 19:01:58 +01:00
|
|
|
// makeRecorder makes a recorder type and assigns it to remote.Recorder
|
2022-06-28 14:34:03 +01:00
|
|
|
func (b *genericBuilder) makeRecorder() remoteBuilder {
|
2022-09-29 18:02:11 +01:00
|
|
|
log.Info("building recorder")
|
2022-06-28 14:34:03 +01:00
|
|
|
b.r.Recorder = newRecorder()
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
2022-08-22 22:33:22 +01:00
|
|
|
// makeMidi makes a midi type and assigns it to remote.Midi
|
|
|
|
func (b *genericBuilder) makeMidi() remoteBuilder {
|
2022-09-29 18:02:11 +01:00
|
|
|
log.Info("building midi")
|
2022-08-22 22:33:22 +01:00
|
|
|
b.r.Midi = newMidi()
|
|
|
|
return b
|
|
|
|
}
|
|
|
|
|
2022-06-26 01:36:32 +01:00
|
|
|
// Get returns a fully constructed remote type for a kind
|
2022-07-09 19:01:58 +01:00
|
|
|
func (b *genericBuilder) Get() *Remote {
|
2022-06-25 16:22:16 +01:00
|
|
|
return &b.r
|
|
|
|
}
|
|
|
|
|
2022-07-10 23:35:56 +01:00
|
|
|
// basicBuilder represents a builder specific to basic type
|
2022-06-25 16:22:16 +01:00
|
|
|
type basicBuilder struct {
|
|
|
|
genericBuilder
|
|
|
|
}
|
|
|
|
|
2022-06-28 14:34:03 +01:00
|
|
|
// Build defines the steps required to build a basic type
|
|
|
|
func (basb *genericBuilder) Build() remoteBuilder {
|
2022-08-22 22:33:22 +01:00
|
|
|
return basb.setKind().
|
|
|
|
makeStrip().
|
|
|
|
makeBus().
|
|
|
|
makeButton().
|
|
|
|
makeCommand().
|
|
|
|
makeVban().
|
|
|
|
makeDevice().
|
|
|
|
makeMidi()
|
2022-06-28 14:34:03 +01:00
|
|
|
}
|
|
|
|
|
2022-07-10 23:35:56 +01:00
|
|
|
// bananaBuilder represents a builder specific to banana type
|
2022-06-25 16:22:16 +01:00
|
|
|
type bananaBuilder struct {
|
|
|
|
genericBuilder
|
|
|
|
}
|
|
|
|
|
2022-06-28 14:34:03 +01:00
|
|
|
// Build defines the steps required to build a banana type
|
|
|
|
func (banb *bananaBuilder) Build() remoteBuilder {
|
2022-08-22 22:33:22 +01:00
|
|
|
return banb.setKind().
|
|
|
|
makeStrip().
|
|
|
|
makeBus().
|
|
|
|
makeButton().
|
|
|
|
makeCommand().
|
|
|
|
makeVban().
|
|
|
|
makeDevice().
|
|
|
|
makeRecorder().
|
|
|
|
makeMidi()
|
2022-06-28 14:34:03 +01:00
|
|
|
}
|
|
|
|
|
2022-07-10 23:35:56 +01:00
|
|
|
// potatoBuilder represents a builder specific to potato type
|
2022-06-25 16:22:16 +01:00
|
|
|
type potatoBuilder struct {
|
|
|
|
genericBuilder
|
|
|
|
}
|
|
|
|
|
2022-06-28 14:34:03 +01:00
|
|
|
// Build defines the steps required to build a potato type
|
|
|
|
func (potb *potatoBuilder) Build() remoteBuilder {
|
2022-08-22 22:33:22 +01:00
|
|
|
return potb.setKind().
|
|
|
|
makeStrip().
|
|
|
|
makeBus().
|
|
|
|
makeButton().
|
|
|
|
makeCommand().
|
|
|
|
makeVban().
|
|
|
|
makeDevice().
|
|
|
|
makeRecorder().
|
|
|
|
makeMidi()
|
2022-06-28 14:34:03 +01:00
|
|
|
}
|
|
|
|
|
2022-09-14 16:05:15 +01:00
|
|
|
var (
|
|
|
|
vmsync bool
|
|
|
|
vmdelay int
|
|
|
|
)
|
|
|
|
|
2022-09-29 18:02:11 +01:00
|
|
|
func init() {
|
|
|
|
log.SetOutput(os.Stdout)
|
|
|
|
log.SetLevel(log.WarnLevel)
|
|
|
|
}
|
|
|
|
|
2022-07-10 23:08:14 +01:00
|
|
|
// NewRemote returns a Remote type for a kind
|
2022-06-26 01:36:32 +01:00
|
|
|
// this is the interface entry point
|
2022-09-14 16:05:15 +01:00
|
|
|
func NewRemote(kindId string, delay int) (*Remote, error) {
|
2022-12-08 10:50:00 +00:00
|
|
|
kind, ok := kindMap[kindId]
|
2022-06-25 16:22:16 +01:00
|
|
|
if !ok {
|
|
|
|
err := fmt.Errorf("unknown Voicemeeter kind '%s'", kindId)
|
2022-08-23 03:16:43 +01:00
|
|
|
return nil, err
|
2022-06-25 16:22:16 +01:00
|
|
|
}
|
2022-09-14 16:05:15 +01:00
|
|
|
if delay < 0 {
|
|
|
|
err := fmt.Errorf("invalid delay value. should be >= 0")
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
vmsync = delay > 0
|
|
|
|
vmdelay = delay
|
2022-06-25 16:22:16 +01:00
|
|
|
|
|
|
|
director := director{}
|
2022-12-08 10:50:00 +00:00
|
|
|
switch kind.Name {
|
2022-06-25 16:22:16 +01:00
|
|
|
case "basic":
|
2022-12-08 10:50:00 +00:00
|
|
|
director.SetBuilder(&basicBuilder{genericBuilder{kind, Remote{}}})
|
2022-06-25 16:22:16 +01:00
|
|
|
case "banana":
|
2022-12-08 10:50:00 +00:00
|
|
|
director.SetBuilder(&bananaBuilder{genericBuilder{kind, Remote{}}})
|
2022-06-25 16:22:16 +01:00
|
|
|
case "potato":
|
2022-12-08 10:50:00 +00:00
|
|
|
director.SetBuilder(&potatoBuilder{genericBuilder{kind, Remote{}}})
|
2022-06-22 20:51:25 +01:00
|
|
|
}
|
2022-06-25 16:22:16 +01:00
|
|
|
director.Construct()
|
2022-08-23 03:16:43 +01:00
|
|
|
return director.Get(), nil
|
2022-06-22 20:51:25 +01:00
|
|
|
}
|