2023-02-17 10:38:45 +01:00
|
|
|
package cast
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"forge.cadoles.com/arcad/edge/pkg/app"
|
|
|
|
"forge.cadoles.com/arcad/edge/pkg/module"
|
|
|
|
"github.com/dop251/goja"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"gitlab.com/wpetit/goweb/logger"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
defaultTimeout = 30 * time.Second
|
|
|
|
)
|
|
|
|
|
|
|
|
type Module struct {
|
|
|
|
ctx context.Context
|
|
|
|
server *app.Server
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *Module) Name() string {
|
|
|
|
return "cast"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *Module) Export(export *goja.Object) {
|
|
|
|
if err := export.Set("refreshDevices", m.refreshDevices); err != nil {
|
|
|
|
panic(errors.Wrap(err, "could not set 'refreshDevices' function"))
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := export.Set("getDevices", m.getDevices); err != nil {
|
|
|
|
panic(errors.Wrap(err, "could not set 'getDevices' function"))
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := export.Set("loadUrl", m.loadUrl); err != nil {
|
|
|
|
panic(errors.Wrap(err, "could not set 'loadUrl' function"))
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := export.Set("stopCast", m.stopCast); err != nil {
|
|
|
|
panic(errors.Wrap(err, "could not set 'stopCast' function"))
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := export.Set("getStatus", m.getStatus); err != nil {
|
|
|
|
panic(errors.Wrap(err, "could not set 'getStatus' function"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *Module) refreshDevices(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
|
|
|
|
rawTimeout := call.Argument(0).String()
|
|
|
|
|
|
|
|
timeout, err := m.parseTimeout(rawTimeout)
|
|
|
|
if err != nil {
|
2023-02-24 14:40:28 +01:00
|
|
|
panic(rt.ToValue(errors.WithStack(err)))
|
2023-02-17 10:38:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
promise := m.server.NewPromise()
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
|
|
|
defer cancel()
|
|
|
|
|
2023-04-20 19:20:52 +02:00
|
|
|
devices, err := ListDevices(ctx, true)
|
|
|
|
if err != nil {
|
2023-02-17 10:38:45 +01:00
|
|
|
err = errors.WithStack(err)
|
|
|
|
logger.Error(ctx, "error refreshing casting devices list", logger.E(errors.WithStack(err)))
|
|
|
|
|
|
|
|
promise.Reject(err)
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-04-20 19:20:52 +02:00
|
|
|
promise.Resolve(devices)
|
2023-02-17 10:38:45 +01:00
|
|
|
}()
|
|
|
|
|
|
|
|
return rt.ToValue(promise)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *Module) getDevices(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
|
2023-04-20 19:20:52 +02:00
|
|
|
ctx := context.Background()
|
2023-02-17 10:38:45 +01:00
|
|
|
|
2023-04-20 19:20:52 +02:00
|
|
|
devices, err := ListDevices(ctx, false)
|
|
|
|
if err != nil {
|
|
|
|
panic(rt.ToValue(errors.WithStack(err)))
|
|
|
|
}
|
2023-02-17 10:38:45 +01:00
|
|
|
|
|
|
|
return rt.ToValue(devices)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *Module) loadUrl(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
|
|
|
|
if len(call.Arguments) < 2 {
|
2023-02-24 14:40:28 +01:00
|
|
|
panic(rt.ToValue(errors.WithStack(module.ErrUnexpectedArgumentsNumber)))
|
2023-02-17 10:38:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
deviceUUID := call.Argument(0).String()
|
|
|
|
url := call.Argument(1).String()
|
|
|
|
|
|
|
|
rawTimeout := call.Argument(2).String()
|
|
|
|
|
|
|
|
timeout, err := m.parseTimeout(rawTimeout)
|
|
|
|
if err != nil {
|
2023-02-24 14:40:28 +01:00
|
|
|
panic(rt.ToValue(errors.WithStack(err)))
|
2023-02-17 10:38:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
promise := m.server.NewPromise()
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
|
|
|
defer cancel()
|
|
|
|
|
2023-04-05 15:12:51 +02:00
|
|
|
err := LoadURL(ctx, deviceUUID, url)
|
2023-02-17 10:38:45 +01:00
|
|
|
if err != nil {
|
|
|
|
err = errors.WithStack(err)
|
|
|
|
logger.Error(ctx, "error while casting url", logger.E(err))
|
|
|
|
|
|
|
|
promise.Reject(err)
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
promise.Resolve(nil)
|
|
|
|
}()
|
|
|
|
|
|
|
|
return m.server.ToValue(promise)
|
|
|
|
}
|
|
|
|
|
2023-02-24 14:40:28 +01:00
|
|
|
func (m *Module) stopCast(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
|
2023-02-17 10:38:45 +01:00
|
|
|
if len(call.Arguments) < 1 {
|
2023-02-24 14:40:28 +01:00
|
|
|
panic(rt.ToValue(errors.WithStack(module.ErrUnexpectedArgumentsNumber)))
|
2023-02-17 10:38:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
deviceUUID := call.Argument(0).String()
|
|
|
|
rawTimeout := call.Argument(1).String()
|
|
|
|
|
|
|
|
timeout, err := m.parseTimeout(rawTimeout)
|
|
|
|
if err != nil {
|
2023-02-24 14:40:28 +01:00
|
|
|
panic(rt.ToValue(errors.WithStack(err)))
|
2023-02-17 10:38:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
promise := m.server.NewPromise()
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
|
|
|
defer cancel()
|
|
|
|
|
2023-04-05 15:12:51 +02:00
|
|
|
err := StopCast(ctx, deviceUUID)
|
2023-02-17 10:38:45 +01:00
|
|
|
if err != nil {
|
|
|
|
err = errors.WithStack(err)
|
|
|
|
logger.Error(ctx, "error while quitting casting device app", logger.E(errors.WithStack(err)))
|
|
|
|
|
|
|
|
promise.Reject(err)
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
promise.Resolve(nil)
|
|
|
|
}()
|
|
|
|
|
|
|
|
return m.server.ToValue(promise)
|
|
|
|
}
|
|
|
|
|
2023-02-24 14:40:28 +01:00
|
|
|
func (m *Module) getStatus(call goja.FunctionCall, rt *goja.Runtime) goja.Value {
|
2023-02-17 10:38:45 +01:00
|
|
|
if len(call.Arguments) < 1 {
|
2023-02-24 14:40:28 +01:00
|
|
|
panic(rt.ToValue(errors.WithStack(module.ErrUnexpectedArgumentsNumber)))
|
2023-02-17 10:38:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
deviceUUID := call.Argument(0).String()
|
|
|
|
rawTimeout := call.Argument(1).String()
|
|
|
|
|
|
|
|
timeout, err := m.parseTimeout(rawTimeout)
|
|
|
|
if err != nil {
|
2023-02-24 14:40:28 +01:00
|
|
|
panic(rt.ToValue(errors.WithStack(err)))
|
2023-02-17 10:38:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
promise := m.server.NewPromise()
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
status, err := getStatus(ctx, deviceUUID)
|
|
|
|
if err != nil {
|
|
|
|
err = errors.WithStack(err)
|
|
|
|
logger.Error(ctx, "error while getting casting device status", logger.E(err))
|
|
|
|
|
|
|
|
promise.Reject(err)
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
promise.Resolve(status)
|
|
|
|
}()
|
|
|
|
|
|
|
|
return m.server.ToValue(promise)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *Module) parseTimeout(rawTimeout string) (time.Duration, error) {
|
|
|
|
var (
|
|
|
|
timeout time.Duration
|
|
|
|
err error
|
|
|
|
)
|
|
|
|
|
|
|
|
if rawTimeout == "undefined" {
|
|
|
|
timeout = defaultTimeout
|
|
|
|
} else {
|
|
|
|
timeout, err = time.ParseDuration(rawTimeout)
|
|
|
|
if err != nil {
|
|
|
|
return defaultTimeout, errors.Wrapf(err, "invalid duration format '%s'", rawTimeout)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return timeout, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func CastModuleFactory() app.ServerModuleFactory {
|
|
|
|
return func(server *app.Server) app.ServerModule {
|
|
|
|
return &Module{
|
2023-04-20 19:20:52 +02:00
|
|
|
server: server,
|
2023-02-17 10:38:45 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|