Added binding support for MediaPlayer error event

This commit is contained in:
Alexei Anoshenko 2025-06-19 14:51:40 +03:00
parent f2fb948325
commit 24aeeb515b
4 changed files with 495 additions and 142 deletions

View File

@ -331,14 +331,7 @@ func valueToNoArgEventListeners[V View](value any) ([]noArgListener[V], bool) {
func setNoArgEventListener[V View](view View, tag PropertyName, value any) []PropertyName { func setNoArgEventListener[V View](view View, tag PropertyName, value any) []PropertyName {
if listeners, ok := valueToNoArgEventListeners[V](value); ok { if listeners, ok := valueToNoArgEventListeners[V](value); ok {
if len(listeners) > 0 { return setArrayPropertyValue(view, tag, listeners)
view.setRaw(tag, listeners)
} else if view.getRaw(tag) != nil {
view.setRaw(tag, nil)
} else {
return []PropertyName{}
}
return []PropertyName{tag}
} }
notCompatibleType(tag, value) notCompatibleType(tag, value)
return nil return nil

View File

@ -232,14 +232,7 @@ func valueToOneArgEventListeners[V View, E any](value any) ([]oneArgListener[V,
func setOneArgEventListener[V View, T any](view View, tag PropertyName, value any) []PropertyName { func setOneArgEventListener[V View, T any](view View, tag PropertyName, value any) []PropertyName {
if listeners, ok := valueToOneArgEventListeners[V, T](value); ok { if listeners, ok := valueToOneArgEventListeners[V, T](value); ok {
if len(listeners) > 0 { return setArrayPropertyValue(view, tag, listeners)
view.setRaw(tag, listeners)
} else if view.getRaw(tag) != nil {
view.setRaw(tag, nil)
} else {
return []PropertyName{}
}
return []PropertyName{tag}
} }
notCompatibleType(tag, value) notCompatibleType(tag, value)
return nil return nil

View File

@ -305,14 +305,7 @@ func valueToTwoArgEventListeners[V View, E any](value any) ([]twoArgListener[V,
func setTwoArgEventListener[V View, T any](view View, tag PropertyName, value any) []PropertyName { func setTwoArgEventListener[V View, T any](view View, tag PropertyName, value any) []PropertyName {
if listeners, ok := valueToTwoArgEventListeners[V, T](value); ok { if listeners, ok := valueToTwoArgEventListeners[V, T](value); ok {
if len(listeners) > 0 { return setArrayPropertyValue(view, tag, listeners)
view.setRaw(tag, listeners)
} else if view.getRaw(tag) != nil {
view.setRaw(tag, nil)
} else {
return []PropertyName{}
}
return []PropertyName{tag}
} }
notCompatibleType(tag, value) notCompatibleType(tag, value)
return nil return nil

View File

@ -3,6 +3,7 @@ package rui
import ( import (
"fmt" "fmt"
"math" "math"
"reflect"
"strconv" "strconv"
"strings" "strings"
) )
@ -488,7 +489,7 @@ const (
// - player - Interface of a player which generated this event, // - player - Interface of a player which generated this event,
// - code - Error code. See below, // - code - Error code. See below,
// - message - Error message, // - message - Error message,
//
// Error codes: // Error codes:
// - 0 (PlayerErrorUnknown) - Unknown error, // - 0 (PlayerErrorUnknown) - Unknown error,
// - 1 (PlayerErrorAborted) - Fetching the associated resource was interrupted by a user request, // - 1 (PlayerErrorAborted) - Fetching the associated resource was interrupted by a user request,
@ -610,7 +611,7 @@ func (player *mediaPlayerData) setFunc(tag PropertyName, value any) []PropertyNa
return setOneArgEventListener[MediaPlayer, float64](player, tag, value) return setOneArgEventListener[MediaPlayer, float64](player, tag, value)
case PlayerErrorEvent: case PlayerErrorEvent:
if listeners, ok := valueToPlayerErrorListeners(value); ok { if listeners, ok := valueToMediaPlayerErrorListeners(value); ok {
return setArrayPropertyValue(player, tag, listeners) return setArrayPropertyValue(player, tag, listeners)
} }
notCompatibleType(tag, value) notCompatibleType(tag, value)
@ -677,131 +678,132 @@ func setMediaPlayerSource(properties Properties, value any) []PropertyName {
return []PropertyName{Source} return []PropertyName{Source}
} }
func valueToPlayerErrorListeners(value any) ([]func(MediaPlayer, int, string), bool) { /*
if value == nil { func valueToPlayerErrorListeners(value any) ([]func(MediaPlayer, int, string), bool) {
return nil, true if value == nil {
}
switch value := value.(type) {
case func(MediaPlayer, int, string):
return []func(MediaPlayer, int, string){value}, true
case func(int, string):
fn := func(_ MediaPlayer, code int, message string) {
value(code, message)
}
return []func(MediaPlayer, int, string){fn}, true
case func(MediaPlayer):
fn := func(player MediaPlayer, _ int, _ string) {
value(player)
}
return []func(MediaPlayer, int, string){fn}, true
case func():
fn := func(MediaPlayer, int, string) {
value()
}
return []func(MediaPlayer, int, string){fn}, true
case []func(MediaPlayer, int, string):
if len(value) == 0 {
return nil, true return nil, true
} }
for _, fn := range value {
if fn == nil {
return nil, false
}
}
return value, true
case []func(int, string): switch value := value.(type) {
count := len(value) case func(MediaPlayer, int, string):
if count == 0 { return []func(MediaPlayer, int, string){value}, true
return nil, true
}
listeners := make([]func(MediaPlayer, int, string), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(_ MediaPlayer, code int, message string) {
v(code, message)
}
}
return listeners, true
case []func(MediaPlayer): case func(int, string):
count := len(value) fn := func(_ MediaPlayer, code int, message string) {
if count == 0 { value(code, message)
return nil, true
}
listeners := make([]func(MediaPlayer, int, string), count)
for i, v := range value {
if v == nil {
return nil, false
} }
listeners[i] = func(player MediaPlayer, _ int, _ string) { return []func(MediaPlayer, int, string){fn}, true
v(player)
}
}
return listeners, true
case []func(): case func(MediaPlayer):
count := len(value) fn := func(player MediaPlayer, _ int, _ string) {
if count == 0 { value(player)
return nil, true
}
listeners := make([]func(MediaPlayer, int, string), count)
for i, v := range value {
if v == nil {
return nil, false
} }
listeners[i] = func(MediaPlayer, int, string) { return []func(MediaPlayer, int, string){fn}, true
v()
}
}
return listeners, true
case []any: case func():
count := len(value) fn := func(MediaPlayer, int, string) {
if count == 0 { value()
return nil, true
}
listeners := make([]func(MediaPlayer, int, string), count)
for i, v := range value {
if v == nil {
return nil, false
} }
switch v := v.(type) { return []func(MediaPlayer, int, string){fn}, true
case func(MediaPlayer, int, string):
listeners[i] = v
case func(int, string): case []func(MediaPlayer, int, string):
if len(value) == 0 {
return nil, true
}
for _, fn := range value {
if fn == nil {
return nil, false
}
}
return value, true
case []func(int, string):
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(MediaPlayer, int, string), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(_ MediaPlayer, code int, message string) { listeners[i] = func(_ MediaPlayer, code int, message string) {
v(code, message) v(code, message)
} }
}
return listeners, true
case func(MediaPlayer): case []func(MediaPlayer):
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(MediaPlayer, int, string), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(player MediaPlayer, _ int, _ string) { listeners[i] = func(player MediaPlayer, _ int, _ string) {
v(player) v(player)
} }
}
return listeners, true
case func(): case []func():
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(MediaPlayer, int, string), count)
for i, v := range value {
if v == nil {
return nil, false
}
listeners[i] = func(MediaPlayer, int, string) { listeners[i] = func(MediaPlayer, int, string) {
v() v()
} }
default:
return nil, false
} }
return listeners, true
case []any:
count := len(value)
if count == 0 {
return nil, true
}
listeners := make([]func(MediaPlayer, int, string), count)
for i, v := range value {
if v == nil {
return nil, false
}
switch v := v.(type) {
case func(MediaPlayer, int, string):
listeners[i] = v
case func(int, string):
listeners[i] = func(_ MediaPlayer, code int, message string) {
v(code, message)
}
case func(MediaPlayer):
listeners[i] = func(player MediaPlayer, _ int, _ string) {
v(player)
}
case func():
listeners[i] = func(MediaPlayer, int, string) {
v()
}
default:
return nil, false
}
}
return listeners, true
} }
return listeners, true
return nil, false
} }
*/
return nil, false
}
func mediaPlayerEvents() map[PropertyName]string { func mediaPlayerEvents() map[PropertyName]string {
return map[PropertyName]string{ return map[PropertyName]string{
AbortEvent: "onabort", AbortEvent: "onabort",
@ -981,31 +983,23 @@ func (player *mediaPlayerData) handleCommand(self View, command PropertyName, da
PlayingEvent, ProgressEvent, SeekedEvent, SeekingEvent, StalledEvent, SuspendEvent, PlayingEvent, ProgressEvent, SeekedEvent, SeekingEvent, StalledEvent, SuspendEvent,
WaitingEvent: WaitingEvent:
if value := player.getRaw(command); value != nil { for _, listener := range getNoArgEventListeners[MediaPlayer](player, nil, command) {
if listeners, ok := value.([]func(MediaPlayer)); ok { listener.Run(player)
for _, listener := range listeners {
listener(player)
}
}
} }
case TimeUpdateEvent, DurationChangedEvent, RateChangedEvent, VolumeChangedEvent: case TimeUpdateEvent, DurationChangedEvent, RateChangedEvent, VolumeChangedEvent:
if value := player.getRaw(command); value != nil { time := dataFloatProperty(data, "value")
if listeners, ok := value.([]func(MediaPlayer, float64)); ok { for _, listener := range getOneArgEventListeners[MediaPlayer, float64](player, nil, command) {
time := dataFloatProperty(data, "value") listener.Run(player, time)
for _, listener := range listeners {
listener(player, time)
}
}
} }
case PlayerErrorEvent: case PlayerErrorEvent:
if value := player.getRaw(command); value != nil { if value := player.getRaw(command); value != nil {
if listeners, ok := value.([]func(MediaPlayer, int, string)); ok { if listeners, ok := value.([]mediaPlayerErrorListener); ok {
code, _ := dataIntProperty(data, "code") code, _ := dataIntProperty(data, "code")
message, _ := data.PropertyValue("message") message, _ := data.PropertyValue("message")
for _, listener := range listeners { for _, listener := range listeners {
listener(player, code, message) listener.Run(player, code, message)
} }
} }
} }
@ -1254,3 +1248,383 @@ func IsMediaPlayerPaused(view View, playerID string) bool {
ErrorLog(`The found View is not MediaPlayer`) ErrorLog(`The found View is not MediaPlayer`)
return false return false
} }
type mediaPlayerErrorListener interface {
Run(MediaPlayer, int, string)
rawListener() any
}
type mediaPlayerErrorListener0 struct {
fn func()
}
type mediaPlayerErrorListenerP struct {
fn func(MediaPlayer)
}
type mediaPlayerErrorListenerI struct {
fn func(int)
}
type mediaPlayerErrorListenerS struct {
fn func(string)
}
type mediaPlayerErrorListenerPI struct {
fn func(MediaPlayer, int)
}
type mediaPlayerErrorListenerPS struct {
fn func(MediaPlayer, string)
}
type mediaPlayerErrorListenerIS struct {
fn func(int, string)
}
type mediaPlayerErrorListenerPIS struct {
fn func(MediaPlayer, int, string)
}
type mediaPlayerErrorListenerBinding struct {
name string
}
func newMediaPlayerErrorListener0(fn func()) mediaPlayerErrorListener {
obj := new(mediaPlayerErrorListener0)
obj.fn = fn
return obj
}
func (data *mediaPlayerErrorListener0) Run(_ MediaPlayer, _ int, _ string) {
data.fn()
}
func (data *mediaPlayerErrorListener0) rawListener() any {
return data.fn
}
func newMediaPlayerErrorListenerP(fn func(MediaPlayer)) mediaPlayerErrorListener {
obj := new(mediaPlayerErrorListenerP)
obj.fn = fn
return obj
}
func (data *mediaPlayerErrorListenerP) Run(player MediaPlayer, _ int, _ string) {
data.fn(player)
}
func (data *mediaPlayerErrorListenerP) rawListener() any {
return data.fn
}
func newMediaPlayerErrorListenerI(fn func(int)) mediaPlayerErrorListener {
obj := new(mediaPlayerErrorListenerI)
obj.fn = fn
return obj
}
func (data *mediaPlayerErrorListenerI) Run(_ MediaPlayer, code int, _ string) {
data.fn(code)
}
func (data *mediaPlayerErrorListenerI) rawListener() any {
return data.fn
}
func newMediaPlayerErrorListenerS(fn func(string)) mediaPlayerErrorListener {
obj := new(mediaPlayerErrorListenerS)
obj.fn = fn
return obj
}
func (data *mediaPlayerErrorListenerS) Run(_ MediaPlayer, _ int, message string) {
data.fn(message)
}
func (data *mediaPlayerErrorListenerS) rawListener() any {
return data.fn
}
func newMediaPlayerErrorListenerPI(fn func(MediaPlayer, int)) mediaPlayerErrorListener {
obj := new(mediaPlayerErrorListenerPI)
obj.fn = fn
return obj
}
func (data *mediaPlayerErrorListenerPI) Run(player MediaPlayer, code int, _ string) {
data.fn(player, code)
}
func (data *mediaPlayerErrorListenerPI) rawListener() any {
return data.fn
}
func newMediaPlayerErrorListenerPS(fn func(MediaPlayer, string)) mediaPlayerErrorListener {
obj := new(mediaPlayerErrorListenerPS)
obj.fn = fn
return obj
}
func (data *mediaPlayerErrorListenerPS) Run(player MediaPlayer, _ int, message string) {
data.fn(player, message)
}
func (data *mediaPlayerErrorListenerPS) rawListener() any {
return data.fn
}
func newMediaPlayerErrorListenerIS(fn func(int, string)) mediaPlayerErrorListener {
obj := new(mediaPlayerErrorListenerIS)
obj.fn = fn
return obj
}
func (data *mediaPlayerErrorListenerIS) Run(_ MediaPlayer, code int, message string) {
data.fn(code, message)
}
func (data *mediaPlayerErrorListenerIS) rawListener() any {
return data.fn
}
func newMediaPlayerErrorListenerPIS(fn func(MediaPlayer, int, string)) mediaPlayerErrorListener {
obj := new(mediaPlayerErrorListenerPIS)
obj.fn = fn
return obj
}
func (data *mediaPlayerErrorListenerPIS) Run(player MediaPlayer, code int, message string) {
data.fn(player, code, message)
}
func (data *mediaPlayerErrorListenerPIS) rawListener() any {
return data.fn
}
func newMediaPlayerErrorListenerBinding(name string) mediaPlayerErrorListener {
obj := new(mediaPlayerErrorListenerBinding)
obj.name = name
return obj
}
func (data *mediaPlayerErrorListenerBinding) Run(player MediaPlayer, code int, message string) {
bind := player.binding()
if bind == nil {
ErrorLogF(`There is no a binding object for call "%s"`, data.name)
return
}
val := reflect.ValueOf(bind)
method := val.MethodByName(data.name)
if !method.IsValid() {
ErrorLogF(`The "%s" method is not valid`, data.name)
return
}
methodType := method.Type()
var args []reflect.Value = nil
switch methodType.NumIn() {
case 0:
args = []reflect.Value{}
case 1:
switch methodType.In(0) {
case reflect.TypeOf(player):
args = []reflect.Value{reflect.ValueOf(player)}
case reflect.TypeOf(code):
args = []reflect.Value{reflect.ValueOf(code)}
case reflect.TypeOf(message):
args = []reflect.Value{reflect.ValueOf(message)}
}
case 2:
in0 := methodType.In(0)
in1 := methodType.In(1)
if in0 == reflect.TypeOf(player) {
if in1 == reflect.TypeOf(code) {
args = []reflect.Value{reflect.ValueOf(player), reflect.ValueOf(code)}
} else if in1 == reflect.TypeOf(message) {
args = []reflect.Value{reflect.ValueOf(player), reflect.ValueOf(message)}
}
} else if in0 == reflect.TypeOf(code) && in1 == reflect.TypeOf(message) {
args = []reflect.Value{reflect.ValueOf(code), reflect.ValueOf(message)}
}
case 3:
if methodType.In(0) == reflect.TypeOf(player) &&
methodType.In(1) == reflect.TypeOf(code) &&
methodType.In(2) == reflect.TypeOf(message) {
args = []reflect.Value{
reflect.ValueOf(player),
reflect.ValueOf(code),
reflect.ValueOf(message),
}
}
}
if args != nil {
method.Call(args)
} else {
ErrorLogF(`Unsupported prototype of "%s" method`, data.name)
}
}
func (data *mediaPlayerErrorListenerBinding) rawListener() any {
return data.name
}
func valueToMediaPlayerErrorListeners(value any) ([]mediaPlayerErrorListener, bool) {
if value == nil {
return nil, true
}
switch value := value.(type) {
case []mediaPlayerErrorListener:
return value, true
case mediaPlayerErrorListener:
return []mediaPlayerErrorListener{value}, true
case string:
return []mediaPlayerErrorListener{newMediaPlayerErrorListenerBinding(value)}, true
case func():
return []mediaPlayerErrorListener{newMediaPlayerErrorListener0(value)}, true
case func(MediaPlayer):
return []mediaPlayerErrorListener{newMediaPlayerErrorListenerP(value)}, true
case func(int):
return []mediaPlayerErrorListener{newMediaPlayerErrorListenerI(value)}, true
case func(string):
return []mediaPlayerErrorListener{newMediaPlayerErrorListenerS(value)}, true
case func(MediaPlayer, int):
return []mediaPlayerErrorListener{newMediaPlayerErrorListenerPI(value)}, true
case func(MediaPlayer, string):
return []mediaPlayerErrorListener{newMediaPlayerErrorListenerPS(value)}, true
case func(int, string):
return []mediaPlayerErrorListener{newMediaPlayerErrorListenerIS(value)}, true
case func(MediaPlayer, int, string):
return []mediaPlayerErrorListener{newMediaPlayerErrorListenerPIS(value)}, true
case []func():
result := make([]mediaPlayerErrorListener, 0, len(value))
for _, fn := range value {
if fn != nil {
result = append(result, newMediaPlayerErrorListener0(fn))
}
}
return result, len(result) > 0
case []func(MediaPlayer):
result := make([]mediaPlayerErrorListener, 0, len(value))
for _, fn := range value {
if fn != nil {
result = append(result, newMediaPlayerErrorListenerP(fn))
}
}
return result, len(result) > 0
case []func(int):
result := make([]mediaPlayerErrorListener, 0, len(value))
for _, fn := range value {
if fn != nil {
result = append(result, newMediaPlayerErrorListenerI(fn))
}
}
return result, len(result) > 0
case []func(string):
result := make([]mediaPlayerErrorListener, 0, len(value))
for _, fn := range value {
if fn != nil {
result = append(result, newMediaPlayerErrorListenerS(fn))
}
}
return result, len(result) > 0
case []func(MediaPlayer, int):
result := make([]mediaPlayerErrorListener, 0, len(value))
for _, fn := range value {
if fn != nil {
result = append(result, newMediaPlayerErrorListenerPI(fn))
}
}
return result, len(result) > 0
case []func(MediaPlayer, string):
result := make([]mediaPlayerErrorListener, 0, len(value))
for _, fn := range value {
if fn != nil {
result = append(result, newMediaPlayerErrorListenerPS(fn))
}
}
return result, len(result) > 0
case []func(int, string):
result := make([]mediaPlayerErrorListener, 0, len(value))
for _, fn := range value {
if fn != nil {
result = append(result, newMediaPlayerErrorListenerIS(fn))
}
}
return result, len(result) > 0
case []func(MediaPlayer, int, string):
result := make([]mediaPlayerErrorListener, 0, len(value))
for _, fn := range value {
if fn != nil {
result = append(result, newMediaPlayerErrorListenerPIS(fn))
}
}
return result, len(result) > 0
case []any:
result := make([]mediaPlayerErrorListener, 0, len(value))
for _, v := range value {
if v != nil {
switch v := v.(type) {
case func():
result = append(result, newMediaPlayerErrorListener0(v))
case func(MediaPlayer):
result = append(result, newMediaPlayerErrorListenerP(v))
case func(int):
result = append(result, newMediaPlayerErrorListenerI(v))
case func(string):
result = append(result, newMediaPlayerErrorListenerS(v))
case func(MediaPlayer, int):
result = append(result, newMediaPlayerErrorListenerPI(v))
case func(MediaPlayer, string):
result = append(result, newMediaPlayerErrorListenerPS(v))
case func(int, string):
result = append(result, newMediaPlayerErrorListenerIS(v))
case func(MediaPlayer, int, string):
result = append(result, newMediaPlayerErrorListenerPIS(v))
case string:
result = append(result, newMediaPlayerErrorListenerBinding(v))
default:
return nil, false
}
}
}
return result, len(result) > 0
}
return nil, false
}