This source file includes following definitions.
- gf_html_media_object
- gf_html_track_init_js
- gf_html_media_element_init_js
- html_media_element_populate_tracks
- html_media_element_get_from_node
- SMJS_FUNCTION
- SMJS_FUNCTION
- SMJS_FUNCTION
- SMJS_FUNCTION
- html_get_element_class
- html_media_element_js_init
- html_media_element_js_finalize
- gf_html_media_get_event_target
- SMJS_FUNC_PROP_GET
- SMJS_FUNC_PROP_SET
- SMJS_FUNC_PROP_SET
- html_media_get_states
- GF_JS_InstanceOf
- SMJS_FUNC_PROP_SET
- ScriptAction
- SMJS_FUNC_PROP_SET
- SMJS_FUNC_PROP_SET
- JSVAL_IS_NUMBER
- SMJS_FUNC_PROP_SET
- SMJS_FUNC_PROP_SET
- SMJS_FUNC_PROP_SET
- SMJS_FUNC_PROP_GET
- SMJS_FUNC_PROP_SET
- SMJS_FUNC_PROP_SET
- html_media_get_audio_stack
- SMJS_FUNC_PROP_SET
- SMJS_FUNC_PROP_GET
- SMJS_FUNCTION
- SMJS_FUNCTION
- html_is_track_list
- SMJS_FUNC_PROP_GET
- SMJS_FUNCTION
- SMJS_FUNC_PROP_GET
- SMJS_FUNC_PROP_GET
- SMJS_FUNC_PROP_GET
- SMJS_FUNC_PROP_SET
- SMJS_FUNC_PROP_GET
- SMJS_FUNC_PROP_SET
- SMJS_FUNC_PROP_GET
- SMJS_FUNC_PROP_SET
- SMJS_FUNC_PROP_GET
- SMJS_FUNC_PROP_SET
- SMJS_FUNC_PROP_GET
- SMJS_FUNC_PROP_SET
- SMJS_FUNCTION
- SMJS_FUNCTION
- SMJS_FUNCTION
- html_media_js_api_del
- html_media_init_js_api
#include <gpac/internal/scenegraph_dev.h>
#include <gpac/nodes_svg.h>
#include <gpac/events.h>
#include <gpac/utf.h>
#include <gpac/download.h>
#include <gpac/network.h>
#include <gpac/xml.h>
#ifndef GPAC_DISABLE_SVG
#ifdef GPAC_ANDROID
#ifndef XP_UNIX
#define XP_UNIX
#endif
#endif
#ifdef GPAC_HAS_SPIDERMONKEY
#include <gpac/internal/smjs_api.h>
#include <gpac/html5_media.h>
#ifdef USE_FFDEV_15
void dom_element_finalize(JSFreeOp *fop, JSObject *obj);
void dom_document_finalize(JSFreeOp *fop, JSObject *obj);
#else
void dom_element_finalize(JSContext *c, JSObject *obj);
void dom_document_finalize(JSContext *c, JSObject *obj);
#endif
void gf_svg_set_attributeNS(GF_Node *n, u32 ns_code, char *name, char *val);
#define JSVAL_CHECK_STRING(_v) (JSVAL_IS_STRING(_v) || JSVAL_IS_NULL(_v))
#include <gpac/internal/terminal_dev.h>
#include <gpac/internal/compositor_dev.h>
static GF_HTML_MediaRuntime *html_media_rt = NULL;
typedef enum
{
MEDIA_ERROR_PROP_ABORTED = -1,
MEDIA_ERROR_PROP_NETWORK = -2,
MEDIA_ERROR_PROP_DECODE = -3,
MEDIA_ERROR_PROP_SRC_NOT_SUPPORTED = -4,
MEDIA_ERROR_PROP_CODE = -5
} GF_HTML_MediaErrorPropEnum;
typedef enum
{
HTML_MEDIA_PROP_SRC = -1,
HTML_MEDIA_PROP_CURRENTSRC = -2,
HTML_MEDIA_PROP_CROSSORIGIN = -3,
HTML_MEDIA_PROP_NETWORKSTATE = -4,
HTML_MEDIA_PROP_PRELOAD = -5,
HTML_MEDIA_PROP_BUFFERED = -6,
HTML_MEDIA_PROP_READYSTATE = -7,
HTML_MEDIA_PROP_SEEKING = -8,
HTML_MEDIA_PROP_CURRENTTIME = -9,
HTML_MEDIA_PROP_DURATION = -10,
HTML_MEDIA_PROP_STARTDATE = -11,
HTML_MEDIA_PROP_PAUSED = -12,
HTML_MEDIA_PROP_DEFAULTPLAYBACKRATE = -13,
HTML_MEDIA_PROP_PLAYBACKRATE = -14,
HTML_MEDIA_PROP_PLAYED = -15,
HTML_MEDIA_PROP_SEEKABLE = -16,
HTML_MEDIA_PROP_ENDED = -17,
HTML_MEDIA_PROP_AUTOPLAY = -18,
HTML_MEDIA_PROP_LOOP = -19,
HTML_MEDIA_PROP_MEDIAGROUP = -20,
HTML_MEDIA_PROP_CONTROLLER = -21,
HTML_MEDIA_PROP_CONTROLS = -22,
HTML_MEDIA_PROP_VOLUME = -23,
HTML_MEDIA_PROP_MUTED = -24,
HTML_MEDIA_PROP_DEFAULTMUTED = -25,
HTML_MEDIA_PROP_AUDIOTRACKS = -26,
HTML_MEDIA_PROP_VIDEOTRACKS = -27,
HTML_MEDIA_PROP_TEXTTRACKS = -28,
HTML_MEDIA_PROP_NETWORK_EMPTY = -29,
HTML_MEDIA_PROP_NETWORK_IDLE = -30,
HTML_MEDIA_PROP_NETWORK_LOADING = -31,
HTML_MEDIA_PROP_NETWORK_NO_SOURCE = -32,
HTML_MEDIA_PROP_HAVE_NOTHING = -33,
HTML_MEDIA_PROP_HAVE_METADATA = -34,
HTML_MEDIA_PROP_HAVE_CURRENT_DATA = -35,
HTML_MEDIA_PROP_HAVE_FUTURE_DATA = -36,
HTML_MEDIA_PROP_HAVE_ENOUGH_DATA = -37,
HTML_MEDIA_PROP_ERROR = -38
} GF_HTML_MediaEltPropEnum;
typedef enum {
HTML_VIDEO_PROP_WIDTH = -1,
HTML_VIDEO_PROP_HEIGHT = -2,
HTML_VIDEO_PROP_VIDEOWIDTH = -3,
HTML_VIDEO_PROP_VIDEOHEIGHT = -4,
HTML_VIDEO_PROP_POSTER = -5
} GF_HTML_VideoEltPropEnum;
typedef enum {
HTML_TRACK_PROP_ID = -1,
HTML_TRACK_PROP_KIND = -2,
HTML_TRACK_PROP_LABEL = -3,
HTML_TRACK_PROP_LANGUAGE = -4,
HTML_TRACK_PROP_SELECTED = -5,
HTML_TRACK_PROP_ENABLED = -6,
HTML_TRACK_PROP_INBANDTYPE = -7
} GF_HTML_TrackPropEnum;
#define HTML_MEDIA_JS_CHECK GF_HTML_MediaElement *me; \
GF_Node *n = (GF_Node *)SMJS_GET_PRIVATE(c, obj); \
if (!n || (n->sgprivate->tag != TAG_SVG_video && n->sgprivate->tag != TAG_SVG_audio)) \
{ \
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR); \
} \
me = (GF_HTML_MediaElement *)html_media_element_get_from_node(c, n); \
if (!me) { \
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR); \
}
#define HTML_MEDIA_JS_START HTML_MEDIA_JS_CHECK
typedef struct
{
GF_TextureHandler txh;
struct _drawable *graph;
MFURL txurl;
Bool first_frame_fetched;
GF_Node *audio;
Bool audio_dirty;
Bool stop_requested;
} SVG_video_stack;
typedef struct
{
GF_AudioInput input;
Bool is_active, is_error;
MFURL aurl;
} SVG_audio_stack;
static GF_MediaObject *gf_html_media_object(GF_Node *n)
{
GF_MediaObject *mo = NULL;
if (n->sgprivate->tag == TAG_SVG_video)
{
SVG_video_stack *video_stack;
video_stack = (SVG_video_stack *)n->sgprivate->UserPrivate;
mo = video_stack->txh.stream;
}
else if (n->sgprivate->tag == TAG_SVG_audio)
{
SVG_audio_stack *audio_stack;
audio_stack = (SVG_audio_stack *)n->sgprivate->UserPrivate;
mo = audio_stack->input.stream;
}
return mo;
}
static void gf_html_track_init_js(GF_HTML_Track *track, JSContext *c, GF_HTML_TrackList *tracklist)
{
JSObject *track_obj;
track->c = c;
if (track->type == HTML_MEDIA_TRACK_TYPE_AUDIO)
{
track_obj = JS_NewObject(c, &html_media_rt->audioTrackClass._class, NULL, tracklist->_this);
}
else if (track->type == HTML_MEDIA_TRACK_TYPE_VIDEO)
{
track_obj = JS_NewObject(c, &html_media_rt->videoTrackClass._class, NULL, tracklist->_this);
}
else if (track->type == HTML_MEDIA_TRACK_TYPE_TEXT)
{
track_obj = JS_NewObject(c, &html_media_rt->textTrackClass._class, NULL, tracklist->_this);
}
else
{
return;
}
tracklist->onchange = JSVAL_NULL;
tracklist->onaddtrack = JSVAL_NULL;
tracklist->onremovetrack = JSVAL_NULL;
track->_this = track_obj;
SMJS_SET_PRIVATE(c, track->_this, track);
}
static void gf_html_media_element_init_js(GF_HTML_MediaElement *me, JSContext *c, JSObject *node_obj)
{
me->c = c;
me->_this = JS_NewObject(c, &html_media_rt->htmlMediaElementClass._class, NULL, node_obj);
SMJS_SET_PRIVATE(c, me->_this, me);
me->error.c = c;
me->error._this = JS_NewObject(c, &html_media_rt->mediaErrorClass._class, NULL, me->_this);
SMJS_SET_PRIVATE(c, me->error._this, &me->error);
me->audioTracks.c = c;
me->audioTracks._this = JS_NewObject(c, &html_media_rt->audioTrackListClass._class, NULL, me->_this);
SMJS_SET_PRIVATE(c, me->audioTracks._this, &me->audioTracks);
me->videoTracks.c = c;
me->videoTracks._this = JS_NewObject(c, &html_media_rt->videoTrackListClass._class, NULL, me->_this);
SMJS_SET_PRIVATE(c, me->videoTracks._this, &me->videoTracks);
me->textTracks.c = c;
me->textTracks._this = JS_NewObject(c, &html_media_rt->textTrackListClass._class, NULL, me->_this);
SMJS_SET_PRIVATE(c, me->textTracks._this, &me->textTracks);
me->buffered->c = c;
me->buffered->_this = JS_NewObject(c, &html_media_rt->timeRangesClass._class, NULL, me->_this);
SMJS_SET_PRIVATE(c, me->buffered->_this, me->buffered);
me->played->c = c;
me->played->_this = JS_NewObject(c, &html_media_rt->timeRangesClass._class, NULL, me->_this);
SMJS_SET_PRIVATE(c, me->played->_this, me->played);
me->seekable->c = c;
me->seekable->_this = JS_NewObject(c, &html_media_rt->timeRangesClass._class, NULL, me->_this);
SMJS_SET_PRIVATE(c, me->seekable->_this, me->seekable);
}
static void html_media_element_populate_tracks(JSContext *c, GF_HTML_MediaElement *me)
{
GF_HTML_Track *track;
GF_MediaObject *mo;
GF_ClientService *service;
GF_Scene *scene;
u32 i, count;
if (!me || !me->node) {
return;
}
mo = gf_html_media_object(me->node);
if (!mo || !mo->odm || !mo->odm->net_service || !mo->odm->parentscene) {
return;
}
service = mo->odm->net_service;
scene = mo->odm->parentscene;
count = gf_list_count(scene->resources);
for (i=0; i<count; i++) {
u32 j;
GF_ObjectManager *odm = (GF_ObjectManager *)gf_list_get(scene->resources, i);
if (odm->net_service != service) continue;
if (!odm->mo || !odm->OD) continue;
for (j = 0; j < gf_list_count(odm->OD->ESDescriptors); j++)
{
char id[256];
char *lang = "";
GF_ESD *esd = (GF_ESD *)gf_list_get(odm->OD->ESDescriptors, j);
sprintf(id, "track%d", esd->ESID);
if (esd->langDesc)
{
lang = "";
}
switch(odm->mo->type)
{
case GF_MEDIA_OBJECT_VIDEO:
if (!html_media_tracklist_has_track(&me->videoTracks, id))
{
track = html_media_add_new_track_to_list(&me->videoTracks, HTML_MEDIA_TRACK_TYPE_VIDEO,
"video/mp4", GF_TRUE, id, "myKind", "myLabel", lang);
gf_html_track_init_js(track, c, &me->videoTracks);
}
break;
case GF_MEDIA_OBJECT_AUDIO:
if (!html_media_tracklist_has_track(&me->audioTracks, id))
{
track = html_media_add_new_track_to_list(&me->audioTracks, HTML_MEDIA_TRACK_TYPE_AUDIO,
"audio/mp4", GF_TRUE, id, "myKind", "myLabel", lang);
gf_html_track_init_js(track, c, &me->audioTracks);
}
break;
case GF_MEDIA_OBJECT_TEXT:
if (!html_media_tracklist_has_track(&me->textTracks, id))
{
track = html_media_add_new_track_to_list(&me->textTracks, HTML_MEDIA_TRACK_TYPE_TEXT,
"text/plain", GF_TRUE, id, "myKind", "myLabel", lang);
gf_html_track_init_js(track, c, &me->textTracks);
}
break;
}
}
}
}
static GF_HTML_MediaElement *html_media_element_get_from_node(JSContext *c, GF_Node *n)
{
jsval vp;
JSObject *me_obj;
JSObject *node_obj;
GF_HTML_MediaElement *me = NULL;
if ((n->sgprivate->tag == TAG_SVG_video || n->sgprivate->tag == TAG_SVG_audio) && n->sgprivate->interact && n->sgprivate->interact->js_binding) {
node_obj = (JSObject *)n->sgprivate->interact->js_binding->node;
if (node_obj) {
JS_GetProperty(c, node_obj, "gpac_me_impl", &vp);
me_obj = JSVAL_TO_OBJECT(vp);
me = (GF_HTML_MediaElement *)SMJS_GET_PRIVATE(c, me_obj);
}
}
return me;
}
static JSBool SMJS_FUNCTION(html_media_load)
{
SMJS_OBJ
if (GF_JS_InstanceOf(c, obj, &html_media_rt->htmlAudioElementClass, NULL) ||
GF_JS_InstanceOf(c, obj, &html_media_rt->htmlVideoElementClass, NULL) ||
GF_JS_InstanceOf(c, obj, &html_media_rt->htmlMediaElementClass, NULL))
{
MFURL mfurl;
GF_Node *n = (GF_Node *)SMJS_GET_PRIVATE(c, obj);
GF_HTML_MediaElement *me = html_media_element_get_from_node(c, n);
mfurl.count = 1;
mfurl.vals = (SFURL *)gf_malloc(sizeof(SFURL));
mfurl.vals[0].url = me->currentSrc;
mfurl.vals[0].OD_ID = GF_MEDIA_EXTERNAL_ID;
gf_mo_register(n, &mfurl, GF_FALSE, GF_FALSE);
gf_free(mfurl.vals);
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static JSBool SMJS_FUNCTION(html_media_canPlayType)
{
SMJS_OBJ
if (GF_JS_InstanceOf(c, obj, &html_media_rt->htmlAudioElementClass, NULL) ||
GF_JS_InstanceOf(c, obj, &html_media_rt->htmlVideoElementClass, NULL) ||
GF_JS_InstanceOf(c, obj, &html_media_rt->htmlMediaElementClass, NULL))
{
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static JSBool SMJS_FUNCTION(html_media_fastSeek)
{
SMJS_OBJ
if (GF_JS_InstanceOf(c, obj, &html_media_rt->htmlAudioElementClass, NULL) ||
GF_JS_InstanceOf(c, obj, &html_media_rt->htmlVideoElementClass, NULL) ||
GF_JS_InstanceOf(c, obj, &html_media_rt->htmlMediaElementClass, NULL))
{
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static JSBool SMJS_FUNCTION(html_media_addTextTrack)
{
SMJS_OBJ
if (GF_JS_InstanceOf(c, obj, &html_media_rt->htmlAudioElementClass, NULL) ||
GF_JS_InstanceOf(c, obj, &html_media_rt->htmlVideoElementClass, NULL) ||
GF_JS_InstanceOf(c, obj, &html_media_rt->htmlMediaElementClass, NULL))
{
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
void *html_get_element_class(GF_Node *n)
{
if (!n || !html_media_rt)
{
return NULL;
} else if (n->sgprivate->tag == TAG_SVG_video) {
return &html_media_rt->htmlVideoElementClass;
} else if (n->sgprivate->tag == TAG_SVG_audio) {
return &html_media_rt->htmlAudioElementClass;
} else {
return NULL;
}
}
void html_media_element_js_init(JSContext *c, JSObject *node_obj, GF_Node *n)
{
if (n->sgprivate->tag == TAG_SVG_video || n->sgprivate->tag == TAG_SVG_audio) {
GF_HTML_MediaElement *me;
me = gf_html_media_element_new(n, NULL);
gf_html_media_element_init_js(me, c, node_obj);
JS_DefineProperty(c, node_obj, "gpac_me_impl", OBJECT_TO_JSVAL(me->_this), 0, 0, JSPROP_READONLY | JSPROP_PERMANENT);
}
}
void html_media_element_js_finalize(JSContext *c, GF_Node *n)
{
GF_HTML_MediaElement *me = html_media_element_get_from_node(c, n);
gf_html_media_element_del(me);
}
void gf_html_media_get_event_target(JSContext *c, JSObject *obj, GF_DOMEventTarget **target, GF_SceneGraph **sg) {
if (!sg || !target) return;
if (GF_JS_InstanceOf(c, obj, &html_media_rt->htmlVideoElementClass, NULL) ||
GF_JS_InstanceOf(c, obj, &html_media_rt->htmlAudioElementClass, NULL) ) {
GF_Node *n = (GF_Node *)SMJS_GET_PRIVATE(c, obj);
*target = gf_dom_event_get_target_from_node(n);
*sg = n->sgprivate->scenegraph;
} else {
*target = NULL;
*sg = NULL;
}
}
static SMJS_FUNC_PROP_GET(html_media_error_get_code)
if (GF_JS_InstanceOf(c, obj, &html_media_rt->mediaErrorClass, NULL))
{
GF_HTML_MediaError *error = (GF_HTML_MediaError*)SMJS_GET_PRIVATE(c, obj);
if (!SMJS_ID_IS_INT(id)) {
return JS_TRUE;
}
switch (SMJS_ID_TO_INT(id))
{
case MEDIA_ERROR_PROP_ABORTED:
*vp = INT_TO_JSVAL(MEDIA_ERR_ABORTED);
return JS_TRUE;
case MEDIA_ERROR_PROP_NETWORK:
*vp = INT_TO_JSVAL(MEDIA_ERR_NETWORK);
return JS_TRUE;
case MEDIA_ERROR_PROP_DECODE:
*vp = INT_TO_JSVAL(MEDIA_ERR_DECODE);
return JS_TRUE;
case MEDIA_ERROR_PROP_SRC_NOT_SUPPORTED:
*vp = INT_TO_JSVAL(MEDIA_ERR_SRC_NOT_SUPPORTED);
return JS_TRUE;
case MEDIA_ERROR_PROP_CODE:
*vp = INT_TO_JSVAL(error->code);
return JS_TRUE;
}
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SMJS_FUNC_PROP_GET(html_media_get_error)
HTML_MEDIA_JS_START
*vp = OBJECT_TO_JSVAL(me->error._this);
return JS_TRUE;
}
static SMJS_FUNC_PROP_GET(html_media_get_src)
GF_FieldInfo info;
HTML_MEDIA_JS_START
if (gf_node_get_attribute_by_name(n, "href", GF_XMLNS_XLINK, GF_TRUE, GF_TRUE, &info)==GF_OK) {
char *szAtt = gf_svg_dump_attribute(n, &info);
*vp = STRING_TO_JSVAL( JS_NewStringCopyZ(c, szAtt) );
if (szAtt) gf_free(szAtt);
}
return JS_TRUE;
}
static SMJS_FUNC_PROP_SET(html_media_set_src)
HTML_MEDIA_JS_START
if (JSVAL_CHECK_STRING(*vp)) {
char *str = SMJS_CHARS(c, *vp);
gf_svg_set_attributeNS(n, GF_XMLNS_XLINK, "href", str);
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SMJS_FUNC_PROP_GET(html_media_get_cors)
GF_FieldInfo info;
HTML_MEDIA_JS_START
if (gf_node_get_attribute_by_name(n, "crossorigin", GF_XMLNS_SVG, GF_TRUE, GF_TRUE, &info)==GF_OK) {
char *szAtt = gf_svg_dump_attribute(n, &info);
*vp = STRING_TO_JSVAL( JS_NewStringCopyZ(c, szAtt) );
if (szAtt) gf_free(szAtt);
}
return JS_TRUE;
}
static SMJS_FUNC_PROP_SET(html_media_set_cors)
HTML_MEDIA_JS_START
if (JSVAL_CHECK_STRING(*vp)) {
char *str = SMJS_CHARS(c, *vp);
gf_svg_set_attributeNS(n, GF_XMLNS_SVG, "crossorigin", str);
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
void media_event_collect_info(GF_ClientService *net, GF_ObjectManager *odm, GF_DOMMediaEvent *media_event, u32 *min_time, u32 *min_buffer);
static void html_media_get_states(GF_MediaObject *mo, GF_HTML_MediaReadyState *readyState, GF_HTML_NetworkState *networkState)
{
GF_DOMMediaEvent media_event;
u32 min_time;
u32 min_buffer;
if (!mo) return;
if (!mo->odm) {
*readyState = HAVE_NOTHING;
*networkState = NETWORK_EMPTY;
return;
}
memset(&media_event, 0, sizeof(GF_DOMMediaEvent));
media_event_collect_info(mo->odm->net_service, mo->odm, &media_event, &min_time, &min_buffer);
if (min_buffer == 0)
{
*readyState = HAVE_NOTHING;
*networkState = NETWORK_EMPTY;
}
else
{
if (media_event.loaded_size != 0)
{
*readyState = HAVE_METADATA;
}
else if (media_event.loaded_size == media_event.total_size)
{
*readyState = HAVE_ENOUGH_DATA;
}
}
}
static SMJS_FUNC_PROP_GET(html_media_get_ready_state)
GF_HTML_MediaReadyState readyState = HAVE_NOTHING;
GF_HTML_NetworkState networkState = NETWORK_EMPTY;
GF_MediaObject *mo = NULL;
HTML_MEDIA_JS_START
html_media_element_populate_tracks(c, me);
mo = gf_html_media_object(n);
html_media_get_states(mo, &readyState, &networkState);
*vp = INT_TO_JSVAL( readyState );
return JS_TRUE;
}
static SMJS_FUNC_PROP_GET(html_media_get_network_state)
GF_HTML_MediaReadyState readyState = HAVE_NOTHING;
GF_HTML_NetworkState networkState = NETWORK_EMPTY;
GF_MediaObject *mo = NULL;
HTML_MEDIA_JS_START
mo = gf_html_media_object(n);
html_media_get_states(mo, &readyState, &networkState);
*vp = INT_TO_JSVAL( networkState );
return JS_TRUE;
}
static SMJS_FUNC_PROP_GET(html_media_get_const)
u32 v = 0;
if (GF_JS_InstanceOf(c, obj, &html_media_rt->htmlMediaElementClass, NULL) ||
GF_JS_InstanceOf(c, obj, &html_media_rt->htmlVideoElementClass, NULL) ||
GF_JS_InstanceOf(c, obj, &html_media_rt->htmlAudioElementClass, NULL))
{
if (!SMJS_ID_IS_INT(id)) {
return JS_TRUE;
}
switch (SMJS_ID_TO_INT(id)) {
case HTML_MEDIA_PROP_NETWORK_EMPTY:
v = NETWORK_EMPTY;
break;
case HTML_MEDIA_PROP_NETWORK_IDLE:
v = NETWORK_IDLE;
break;
case HTML_MEDIA_PROP_NETWORK_LOADING:
v = NETWORK_LOADING;
break;
case HTML_MEDIA_PROP_NETWORK_NO_SOURCE:
v = NETWORK_NO_SOURCE;
break;
case HTML_MEDIA_PROP_HAVE_NOTHING:
v = HAVE_NOTHING;
break;
case HTML_MEDIA_PROP_HAVE_METADATA:
v = HAVE_METADATA;
break;
case HTML_MEDIA_PROP_HAVE_CURRENT_DATA:
v = HAVE_CURRENT_DATA;
break;
case HTML_MEDIA_PROP_HAVE_FUTURE_DATA:
v = HAVE_FUTURE_DATA;
break;
case HTML_MEDIA_PROP_HAVE_ENOUGH_DATA:
v = HAVE_ENOUGH_DATA;
break;
default:
return JS_TRUE;
}
*vp = INT_TO_JSVAL( v );
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SMJS_FUNC_PROP_GET(html_media_get_preload)
GF_FieldInfo info;
HTML_MEDIA_JS_START
if (gf_node_get_attribute_by_name(n, "preload", GF_XMLNS_SVG, GF_TRUE, GF_TRUE, &info)==GF_OK) {
char *szAtt = gf_svg_dump_attribute(n, &info);
*vp = STRING_TO_JSVAL( JS_NewStringCopyZ(c, szAtt) );
if (szAtt) gf_free(szAtt);
}
return JS_TRUE;
}
static SMJS_FUNC_PROP_SET(html_media_set_preload)
HTML_MEDIA_JS_START
if (JSVAL_CHECK_STRING(*vp)) {
char *str = SMJS_CHARS(c, *vp);
gf_svg_set_attributeNS(n, GF_XMLNS_SVG, "preload", str);
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SMJS_FUNC_PROP_GET(html_media_get_buffered)
HTML_MEDIA_JS_START
*vp = OBJECT_TO_JSVAL( me->buffered->_this );
return JS_TRUE;
}
static SMJS_FUNC_PROP_GET(html_media_get_seeking)
HTML_MEDIA_JS_START
*vp = BOOLEAN_TO_JSVAL( (me->seeking ? JS_TRUE : JS_FALSE) );
return JS_TRUE;
}
static SMJS_FUNC_PROP_GET(html_media_get_current_time)
u32 time_ms = 0;
Double time_s;
GF_MediaObject *mo = NULL;
HTML_MEDIA_JS_START
mo = gf_html_media_object(n);
gf_mo_get_object_time(mo, &time_ms);
time_s = time_ms / 1000.0;
*vp = JS_MAKE_DOUBLE(c, time_s );
return JS_TRUE;
}
static GFINLINE Bool ScriptAction(GF_SceneGraph *scene, u32 type, GF_Node *node, GF_JSAPIParam *param)
{
if (scene->script_action)
{
return scene->script_action(scene->script_action_cbck, type, node, param);
}
return GF_FALSE;
}
static SMJS_FUNC_PROP_SET(html_media_set_current_time)
double d;
GF_JSAPIParam par;
HTML_MEDIA_JS_START
if (!JSVAL_IS_NUMBER(*vp)) {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
JS_ValueToNumber(c, *vp, &d);
par.time = d;
ScriptAction(n->sgprivate->scenegraph, GF_JSAPI_OP_SET_TIME, (GF_Node *)n, &par);
return JS_TRUE;
}
static SMJS_FUNC_PROP_GET(html_media_get_duration)
Double dur;
GF_MediaObject *mo = NULL;
HTML_MEDIA_JS_START
mo = gf_html_media_object(n);
dur = gf_mo_get_duration(mo);
if (dur <= 0) {
*vp = JS_GetNaNValue(c);
} else {
*vp = DOUBLE_TO_JSVAL(JS_NewDouble(c, dur));
}
return JS_TRUE;
}
static SMJS_FUNC_PROP_GET(html_media_get_start_date)
HTML_MEDIA_JS_START
*vp = JSVAL_NULL;
return JS_TRUE;
}
static SMJS_FUNC_PROP_GET(html_media_get_paused)
HTML_MEDIA_JS_START
*vp =( BOOLEAN_TO_JSVAL( (me->paused ? JS_TRUE : JS_FALSE) ) );
return JS_TRUE;
}
static SMJS_FUNC_PROP_GET(html_media_get_default_playback_rate)
HTML_MEDIA_JS_START
*vp = DOUBLE_TO_JSVAL(JS_NewDouble(c, me->defaultPlaybackRate));
return JS_TRUE;
}
static SMJS_FUNC_PROP_SET(html_media_set_default_playback_rate)
jsdouble d;
HTML_MEDIA_JS_START
if (!JSVAL_IS_NUMBER(*vp)) {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
JS_ValueToNumber(c, *vp, &d);
me->defaultPlaybackRate = d;
return JS_TRUE;
}
static SMJS_FUNC_PROP_GET(html_media_get_playback_rate)
Double speed;
GF_Node *n = (GF_Node *)SMJS_GET_PRIVATE(c, obj);
GF_MediaObject *mo = gf_html_media_object(n);
speed = gf_mo_get_current_speed(mo);
*vp = DOUBLE_TO_JSVAL(JS_NewDouble(c, speed));
return JS_TRUE;
}
static SMJS_FUNC_PROP_SET(html_media_set_playback_rate)
jsdouble d;
Fixed speed;
GF_MediaObject *mo;
HTML_MEDIA_JS_START
mo = gf_html_media_object(n);
if (!JSVAL_IS_NUMBER(*vp)) {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
JS_ValueToNumber(c, *vp, &d);
speed = FLT2FIX(d);
gf_mo_set_speed(mo, speed);
return JS_TRUE;
}
static SMJS_FUNC_PROP_GET(html_media_get_played)
HTML_MEDIA_JS_START
*vp =( OBJECT_TO_JSVAL( me->played->_this ) );
return JS_TRUE;
}
static SMJS_FUNC_PROP_GET(html_media_get_seekable)
HTML_MEDIA_JS_START
*vp =( OBJECT_TO_JSVAL( me->seekable->_this ) );
return JS_TRUE;
}
static SMJS_FUNC_PROP_GET(html_media_get_ended)
GF_MediaObject *mo;
HTML_MEDIA_JS_START
mo = gf_html_media_object(n);
*vp = BOOLEAN_TO_JSVAL( gf_mo_is_done(mo) ? JS_TRUE : JS_FALSE);
return JS_TRUE;
}
static SMJS_FUNC_PROP_GET(html_media_get_autoplay)
GF_FieldInfo info;
HTML_MEDIA_JS_START
if (gf_node_get_attribute_by_name(n, "autoplay", GF_XMLNS_SVG, GF_TRUE, GF_TRUE, &info)==GF_OK) {
char *szAtt = gf_svg_dump_attribute(n, &info);
if (!strcmp(szAtt, "true") || !strcmp(szAtt, "TRUE")) {
*vp =( BOOLEAN_TO_JSVAL( JS_TRUE ) );
} else {
*vp =( BOOLEAN_TO_JSVAL( JS_FALSE ) );
}
if (szAtt) gf_free(szAtt);
}
return JS_TRUE;
}
static SMJS_FUNC_PROP_SET(html_media_set_autoplay)
HTML_MEDIA_JS_START
if (JSVAL_CHECK_STRING(*vp)) {
char *str = SMJS_CHARS(c, *vp);
gf_svg_set_attributeNS(n, GF_XMLNS_SVG, "autoplay", str);
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SMJS_FUNC_PROP_GET(html_media_get_loop)
GF_FieldInfo info;
HTML_MEDIA_JS_START
if (gf_node_get_attribute_by_name(n, "loop", GF_XMLNS_SVG, GF_TRUE, GF_TRUE, &info)==GF_OK) {
char *szAtt = gf_svg_dump_attribute(n, &info);
if (!strcmp(szAtt, "true") || !strcmp(szAtt, "TRUE")) {
*vp =( BOOLEAN_TO_JSVAL( JS_TRUE ) );
} else {
*vp =( BOOLEAN_TO_JSVAL( JS_FALSE ) );
}
if (szAtt) gf_free(szAtt);
}
return JS_TRUE;
}
static SMJS_FUNC_PROP_SET(html_media_set_loop)
HTML_MEDIA_JS_START
if (JSVAL_CHECK_STRING(*vp)) {
char *str = SMJS_CHARS(c, *vp);
gf_svg_set_attributeNS(n, GF_XMLNS_SVG, "loop", str);
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SMJS_FUNC_PROP_GET(html_media_get_mediagroup)
GF_FieldInfo info;
HTML_MEDIA_JS_START
if (gf_node_get_attribute_by_name(n, "mediagroup", GF_XMLNS_SVG, GF_TRUE, GF_TRUE, &info)==GF_OK) {
char *szAtt = gf_svg_dump_attribute(n, &info);
*vp =( STRING_TO_JSVAL( JS_NewStringCopyZ(c, szAtt) ) );
if (szAtt) gf_free(szAtt);
}
return JS_TRUE;
}
static SMJS_FUNC_PROP_SET(html_media_set_mediagroup)
HTML_MEDIA_JS_START
if (JSVAL_CHECK_STRING(*vp)) {
char *str = SMJS_CHARS(c, *vp);
gf_svg_set_attributeNS(n, GF_XMLNS_SVG, "mediagroup", str);
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SMJS_FUNC_PROP_GET(html_media_get_controller)
HTML_MEDIA_JS_START
if (me->controller) {
*vp = OBJECT_TO_JSVAL( me->controller->_this );
} else {
*vp = JSVAL_NULL;
}
return JS_TRUE;
}
static SMJS_FUNC_PROP_SET(html_media_set_controller)
HTML_MEDIA_JS_START
if (JSVAL_IS_OBJECT(*vp)) {
me->controller = (GF_HTML_MediaController *)SMJS_GET_PRIVATE(c, JSVAL_TO_OBJECT(*vp));
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SMJS_FUNC_PROP_GET(html_media_get_controls)
GF_FieldInfo info;
HTML_MEDIA_JS_START
if (gf_node_get_attribute_by_name(n, "controls", GF_XMLNS_SVG, GF_TRUE, GF_TRUE, &info)==GF_OK) {
char *szAtt = gf_svg_dump_attribute(n, &info);
if (!strcmp(szAtt, "true") || !strcmp(szAtt, "TRUE")) {
*vp =( BOOLEAN_TO_JSVAL( JS_TRUE ) );
} else {
*vp =( BOOLEAN_TO_JSVAL( JS_FALSE ) );
}
if (szAtt) gf_free(szAtt);
}
return JS_TRUE;
}
static SMJS_FUNC_PROP_SET(html_media_set_controls)
HTML_MEDIA_JS_START
if (JSVAL_CHECK_STRING(*vp)) {
char *str = SMJS_CHARS(c, *vp);
gf_svg_set_attributeNS(n, GF_XMLNS_SVG, "controls", str);
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SVG_audio_stack *html_media_get_audio_stack(GF_Node *n) {
SVG_video_stack *video_stack = NULL;
SVG_audio_stack *audio_stack = NULL;
if (n->sgprivate->tag == TAG_SVG_video) {
video_stack = (SVG_video_stack *)n->sgprivate->UserPrivate;
if (video_stack->audio) {
audio_stack = (SVG_audio_stack *)video_stack->audio->sgprivate->UserPrivate;
}
} else if (n->sgprivate->tag == TAG_SVG_audio) {
audio_stack = (SVG_audio_stack *)n->sgprivate->UserPrivate;
}
return audio_stack;
}
static SMJS_FUNC_PROP_GET(html_media_get_volume)
Fixed volume = FIX_ONE;
SVG_audio_stack *audio_stack = NULL;
HTML_MEDIA_JS_CHECK
audio_stack = html_media_get_audio_stack(n);
if (audio_stack) {
audio_stack->input.input_ifce.GetChannelVolume(&audio_stack->input.input_ifce.callback, &volume);
}
*vp = DOUBLE_TO_JSVAL(JS_NewDouble(c, FIX2FLT(volume)));
return JS_TRUE;
}
static SMJS_FUNC_PROP_SET(html_media_set_volume)
jsdouble volume;
SVG_audio_stack *audio_stack = NULL;
HTML_MEDIA_JS_CHECK
audio_stack = html_media_get_audio_stack(n);
if (audio_stack) {
JS_ValueToNumber(c, *vp, &volume);
audio_stack->input.intensity = FLT2FIX(volume);
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SMJS_FUNC_PROP_GET(html_media_get_muted)
SVG_audio_stack *audio_stack = NULL;
HTML_MEDIA_JS_CHECK
audio_stack = html_media_get_audio_stack(n);
if (audio_stack) {
*vp = BOOLEAN_TO_JSVAL(audio_stack->input.is_muted ? JS_TRUE : JS_FALSE);
} else {
*vp =( BOOLEAN_TO_JSVAL( JS_FALSE ) );
}
return JS_TRUE;
}
static SMJS_FUNC_PROP_SET(html_media_set_muted)
SVG_audio_stack *audio_stack = NULL;
HTML_MEDIA_JS_CHECK
audio_stack = html_media_get_audio_stack(n);
if (audio_stack) {
audio_stack->input.is_muted = (JSVAL_TO_BOOLEAN(*vp) == JS_TRUE ? GF_TRUE : GF_FALSE);
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SMJS_FUNC_PROP_GET(html_media_get_default_muted)
GF_FieldInfo info;
HTML_MEDIA_JS_START
if (gf_node_get_attribute_by_name(n, "muted", GF_XMLNS_SVG, GF_TRUE, GF_TRUE, &info)==GF_OK) {
char *szAtt = gf_svg_dump_attribute(n, &info);
if (!strcmp(szAtt, "true") || !strcmp(szAtt, "TRUE")) {
*vp =( BOOLEAN_TO_JSVAL( JS_TRUE ) );
} else {
*vp =( BOOLEAN_TO_JSVAL( JS_FALSE ) );
}
if (szAtt) gf_free(szAtt);
} else {
*vp =( BOOLEAN_TO_JSVAL( JS_FALSE ) );
}
return JS_TRUE;
}
static SMJS_FUNC_PROP_SET(html_media_set_default_muted)
HTML_MEDIA_JS_START
if (JSVAL_CHECK_STRING(*vp)) {
char *str = SMJS_CHARS(c, *vp);
gf_svg_set_attributeNS(n, GF_XMLNS_SVG, "muted", str);
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SMJS_FUNC_PROP_GET(html_media_get_audio_tracks)
HTML_MEDIA_JS_START
*vp =( OBJECT_TO_JSVAL( me->audioTracks._this ) );
return JS_TRUE;
}
static SMJS_FUNC_PROP_GET(html_media_get_video_tracks)
HTML_MEDIA_JS_START
*vp =( OBJECT_TO_JSVAL( me->videoTracks._this ) );
return JS_TRUE;
}
static SMJS_FUNC_PROP_GET(html_media_get_text_tracks)
HTML_MEDIA_JS_START
*vp =( OBJECT_TO_JSVAL( me->textTracks._this ) );
return JS_TRUE;
}
static SMJS_FUNC_PROP_GET(html_time_ranges_get_length)
GF_HTML_MediaTimeRanges *timeranges;
if (!GF_JS_InstanceOf(c, obj, &html_media_rt->timeRangesClass, NULL)) {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
timeranges = (GF_HTML_MediaTimeRanges *)SMJS_GET_PRIVATE(c, obj);
*vp = INT_TO_JSVAL( gf_list_count(timeranges->times)/2);
return JS_TRUE;
}
static JSBool SMJS_FUNCTION(html_time_ranges_start)
{
GF_HTML_MediaTimeRanges *timeranges;
SMJS_OBJ
SMJS_ARGS
if ((argc!=1) || !GF_JS_InstanceOf(c, obj, &html_media_rt->timeRangesClass, NULL)) {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
timeranges = (GF_HTML_MediaTimeRanges *)SMJS_GET_PRIVATE(c, obj);
if (!timeranges) {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
if (JSVAL_IS_INT(argv[0])) {
u32 i = JSVAL_TO_INT(argv[0]);
u64 *start_value = (u64 *)gf_list_get(timeranges->times, 2*i);
if (!start_value) {
return dom_throw_exception(c, GF_DOM_EXC_INDEX_SIZE_ERR);
} else {
SMJS_SET_RVAL(DOUBLE_TO_JSVAL(JS_NewDouble(c, (*start_value)*1.0/timeranges->timescale)));
}
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
return JS_TRUE;
}
static JSBool SMJS_FUNCTION(html_time_ranges_end)
{
GF_HTML_MediaTimeRanges *timeranges;
SMJS_OBJ
SMJS_ARGS
if ((argc!=1) || !GF_JS_InstanceOf(c, obj, &html_media_rt->timeRangesClass, NULL)) {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
timeranges = (GF_HTML_MediaTimeRanges *)SMJS_GET_PRIVATE(c, obj);
if (!timeranges) {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
if (JSVAL_IS_INT(argv[0])) {
u32 i = JSVAL_TO_INT(argv[0]);
u64 *end_value = (u64 *)gf_list_get(timeranges->times, 2*i+1);
if (!end_value) {
return dom_throw_exception(c, GF_DOM_EXC_INDEX_SIZE_ERR);
} else {
SMJS_SET_RVAL(DOUBLE_TO_JSVAL(JS_NewDouble(c, (*end_value)*1.0/timeranges->timescale)));
}
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
return JS_TRUE;
}
static Bool html_is_track_list(JSContext *c, JSObject *obj) {
if (GF_JS_InstanceOf(c, obj, &html_media_rt->videoTrackListClass, NULL)) return GF_TRUE;
if (GF_JS_InstanceOf(c, obj, &html_media_rt->audioTrackListClass, NULL)) return GF_TRUE;
if (GF_JS_InstanceOf(c, obj, &html_media_rt->textTrackListClass, NULL)) return GF_TRUE;
return GF_FALSE;
}
static SMJS_FUNC_PROP_GET(html_track_list_get_length)
GF_HTML_TrackList *tracklist;
if (html_is_track_list(c, obj)) {
tracklist = (GF_HTML_TrackList *)SMJS_GET_PRIVATE(c, obj);
if (tracklist) {
*vp = INT_TO_JSVAL( gf_list_count(tracklist->tracks) );
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static JSBool SMJS_FUNCTION(html_track_list_get_track_by_id)
{
SMJS_OBJ
SMJS_ARGS
if (html_is_track_list(c, obj)) {
GF_HTML_TrackList *tracklist;
GF_HTML_Track *track;
char *str;
tracklist = (GF_HTML_TrackList *)SMJS_GET_PRIVATE(c, obj);
str = SMJS_CHARS_FROM_STRING(c, JS_ValueToString(c, argv[0]) );
track = html_media_tracklist_get_track(tracklist, str);
SMJS_FREE(c, str);
if (track) {
SMJS_SET_RVAL(OBJECT_TO_JSVAL(track->_this));
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SMJS_FUNC_PROP_GET(html_track_list_get_property)
if (html_is_track_list(c, obj)) {
GF_HTML_TrackList *tracklist;
s32 index;
tracklist = (GF_HTML_TrackList *)SMJS_GET_PRIVATE(c, obj);
index = SMJS_ID_TO_INT(id);
if (index >= 0 && (u32)index < gf_list_count(tracklist->tracks)) {
GF_HTML_Track *track = (GF_HTML_Track *)gf_list_get(tracklist->tracks, (u32)index);
*vp = OBJECT_TO_JSVAL(track->_this);
}
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SMJS_FUNC_PROP_GET(html_track_list_get_selected_index)
if (html_is_track_list(c, obj)) {
GF_HTML_TrackList *tracklist = (GF_HTML_TrackList *)SMJS_GET_PRIVATE(c, obj);
*vp = INT_TO_JSVAL(tracklist->selected_index);
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SMJS_FUNC_PROP_GET(html_track_list_get_onchange)
if (html_is_track_list(c, obj)) {
GF_HTML_TrackList *tracklist = (GF_HTML_TrackList *)SMJS_GET_PRIVATE(c, obj);
if (! JSVAL_IS_NULL(tracklist->onchange)) {
*vp = tracklist->onchange;
} else {
*vp = JSVAL_NULL;
}
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
JSBool gf_set_js_eventhandler(JSContext *c, jsval vp, jsval *callbackfuncval);
static SMJS_FUNC_PROP_SET(html_track_list_set_onchange)
if (html_is_track_list(c, obj)) {
GF_HTML_TrackList *tracklist = (GF_HTML_TrackList *)SMJS_GET_PRIVATE(c, obj);
gf_set_js_eventhandler(c, *vp, &tracklist->onchange);
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SMJS_FUNC_PROP_GET(html_track_list_get_onaddtrack)
if (html_is_track_list(c, obj)) {
GF_HTML_TrackList *tracklist = (GF_HTML_TrackList *)SMJS_GET_PRIVATE(c, obj);
if (! JSVAL_IS_NULL(tracklist->onaddtrack)) {
*vp = tracklist->onaddtrack;
} else {
*vp = JSVAL_NULL;
}
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SMJS_FUNC_PROP_SET(html_track_list_set_onaddtrack)
if (html_is_track_list(c, obj)) {
GF_HTML_TrackList *tracklist = (GF_HTML_TrackList *)SMJS_GET_PRIVATE(c, obj);
gf_set_js_eventhandler(c, *vp, &tracklist->onaddtrack);
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SMJS_FUNC_PROP_GET(html_track_list_get_onremovetrack)
if (html_is_track_list(c, obj)) {
GF_HTML_TrackList *tracklist = (GF_HTML_TrackList *)SMJS_GET_PRIVATE(c, obj);
if (! JSVAL_IS_NULL(tracklist->onremovetrack) ) {
*vp = tracklist->onremovetrack;
} else {
*vp = JSVAL_NULL;
}
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SMJS_FUNC_PROP_SET(html_track_list_set_onremovetrack)
if (html_is_track_list(c, obj)) {
GF_HTML_TrackList *tracklist = (GF_HTML_TrackList *)SMJS_GET_PRIVATE(c, obj);
gf_set_js_eventhandler(c, *vp, &tracklist->onremovetrack);
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SMJS_FUNC_PROP_GET(html_track_get_property)
if (html_is_track_list(c, obj)) {
GF_HTML_Track *track = (GF_HTML_Track *)SMJS_GET_PRIVATE(c, obj);
if (!SMJS_ID_IS_INT(id)) {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
switch (SMJS_ID_TO_INT(id)) {
case HTML_TRACK_PROP_ID:
*vp = STRING_TO_JSVAL( JS_NewStringCopyZ(c, track->id ? track->id : "") );
return JS_TRUE;
case HTML_TRACK_PROP_KIND:
*vp = STRING_TO_JSVAL( JS_NewStringCopyZ(c, track->kind ? track->kind : "") );
return JS_TRUE;
case HTML_TRACK_PROP_LABEL:
*vp = STRING_TO_JSVAL( JS_NewStringCopyZ(c, track->label ? track->label : "") );
return JS_TRUE;
case HTML_TRACK_PROP_LANGUAGE:
*vp = STRING_TO_JSVAL( JS_NewStringCopyZ(c, track->language ? track->language : "") );
return JS_TRUE;
case HTML_TRACK_PROP_INBANDTYPE:
if (GF_JS_InstanceOf(c, obj, &html_media_rt->textTrackClass, NULL)) {
*vp = STRING_TO_JSVAL( JS_NewStringCopyZ(c, track->mime ? track->mime : "") );
return JS_TRUE;
}
case HTML_TRACK_PROP_SELECTED:
if (GF_JS_InstanceOf(c, obj, &html_media_rt->videoTrackClass, NULL)) {
*vp = BOOLEAN_TO_JSVAL(track->enabled_or_selected ? JS_TRUE : JS_FALSE);
}
return JS_TRUE;
case HTML_TRACK_PROP_ENABLED:
if (GF_JS_InstanceOf(c, obj, &html_media_rt->audioTrackClass, NULL)) {
*vp = BOOLEAN_TO_JSVAL(track->enabled_or_selected ? JS_TRUE : JS_FALSE);
}
return JS_TRUE;
}
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SMJS_FUNC_PROP_SET(html_track_set_property)
if (html_is_track_list(c, obj)) {
GF_HTML_Track *track = (GF_HTML_Track *)SMJS_GET_PRIVATE(c, obj);
if (!SMJS_ID_IS_INT(id)) {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
switch (SMJS_ID_TO_INT(id)) {
case HTML_TRACK_PROP_SELECTED:
if (GF_JS_InstanceOf(c, obj, &html_media_rt->videoTrackClass, NULL))
{
track->enabled_or_selected = (JSVAL_TO_BOOLEAN(*vp) == JS_TRUE ? GF_TRUE : GF_FALSE);
}
return JS_TRUE;
case HTML_TRACK_PROP_ENABLED:
if (GF_JS_InstanceOf(c, obj, &html_media_rt->audioTrackClass, NULL))
{
track->enabled_or_selected = (JSVAL_TO_BOOLEAN(*vp) == JS_TRUE ? GF_TRUE : GF_FALSE);
}
return JS_TRUE;
}
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SMJS_FUNC_PROP_GET(html_video_get_property)
if (GF_JS_InstanceOf(c, obj, &html_media_rt->htmlVideoElementClass, NULL))
{
GF_FieldInfo info;
SVG_video_stack *video;
GF_Node *n = (GF_Node *)SMJS_GET_PRIVATE(c, obj);
if (!n) return JS_TRUE;
video = (SVG_video_stack *)n->sgprivate->UserPrivate;
if (!SMJS_ID_IS_INT(id)) {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
switch (SMJS_ID_TO_INT(id)) {
case HTML_VIDEO_PROP_WIDTH:
if (gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_width, GF_TRUE, GF_TRUE, &info)==GF_OK) {
SVG_Length *length;
length = (SVG_Length *)info.far_ptr;
*vp = INT_TO_JSVAL( FIX2FLT(length->value) );
}
return JS_TRUE;
case HTML_VIDEO_PROP_HEIGHT:
if (gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_height, GF_TRUE, GF_TRUE, &info)==GF_OK) {
SVG_Length *length;
length = (SVG_Length *)info.far_ptr;
*vp = INT_TO_JSVAL( FIX2FLT(length->value) );
}
return JS_TRUE;
case HTML_VIDEO_PROP_VIDEOWIDTH:
*vp = INT_TO_JSVAL( video->txh.width );
return JS_TRUE;
case HTML_VIDEO_PROP_VIDEOHEIGHT:
*vp = INT_TO_JSVAL( video->txh.height );
return JS_TRUE;
case HTML_VIDEO_PROP_POSTER:
if (gf_node_get_attribute_by_name(n, "poster", GF_XMLNS_SVG, GF_TRUE, GF_TRUE, &info)==GF_OK) {
char *szAtt = gf_svg_dump_attribute(n, &info);
*vp = STRING_TO_JSVAL( JS_NewStringCopyZ(c, szAtt) );
if (szAtt) gf_free(szAtt);
}
return JS_TRUE;
}
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static SMJS_FUNC_PROP_SET(html_video_set_property)
if (GF_JS_InstanceOf(c, obj, &html_media_rt->htmlVideoElementClass, NULL))
{
GF_Node *n = (GF_Node *)SMJS_GET_PRIVATE(c, obj);
if (!SMJS_ID_IS_INT(id)) {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
switch (SMJS_ID_TO_INT(id)) {
case HTML_VIDEO_PROP_WIDTH:
return JS_TRUE;
case HTML_VIDEO_PROP_HEIGHT:
return JS_TRUE;
case HTML_VIDEO_PROP_POSTER:
{
char *str = SMJS_CHARS_FROM_STRING(c, JS_ValueToString(c, *vp) );
gf_svg_set_attributeNS(n, GF_XMLNS_SVG, "poster", str);
SMJS_FREE(c, str);
return JS_TRUE;
}
}
return JS_TRUE;
} else {
return dom_throw_exception(c, GF_DOM_EXC_INVALID_ACCESS_ERR);
}
}
static JSBool SMJS_FUNCTION(html_media_event_add_listener)
{
JSBool SMJS_FUNCTION_EXT(gf_sg_js_event_add_listener, GF_Node *vrml_node);
return gf_sg_js_event_add_listener(SMJS_CALL_ARGS, NULL);
}
static JSBool SMJS_FUNCTION(html_media_event_remove_listener)
{
JSBool SMJS_FUNCTION_EXT(gf_sg_js_event_remove_listener, GF_Node *vrml_node);
return gf_sg_js_event_remove_listener(SMJS_CALL_ARGS, NULL);
}
static JSBool SMJS_FUNCTION(html_media_event_dispatch)
{
return JS_TRUE;
}
void html_media_source_init_js_api(JSContext *js_ctx, JSObject *global, GF_HTML_MediaRuntime *html_media_rt);
void html_media_js_api_del() {
if (html_media_rt) {
gf_free(html_media_rt);
html_media_rt = NULL;
}
}
void html_media_init_js_api(GF_SceneGraph *scene) {
if (!html_media_rt) {
GF_SAFEALLOC(html_media_rt, GF_HTML_MediaRuntime);
JS_SETUP_CLASS(html_media_rt->mediaErrorClass, "MediaError", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub_forSetter, JS_FinalizeStub);
{
JSPropertySpec mediaErrorClassProps[] = {
{"MEDIA_ERR_ABORTED", MEDIA_ERROR_PROP_ABORTED, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_error_get_code, 0},
{"MEDIA_ERR_NETWORK", MEDIA_ERROR_PROP_NETWORK, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_error_get_code, 0},
{"MEDIA_ERR_DECODE", MEDIA_ERROR_PROP_DECODE, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_error_get_code, 0},
{"MEDIA_ERR_SRC_NOT_SUPPORTED", MEDIA_ERROR_PROP_SRC_NOT_SUPPORTED, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_error_get_code, 0},
{"code", MEDIA_ERROR_PROP_CODE, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_error_get_code, 0},
{0, 0, 0, 0, 0}
};
JSFunctionSpec mediaErrorClassFuncs[] = {
SMJS_FUNCTION_SPEC(0, 0, 0)
};
GF_JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &html_media_rt->mediaErrorClass, 0, 0, mediaErrorClassProps, mediaErrorClassFuncs, 0, 0);
GF_LOG(GF_LOG_DEBUG, GF_LOG_SCRIPT, ("[HTMLMediaAPI] MediaError class initialized\n"));
}
JS_SETUP_CLASS(html_media_rt->timeRangesClass, "TimeRanges", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub_forSetter, JS_FinalizeStub);
{
JSPropertySpec timeRangesClassProps[] = {
{"length", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_time_ranges_get_length, 0},
{0, 0, 0, 0, 0}
};
JSFunctionSpec timeRangesClassFuncs[] = {
SMJS_FUNCTION_SPEC("start", html_time_ranges_start, 1),
SMJS_FUNCTION_SPEC("end", html_time_ranges_end, 1),
SMJS_FUNCTION_SPEC(0, 0, 0)
};
GF_JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &html_media_rt->timeRangesClass, 0, 0, timeRangesClassProps, timeRangesClassFuncs, 0, 0);
GF_LOG(GF_LOG_DEBUG, GF_LOG_SCRIPT, ("[HTMLMediaAPI] TimeRanges class initialized\n"));
}
JS_SETUP_CLASS(html_media_rt->audioTrackClass, "AudioTrack", JSCLASS_HAS_PRIVATE, html_track_get_property, html_track_set_property, JS_FinalizeStub);
{
JSPropertySpec audioTrackClassProps[] = {
{"id", HTML_TRACK_PROP_ID, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
{"kind", HTML_TRACK_PROP_KIND, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
{"label", HTML_TRACK_PROP_LABEL, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
{"language", HTML_TRACK_PROP_LANGUAGE, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
{"enabled", HTML_TRACK_PROP_SELECTED, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
{0, 0, 0, 0, 0}
};
JSFunctionSpec audioTrackClassFuncs[] = {
SMJS_FUNCTION_SPEC(0, 0, 0)
};
GF_JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &html_media_rt->audioTrackClass, 0, 0, audioTrackClassProps, audioTrackClassFuncs, 0, 0);
GF_LOG(GF_LOG_DEBUG, GF_LOG_SCRIPT, ("[HTMLMediaAPI] AudioTrack class initialized\n"));
}
JS_SETUP_CLASS(html_media_rt->videoTrackClass, "VideoTrack", JSCLASS_HAS_PRIVATE, html_track_get_property, html_track_set_property, JS_FinalizeStub);
{
JSPropertySpec videoTrackClassProps[] = {
{"id", HTML_TRACK_PROP_ID, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
{"kind", HTML_TRACK_PROP_KIND, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
{"label", HTML_TRACK_PROP_LABEL, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
{"language", HTML_TRACK_PROP_LANGUAGE, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
{"selected", HTML_TRACK_PROP_SELECTED, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, 0, 0},
{0, 0, 0, 0, 0}
};
JSFunctionSpec videoTrackClassFuncs[] = {
SMJS_FUNCTION_SPEC(0, 0, 0)
};
GF_JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &html_media_rt->videoTrackClass, 0, 0, videoTrackClassProps, videoTrackClassFuncs, 0, 0);
GF_LOG(GF_LOG_DEBUG, GF_LOG_SCRIPT, ("[HTMLMediaAPI] VideoTrack class initialized\n"));
}
JS_SETUP_CLASS(html_media_rt->textTrackClass, "TextTrack", JSCLASS_HAS_PRIVATE, html_track_get_property, html_track_set_property, JS_FinalizeStub);
{
JSPropertySpec textTrackClassProps[] = {
{"id", HTML_TRACK_PROP_ID, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
{"kind", HTML_TRACK_PROP_KIND, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
{"label", HTML_TRACK_PROP_LABEL, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
{"language", HTML_TRACK_PROP_LANGUAGE, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
{"inBandMetadataTrackDispatchType", HTML_TRACK_PROP_INBANDTYPE, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
{0, 0, 0, 0, 0}
};
JSFunctionSpec textTrackClassFuncs[] = {
SMJS_FUNCTION_SPEC(0, 0, 0)
};
GF_JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &html_media_rt->textTrackClass, 0, 0, textTrackClassProps, textTrackClassFuncs, 0, 0);
GF_LOG(GF_LOG_DEBUG, GF_LOG_SCRIPT, ("[HTMLMediaAPI] TextTrack class initialized\n"));
}
JS_SETUP_CLASS(html_media_rt->audioTrackListClass, "AudioTrackList", JSCLASS_HAS_PRIVATE, html_track_list_get_property, JS_PropertyStub_forSetter, JS_FinalizeStub);
{
JSPropertySpec audioTrackListClassProps[] = {
{"length", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_track_list_get_length, 0},
{"onchange", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, html_track_list_get_onchange, html_track_list_set_onchange},
{"onaddtrack", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, html_track_list_get_onaddtrack, html_track_list_set_onaddtrack},
{"onremovetrack", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, html_track_list_get_onremovetrack, html_track_list_set_onremovetrack},
{0, 0, 0, 0, 0}
};
JSFunctionSpec audioTrackListClassFuncs[] = {
SMJS_FUNCTION_SPEC("getTrackById", html_track_list_get_track_by_id, 1),
SMJS_FUNCTION_SPEC(0, 0, 0)
};
GF_JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &html_media_rt->audioTrackListClass, 0, 0, audioTrackListClassProps, audioTrackListClassFuncs, 0, 0);
GF_LOG(GF_LOG_DEBUG, GF_LOG_SCRIPT, ("[HTMLMediaAPI] AudioTrackList class initialized\n"));
}
JS_SETUP_CLASS(html_media_rt->videoTrackListClass, "VideoTrackList", JSCLASS_HAS_PRIVATE, html_track_list_get_property, JS_PropertyStub_forSetter, JS_FinalizeStub);
{
JSPropertySpec videoTrackListClassProps[] = {
{"selectedIndex", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_track_list_get_selected_index, 0},
{"length", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_track_list_get_length, 0},
{"onchange", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, html_track_list_get_onchange, html_track_list_set_onchange},
{"onaddtrack", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, html_track_list_get_onaddtrack, html_track_list_set_onaddtrack},
{"onremovetrack", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, html_track_list_get_onremovetrack, html_track_list_set_onremovetrack},
{0, 0, 0, 0, 0}
};
JSFunctionSpec videoTrackListClassFuncs[] = {
SMJS_FUNCTION_SPEC("getTrackById", html_track_list_get_track_by_id, 1),
SMJS_FUNCTION_SPEC(0, 0, 0)
};
GF_JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &html_media_rt->videoTrackListClass, 0, 0, videoTrackListClassProps, videoTrackListClassFuncs, 0, 0);
GF_LOG(GF_LOG_DEBUG, GF_LOG_SCRIPT, ("[HTMLMediaAPI] VideoTrackList class initialized\n"));
}
JS_SETUP_CLASS(html_media_rt->textTrackListClass, "TextTrackList", JSCLASS_HAS_PRIVATE, html_track_list_get_property, JS_PropertyStub_forSetter, JS_FinalizeStub);
{
JSPropertySpec textTrackListClassProps[] = {
{"length", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_track_list_get_length, 0},
{"onaddtrack", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, html_track_list_get_onaddtrack, html_track_list_set_onaddtrack},
{"onremovetrack", 0, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, html_track_list_get_onremovetrack, html_track_list_set_onremovetrack},
{0, 0, 0, 0, 0}
};
JSFunctionSpec textTrackListClassFuncs[] = {
SMJS_FUNCTION_SPEC("getTrackById", html_track_list_get_track_by_id, 1),
SMJS_FUNCTION_SPEC(0, 0, 0)
};
GF_JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &html_media_rt->textTrackListClass, 0, 0, textTrackListClassProps, textTrackListClassFuncs, 0, 0);
GF_LOG(GF_LOG_DEBUG, GF_LOG_SCRIPT, ("[HTMLMediaAPI] TextTrackList class initialized\n"));
}
JS_SETUP_CLASS(html_media_rt->mediaControllerClass, "MediaController", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub_forSetter, JS_FinalizeStub);
{
JSPropertySpec mediaControllerClassProps[] = {
{0, 0, 0, 0, 0}
};
JSFunctionSpec mediaControllerClassFuncs[] = {
SMJS_FUNCTION_SPEC(0, 0, 0)
};
GF_JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, 0, &html_media_rt->mediaControllerClass, 0, 0, mediaControllerClassProps, mediaControllerClassFuncs, 0, 0);
GF_LOG(GF_LOG_DEBUG, GF_LOG_SCRIPT, ("[HTMLMediaAPI] MediaController class initialized\n"));
}
JS_SETUP_CLASS(html_media_rt->htmlMediaElementClass, "HTMLMediaElement", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub_forSetter, JS_FinalizeStub);
{
JSPropertySpec htmlMediaElementClassProps[] = {
{"error", HTML_MEDIA_PROP_ERROR, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_error, 0},
{"src", HTML_MEDIA_PROP_SRC, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED , html_media_get_src, html_media_set_src},
{"currentSrc", HTML_MEDIA_PROP_CURRENTSRC, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_src, 0},
{"crossOrigin", HTML_MEDIA_PROP_CROSSORIGIN, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, html_media_get_cors, html_media_set_cors},
{"NETWORK_EMPTY", HTML_MEDIA_PROP_NETWORK_EMPTY, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_const, 0},
{"NETWORK_IDLE", HTML_MEDIA_PROP_NETWORK_IDLE, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_const, 0},
{"NETWORK_LOADING", HTML_MEDIA_PROP_NETWORK_LOADING, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_const, 0},
{"NETWORK_NO_SOURCE", HTML_MEDIA_PROP_NETWORK_NO_SOURCE,JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_const, 0},
{"networkState", HTML_MEDIA_PROP_NETWORKSTATE, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_network_state, 0},
{"preload", HTML_MEDIA_PROP_PRELOAD, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, html_media_get_preload, html_media_set_preload},
{"buffered", HTML_MEDIA_PROP_BUFFERED, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_buffered, 0},
{"HAVE_NOTHING", HTML_MEDIA_PROP_HAVE_NOTHING, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_const, 0},
{"HAVE_METADATA", HTML_MEDIA_PROP_HAVE_METADATA, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_const, 0},
{"HAVE_CURRENT_DATA", HTML_MEDIA_PROP_HAVE_CURRENT_DATA, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_const, 0},
{"HAVE_FUTURE_DATA", HTML_MEDIA_PROP_HAVE_FUTURE_DATA, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_const, 0},
{"HAVE_ENOUGH_DATA", HTML_MEDIA_PROP_HAVE_ENOUGH_DATA, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_const, 0},
{"readyState", HTML_MEDIA_PROP_READYSTATE, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_ready_state, 0},
{"seeking", HTML_MEDIA_PROP_SEEKING, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_seeking, 0},
{"currentTime", HTML_MEDIA_PROP_CURRENTTIME, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, html_media_get_current_time, html_media_set_current_time},
{"duration", HTML_MEDIA_PROP_DURATION, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_duration, 0},
{"startDate", HTML_MEDIA_PROP_STARTDATE, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_start_date, 0},
{"paused", HTML_MEDIA_PROP_PAUSED, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_paused, 0},
{"defaultPlaybackRate", HTML_MEDIA_PROP_DEFAULTPLAYBACKRATE, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, html_media_get_default_playback_rate, html_media_set_default_playback_rate},
{"playbackRate", HTML_MEDIA_PROP_PLAYBACKRATE, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, html_media_get_playback_rate, html_media_set_playback_rate},
{"played", HTML_MEDIA_PROP_PLAYED, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_played, 0},
{"seekable", HTML_MEDIA_PROP_SEEKABLE, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_seekable, 0},
{"ended", HTML_MEDIA_PROP_ENDED, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_ended, 0},
{"autoplay", HTML_MEDIA_PROP_AUTOPLAY, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, html_media_get_autoplay, html_media_set_autoplay},
{"loop", HTML_MEDIA_PROP_LOOP, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, html_media_get_loop, html_media_set_loop},
{"mediaGroup", HTML_MEDIA_PROP_MEDIAGROUP, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, html_media_get_mediagroup, html_media_set_mediagroup},
{"controller", HTML_MEDIA_PROP_CONTROLLER, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, html_media_get_controller, html_media_set_controller},
{"controls", HTML_MEDIA_PROP_CONTROLS, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, html_media_get_controls, html_media_set_controls},
{"volume", HTML_MEDIA_PROP_VOLUME, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, html_media_get_volume, html_media_set_volume},
{"muted", HTML_MEDIA_PROP_MUTED, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, html_media_get_muted, html_media_set_muted},
{"defaultMuted", HTML_MEDIA_PROP_DEFAULTMUTED, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED, html_media_get_default_muted, html_media_set_default_muted},
{"audioTracks", HTML_MEDIA_PROP_AUDIOTRACKS, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_audio_tracks, 0},
{"videoTracks", HTML_MEDIA_PROP_VIDEOTRACKS, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_video_tracks, 0},
{"textTracks", HTML_MEDIA_PROP_TEXTTRACKS, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, html_media_get_text_tracks, 0},
{0, 0, 0, 0, 0}
};
JSBool SMJS_FUNCTION(svg_udom_smil_pause);
JSBool SMJS_FUNCTION(svg_udom_smil_begin);
JSBool SMJS_FUNCTION(svg_udom_smil_end);
JSFunctionSpec htmlMediaElementClassFuncs[] = {
SMJS_FUNCTION_SPEC("load", html_media_load, 0),
SMJS_FUNCTION_SPEC("canPlayType", html_media_canPlayType, 1),
SMJS_FUNCTION_SPEC("fastSeek", html_media_fastSeek, 1),
SMJS_FUNCTION_SPEC("play", svg_udom_smil_begin, 0),
SMJS_FUNCTION_SPEC("pause", svg_udom_smil_pause, 0),
SMJS_FUNCTION_SPEC("addTextTrack", html_media_addTextTrack, 1),
SMJS_FUNCTION_SPEC("addEventListener", html_media_event_add_listener, 3),
SMJS_FUNCTION_SPEC("removeEventListener", html_media_event_remove_listener, 3),
SMJS_FUNCTION_SPEC("dispatchEvent", html_media_event_dispatch, 1),
SMJS_FUNCTION_SPEC(0, 0, 0)
};
JSObject *elt_proto = dom_js_get_element_proto(scene->svg_js->js_ctx);
GF_JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, elt_proto, &html_media_rt->htmlMediaElementClass, 0, 0, htmlMediaElementClassProps, htmlMediaElementClassFuncs, 0, 0);
GF_LOG(GF_LOG_DEBUG, GF_LOG_SCRIPT, ("[HTMLMediaAPI] HTMLMediaElement class initialized\n"));
}
JS_SETUP_CLASS(html_media_rt->htmlVideoElementClass, "HTMLVideoElement", JSCLASS_HAS_PRIVATE, html_video_get_property, html_video_set_property, dom_element_finalize);
{
JSPropertySpec htmlVideoElementClassProps[] = {
{"width", HTML_VIDEO_PROP_WIDTH, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED , 0, 0},
{"height", HTML_VIDEO_PROP_HEIGHT, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED , 0, 0},
{"videoWidth", HTML_VIDEO_PROP_VIDEOWIDTH, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
{"videoHeight", HTML_VIDEO_PROP_VIDEOHEIGHT, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_READONLY, 0, 0},
{"poster", HTML_VIDEO_PROP_POSTER, JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED , 0, 0},
{0, 0, 0, 0, 0}
};
JSFunctionSpec htmlVideoElementClassFuncs[] = {
SMJS_FUNCTION_SPEC(0, 0, 0)
};
GF_JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, html_media_rt->htmlMediaElementClass._proto, &html_media_rt->htmlVideoElementClass, 0, 0, htmlVideoElementClassProps, htmlVideoElementClassFuncs, 0, 0);
GF_LOG(GF_LOG_DEBUG, GF_LOG_SCRIPT, ("[HTMLMediaAPI] HTMLVideoElement class initialized\n"));
}
JS_SETUP_CLASS(html_media_rt->htmlAudioElementClass, "HTMLAudioElement", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub_forSetter, dom_element_finalize);
{
JSPropertySpec htmlAudioElementClassProps[] = {
{0, 0, 0, 0, 0}
};
JSFunctionSpec htmlAudioElementClassFuncs[] = {
SMJS_FUNCTION_SPEC(0, 0, 0)
};
GF_JS_InitClass(scene->svg_js->js_ctx, scene->svg_js->global, html_media_rt->htmlMediaElementClass._proto, &html_media_rt->htmlAudioElementClass, 0, 0, htmlAudioElementClassProps, htmlAudioElementClassFuncs, 0, 0);
GF_LOG(GF_LOG_DEBUG, GF_LOG_SCRIPT, ("[HTMLMediaAPI] HTMLAudioElement class initialized\n"));
}
html_media_source_init_js_api(scene->svg_js->js_ctx, scene->svg_js->global, html_media_rt);
}
}
#endif
#endif