Commit a593fa18 authored by Damien Fouilleul's avatar Damien Fouilleul

all: rewrite of mozilla plugin

- added a couple of support APIs in libvlc
- retired XPCOM interface, all scripting now goes through NPObject apis
- new APIs using libvlc (roughly similar to java bindings)
parent faef0357
......@@ -275,7 +275,8 @@ enum output_query_e
VOUT_REPARENT,
VOUT_SNAPSHOT,
VOUT_CLOSE,
VOUT_SET_FOCUS /* arg1= vlc_bool_t res= */
VOUT_SET_FOCUS, /* arg1= vlc_bool_t res= */
VOUT_SET_VIEWPORT /* arg1= view rect, arg2=clip rect, res= */
};
/**
......
......@@ -356,7 +356,7 @@ void libvlc_video_resize( libvlc_input_t *, int, int, libvlc_exception_t *);
typedef int libvlc_drawable_t;
/**
* Get current mute status
* change the video output parent
* \param p_instance libvlc instance
* \param drawable the new parent window (Drawable on X11, CGrafPort on MacOSX, HWND on Win32)
* \param p_exception an initialized exception
......@@ -364,6 +364,45 @@ typedef int libvlc_drawable_t;
*/
int libvlc_video_reparent( libvlc_input_t *, libvlc_drawable_t, libvlc_exception_t * );
/**
* Set the video output parent
* \param p_instance libvlc instance
* \param drawable the new parent window (Drawable on X11, CGrafPort on MacOSX, HWND on Win32)
* \param p_exception an initialized exception
*/
void libvlc_video_set_parent( libvlc_instance_t *, libvlc_drawable_t, libvlc_exception_t * );
/**
* Set the video output size
* \param p_instance libvlc instance
* \param width new width for video drawable
* \param height new height for video drawable
* \param p_exception an initialized exception
*/
void libvlc_video_set_size( libvlc_instance_t *, int, int, libvlc_exception_t * );
/**
* Downcast to this general type as placeholder for a platform specific one, such as:
* Drawable on X11,
* CGrafPort on MacOSX,
* HWND on win32
*/
typedef struct
{
int top, left;
int bottom, right;
}
libvlc_rectangle_t;
/**
* Set the video output viewport for a windowless video ouput (MacOS X only)
* \param p_instance libvlc instance
* \param view coordinates within video drawable
* \param clip coordinates within video drawable
* \param p_exception an initialized exception
*/
void libvlc_video_set_viewport( libvlc_instance_t *, const libvlc_rectangle_t *, const libvlc_rectangle_t *, libvlc_exception_t * );
/** @} */
......@@ -380,6 +419,14 @@ int libvlc_video_reparent( libvlc_input_t *, libvlc_drawable_t, libvlc_exception
* @{
*/
/**
* Toggle mute status
* \param p_instance libvlc instance
* \param p_exception an initialized exception
* \return void
*/
void libvlc_audio_toggle_mute( libvlc_instance_t *, libvlc_exception_t * );
/**
* Get current mute status
* \param p_instance libvlc instance
......
......@@ -86,11 +86,9 @@ static void Unlock ( vout_thread_t * p_vout );
static int aglInit ( vout_thread_t * p_vout );
static void aglEnd ( vout_thread_t * p_vout );
static int aglManage ( vout_thread_t * p_vout );
static int aglControl( vout_thread_t *, int, va_list );
static void aglSwap ( vout_thread_t * p_vout );
static int DrawableRedraw( vlc_object_t *p_this, const char *psz_name,
vlc_value_t oval, vlc_value_t nval, void *param);
int E_(OpenVideoGL) ( vlc_object_t * p_this )
{
vout_thread_t * p_vout = (vout_thread_t *) p_this;
......@@ -131,19 +129,11 @@ int E_(OpenVideoGL) ( vlc_object_t * p_this )
AGL_DEPTH_SIZE, 24,
AGL_NONE };
AGLDevice screen;
AGLPixelFormat pixFormat;
p_vout->p_sys->b_embedded = VLC_TRUE;
screen = GetGWorldDevice((CGrafPtr)value_drawable.i_int);
if( NULL == screen )
{
msg_Err( p_vout, "can't find screen device for drawable" );
return VLC_EGENERIC;
}
pixFormat = aglChoosePixelFormat(&screen, 1, ATTRIBUTES);
pixFormat = aglChoosePixelFormat(NULL, 0, ATTRIBUTES);
if( NULL == pixFormat )
{
msg_Err( p_vout, "no screen renderer available for required attributes." );
......@@ -158,8 +148,8 @@ int E_(OpenVideoGL) ( vlc_object_t * p_this )
return VLC_EGENERIC;
}
else {
// tell opengl to sync buffer swap with vertical retrace
GLint param = 1;
// tell opengl not to sync buffer swap with vertical retrace
GLint param = 0;
aglSetInteger(p_vout->p_sys->agl_ctx, AGL_SWAP_INTERVAL, &param);
aglEnable(p_vout->p_sys->agl_ctx, AGL_SWAP_INTERVAL);
}
......@@ -167,7 +157,7 @@ int E_(OpenVideoGL) ( vlc_object_t * p_this )
p_vout->pf_init = aglInit;
p_vout->pf_end = aglEnd;
p_vout->pf_manage = aglManage;
p_vout->pf_control = NULL;
p_vout->pf_control = aglControl;
p_vout->pf_swap = aglSwap;
p_vout->pf_lock = Lock;
p_vout->pf_unlock = Unlock;
......@@ -207,7 +197,6 @@ void E_(CloseVideoGL) ( vlc_object_t * p_this )
vout_thread_t * p_vout = (vout_thread_t *) p_this;
if( p_vout->p_sys->b_embedded )
{
var_DelCallback(p_vout->p_vlc, "drawableredraw", DrawableRedraw, p_vout);
aglDestroyContext(p_vout->p_sys->agl_ctx);
}
else
......@@ -456,13 +445,38 @@ static void Unlock( vout_thread_t * p_vout )
* embedded AGL context implementation
*****************************************************************************/
static void UpdateEmbeddedGeometry( vout_thread_t *p_vout );
static void aglSetViewport( vout_thread_t *p_vout, Rect viewBounds, Rect clipBounds );
static void aglReshape( vout_thread_t * p_vout );
static int aglInit( vout_thread_t * p_vout )
{
UpdateEmbeddedGeometry(p_vout);
var_AddCallback(p_vout->p_vlc, "drawableredraw", DrawableRedraw, p_vout);
vlc_value_t val;
Rect viewBounds;
Rect clipBounds;
var_Get( p_vout->p_vlc, "drawable", &val );
p_vout->p_sys->agl_drawable = (AGLDrawable)val.i_int;
aglSetDrawable(p_vout->p_sys->agl_ctx, p_vout->p_sys->agl_drawable);
var_Get( p_vout->p_vlc, "drawable-view-top", &val );
viewBounds.top = val.i_int;
var_Get( p_vout->p_vlc, "drawable-view-left", &val );
viewBounds.left = val.i_int;
var_Get( p_vout->p_vlc, "drawable-view-bottom", &val );
viewBounds.bottom = val.i_int;
var_Get( p_vout->p_vlc, "drawable-view-right", &val );
viewBounds.right = val.i_int;
var_Get( p_vout->p_vlc, "drawable-clip-top", &val );
clipBounds.top = val.i_int;
var_Get( p_vout->p_vlc, "drawable-clip-left", &val );
clipBounds.left = val.i_int;
var_Get( p_vout->p_vlc, "drawable-clip-bottom", &val );
clipBounds.bottom = val.i_int;
var_Get( p_vout->p_vlc, "drawable-clip-right", &val );
clipBounds.right = val.i_int;
aglSetViewport(p_vout, viewBounds, clipBounds);
aglSetCurrentContext(p_vout->p_sys->agl_ctx);
return VLC_SUCCESS;
......@@ -547,84 +561,80 @@ static int aglManage( vout_thread_t * p_vout )
return VLC_SUCCESS;
}
static int aglControl( vout_thread_t *p_vout, int i_query, va_list args )
{
switch( i_query )
{
case VOUT_SET_VIEWPORT:
{
Rect viewBounds, clipBounds;
viewBounds.top = va_arg( args, int);
viewBounds.left = va_arg( args, int);
viewBounds.bottom = va_arg( args, int);
viewBounds.right = va_arg( args, int);
clipBounds.top = va_arg( args, int);
clipBounds.left = va_arg( args, int);
clipBounds.bottom = va_arg( args, int);
clipBounds.right = va_arg( args, int);
aglSetViewport(p_vout, viewBounds, clipBounds);
return VLC_SUCCESS;
}
case VOUT_REPARENT:
{
AGLDrawable drawable = (AGLDrawable)va_arg( args, int);
if( drawable != p_vout->p_sys->agl_drawable )
{
p_vout->p_sys->agl_drawable = drawable;
aglSetDrawable(p_vout->p_sys->agl_ctx, drawable);
}
return VLC_SUCCESS;
}
default:
return vout_vaControlDefault( p_vout, i_query, args );
}
}
static void aglSwap( vout_thread_t * p_vout )
{
p_vout->p_sys->b_got_frame = VLC_TRUE;
aglSwapBuffers(p_vout->p_sys->agl_ctx);
}
static void UpdateEmbeddedGeometry( vout_thread_t *p_vout )
static void aglSetViewport( vout_thread_t *p_vout, Rect viewBounds, Rect clipBounds )
{
vlc_value_t val;
vlc_value_t valt, vall, valb, valr, valx, valy, valw, valh,
valportx, valporty;
Rect winBounds;
Rect clientBounds;
GLint rect[4];
var_Get( p_vout->p_vlc, "drawable", &val );
var_Get( p_vout->p_vlc, "drawablet", &valt );
var_Get( p_vout->p_vlc, "drawablel", &vall );
var_Get( p_vout->p_vlc, "drawableb", &valb );
var_Get( p_vout->p_vlc, "drawabler", &valr );
var_Get( p_vout->p_vlc, "drawablex", &valx );
var_Get( p_vout->p_vlc, "drawabley", &valy );
var_Get( p_vout->p_vlc, "drawablew", &valw );
var_Get( p_vout->p_vlc, "drawableh", &valh );
var_Get( p_vout->p_vlc, "drawableportx", &valportx );
var_Get( p_vout->p_vlc, "drawableporty", &valporty );
// mozilla plugin provides coordinates based on port bounds
// however AGL coordinates are based on window structure region
// and are vertically flipped
GLint rect[4];
CGrafPtr port = (CGrafPtr)p_vout->p_sys->agl_drawable;
Rect winBounds, clientBounds;
GetWindowBounds(GetWindowFromPort((CGrafPtr)val.i_int),
GetWindowBounds(GetWindowFromPort(port),
kWindowStructureRgn, &winBounds);
GetWindowBounds(GetWindowFromPort((CGrafPtr)val.i_int),
GetWindowBounds(GetWindowFromPort(port),
kWindowContentRgn, &clientBounds);
/* update video clipping bounds in drawable */
rect[0] = (clientBounds.left-winBounds.left)
+ vall.i_int; // from window left edge
+ clipBounds.left; // from window left edge
rect[1] = (winBounds.bottom-winBounds.top)
- (clientBounds.top-winBounds.top)
- valb.i_int; // from window bottom edge
rect[2] = valr.i_int-vall.i_int; // width
rect[3] = valb.i_int-valt.i_int; // height
- clipBounds.bottom; // from window bottom edge
rect[2] = clipBounds.right-clipBounds.left; // width
rect[3] = clipBounds.bottom-clipBounds.top; // height
aglSetInteger(p_vout->p_sys->agl_ctx, AGL_BUFFER_RECT, rect);
aglEnable(p_vout->p_sys->agl_ctx, AGL_BUFFER_RECT);
/* update video internal bounds in drawable */
p_vout->p_sys->i_offx = -vall.i_int - valportx.i_int;
p_vout->p_sys->i_offy = valb.i_int + valporty.i_int - valh.i_int;
p_vout->p_sys->i_width = valw.i_int;
p_vout->p_sys->i_height = valh.i_int;
p_vout->p_sys->i_width = viewBounds.right-viewBounds.left;
p_vout->p_sys->i_height = viewBounds.bottom-viewBounds.top;
p_vout->p_sys->i_offx = -clipBounds.left - viewBounds.left;
p_vout->p_sys->i_offy = clipBounds.bottom + viewBounds.top
- p_vout->p_sys->i_height;
if( p_vout->p_sys->agl_drawable == (AGLDrawable)val.i_int )
{
aglUpdateContext(p_vout->p_sys->agl_ctx);
}
else
{
p_vout->p_sys->agl_drawable = (AGLDrawable)val.i_int;
aglSetDrawable(p_vout->p_sys->agl_ctx, p_vout->p_sys->agl_drawable);
}
aglUpdateContext(p_vout->p_sys->agl_ctx);
aglReshape( p_vout );
}
/* If we're embedded, the application is expected to indicate a
* window change (move/resize/etc) via the "drawableredraw" value.
*/
static int DrawableRedraw( vlc_object_t *p_this, const char *psz_name,
vlc_value_t oval, vlc_value_t nval, void *param)
{
vout_thread_t *p_vout = (vout_thread_t *)param;
UpdateEmbeddedGeometry( p_vout );
return VLC_SUCCESS;
}
......@@ -4,18 +4,20 @@
noinst_LIBRARIES = $(noinst_LIBRARIES_mozilla)
MOSTLYCLEANFILES = $(npvlc_DATA) $(vlcintf_xpt_DATA)
MOSTLYCLEANFILES = $(npvlc_DATA)
CLEANFILES = stamp-pic $(BUILT_SOURCES)
EXTRA_DIST = $(DIST_sources) vlcintf.idl npvlc_rc.rc vlc.r
EXTRA_DIST = $(DIST_sources) npvlc_rc.rc vlc.r
SOURCES_mozilla_common = \
vlcshell.cpp \
vlcplugin.cpp \
vlcplugin.h \
vlcpeer.cpp \
vlcpeer.h \
vlcruntime.cpp \
vlcruntime.h \
control/npolibvlc.cpp \
control/npolibvlc.h \
control/npovlc.cpp \
control/npovlc.h \
control/nporuntime.cpp \
control/nporuntime.h \
support/classinfo.h
DIST_sources = $(SOURCES_mozilla_common) \
......@@ -141,11 +143,6 @@ endif
noinst_LIBRARIES_mozilla = libnpvlc.a
$(SOURCES_mozilla): vlcintf.h
BUILT_SOURCES = vlcintf.h
vlcintf_xpt_DATA = vlcintf.xpt
if USE_LIBTOOL
# FIXME: name is incorrect on Win32 & Darwin
npvlc_LTLIBRARIES = libvlcplugin.la
......@@ -175,15 +172,6 @@ $(npvlc): $(libnpvlc_a_OBJECTS) $(libnpvlc_a_DEPENDENCIES) stamp-pic
# Cygwin work-around
@if test -f "$@.exe"; then mv -f "$@.exe" "$@"; fi
vlcintf_xptdir = $(libdir)/mozilla/components
vlcintf.xpt: vlcintf.idl
$(XPIDL) $(XPIDL_INCL) \
-m typelib -o vlcintf $(srcdir)/vlcintf.idl
vlcintf.h: vlcintf.idl
$(XPIDL) $(XPIDL_INCL) \
-m header -o vlcintf $(srcdir)/vlcintf.idl
###############################################################################
# Stamp rules
###############################################################################
......
/*****************************************************************************
* vlc.cpp: support for NPRuntime API for Netscape Script-able plugins
* FYI: http://www.mozilla.org/projects/plugins/npruntime.html
*****************************************************************************
* Copyright (C) 2005 the VideoLAN team
*
* Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* Mozilla stuff */
#ifdef HAVE_MOZILLA_CONFIG_H
# include <mozilla-config.h>
#endif
#include "npolibvlc.h"
#include "vlcplugin.h"
/*
** implementation of libvlc root object
*/
LibvlcRootNPObject::LibvlcRootNPObject(NPP instance, const NPClass *aClass) :
RuntimeNPObject(instance, aClass)
{
static NPClass *audioClass = new RuntimeNPClass<LibvlcAudioNPObject>();
static NPClass *inputClass = new RuntimeNPClass<LibvlcInputNPObject>();
static NPClass *playlistClass = new RuntimeNPClass<LibvlcPlaylistNPObject>();
static NPClass *videoClass = new RuntimeNPClass<LibvlcVideoNPObject>();
audioObj = NPN_CreateObject(instance, audioClass);
inputObj = NPN_CreateObject(instance, inputClass);
playlistObj = NPN_CreateObject(instance, playlistClass);
videoObj = NPN_CreateObject(instance, videoClass);
}
LibvlcRootNPObject::~LibvlcRootNPObject()
{
NPN_ReleaseObject(audioObj);
NPN_ReleaseObject(inputObj);
NPN_ReleaseObject(playlistObj);
NPN_ReleaseObject(videoObj);
}
const NPUTF8 * const LibvlcRootNPObject::propertyNames[] =
{
"audio",
"input",
"playlist",
"video",
};
enum LibvlcRootNPObjectPropertyIds
{
ID_audio = 0,
ID_input,
ID_playlist,
ID_video,
};
const int LibvlcRootNPObject::propertyCount = sizeof(LibvlcRootNPObject::propertyNames)/sizeof(NPUTF8 *);
RuntimeNPObject::InvokeResult LibvlcRootNPObject::getProperty(int index, NPVariant *result)
{
switch( index )
{
case ID_audio:
OBJECT_TO_NPVARIANT(NPN_RetainObject(audioObj), *result);
return INVOKERESULT_NO_ERROR;
case ID_input:
OBJECT_TO_NPVARIANT(NPN_RetainObject(inputObj), *result);
return INVOKERESULT_NO_ERROR;
case ID_playlist:
OBJECT_TO_NPVARIANT(NPN_RetainObject(playlistObj), *result);
return INVOKERESULT_NO_ERROR;
case ID_video:
OBJECT_TO_NPVARIANT(NPN_RetainObject(videoObj), *result);
return INVOKERESULT_NO_ERROR;
}
return INVOKERESULT_GENERIC_ERROR;
}
const NPUTF8 * const LibvlcRootNPObject::methodNames[] =
{
/* no methods */
};
const int LibvlcRootNPObject::methodCount = sizeof(LibvlcRootNPObject::methodNames)/sizeof(NPUTF8 *);
/*
** implementation of libvlc audio object
*/
const NPUTF8 * const LibvlcAudioNPObject::propertyNames[] =
{
"mute",
"volume",
};
enum LibvlcAudioNPObjectPropertyIds
{
ID_mute,
ID_volume,
};
const int LibvlcAudioNPObject::propertyCount = sizeof(LibvlcAudioNPObject::propertyNames)/sizeof(NPUTF8 *);
RuntimeNPObject::InvokeResult LibvlcAudioNPObject::getProperty(int index, NPVariant *result)
{
VlcPlugin *p_plugin = reinterpret_cast<VlcPlugin *>(_instance->pdata);
if( p_plugin )
{
libvlc_exception_t ex;
libvlc_exception_init(&ex);
switch( index )
{
case ID_mute:
{
vlc_bool_t muted = libvlc_audio_get_mute(p_plugin->getVLC(), &ex);
if( libvlc_exception_raised(&ex) )
{
NPN_SetException(this, libvlc_exception_get_message(&ex));
libvlc_exception_clear(&ex);
return INVOKERESULT_GENERIC_ERROR;
}
BOOLEAN_TO_NPVARIANT(muted, *result);
return INVOKERESULT_NO_ERROR;
}
case ID_volume:
{
int volume = libvlc_audio_get_volume(p_plugin->getVLC(), &ex);
if( libvlc_exception_raised(&ex) )
{
NPN_SetException(this, libvlc_exception_get_message(&ex));
libvlc_exception_clear(&ex);
return INVOKERESULT_GENERIC_ERROR;
}
INT32_TO_NPVARIANT(volume, *result);
return INVOKERESULT_NO_ERROR;
}
}
}
return INVOKERESULT_GENERIC_ERROR;
}
RuntimeNPObject::InvokeResult LibvlcAudioNPObject::setProperty(int index, const NPVariant *value)
{
VlcPlugin *p_plugin = reinterpret_cast<VlcPlugin *>(_instance->pdata);
if( p_plugin )
{
libvlc_exception_t ex;
libvlc_exception_init(&ex);
switch( index )
{
case ID_mute:
if( NPVARIANT_IS_BOOLEAN(*value) )
{
libvlc_audio_set_mute(p_plugin->getVLC(),
NPVARIANT_TO_BOOLEAN(*value), &ex);
if( libvlc_exception_raised(&ex) )
{
NPN_SetException(this, libvlc_exception_get_message(&ex));
libvlc_exception_clear(&ex);
return INVOKERESULT_GENERIC_ERROR;
}
return INVOKERESULT_NO_ERROR;
}
return INVOKERESULT_INVALID_VALUE;
case ID_volume:
if( isNumberValue(*value) )
{
libvlc_audio_set_volume(p_plugin->getVLC(),
numberValue(*value), &ex);
if( libvlc_exception_raised(&ex) )
{
NPN_SetException(this, libvlc_exception_get_message(&ex));
libvlc_exception_clear(&ex);
return INVOKERESULT_GENERIC_ERROR;
}
return INVOKERESULT_NO_ERROR;
}
return INVOKERESULT_INVALID_VALUE;
}
}
return INVOKERESULT_GENERIC_ERROR;
}
const NPUTF8 * const LibvlcAudioNPObject::methodNames[] =
{
"togglemute",
};
enum LibvlcAudioNPObjectMethodIds
{
ID_togglemute,
};
const int LibvlcAudioNPObject::methodCount = sizeof(LibvlcAudioNPObject::methodNames)/sizeof(NPUTF8 *);
RuntimeNPObject::InvokeResult LibvlcAudioNPObject::invoke(int index, const NPVariant *args, uint32_t argCount, NPVariant *result)
{
VlcPlugin *p_plugin = reinterpret_cast<VlcPlugin *>(_instance->pdata);
if( p_plugin )
{
libvlc_exception_t ex;
libvlc_exception_init(&ex);
switch( index )
{
case ID_togglemute:
if( argCount == 0 )
{
libvlc_audio_toggle_mute(p_plugin->getVLC(), &ex);
if( libvlc_exception_raised(&ex) )
{
NPN_SetException(this, libvlc_exception_get_message(&ex));
libvlc_exception_clear(&ex);
return INVOKERESULT_GENERIC_ERROR;
}
else
{
VOID_TO_NPVARIANT(*result);
return INVOKERESULT_NO_ERROR;
}
}
return INVOKERESULT_NO_SUCH_METHOD;
default:
return INVOKERESULT_NO_SUCH_METHOD;
}
}
return INVOKERESULT_GENERIC_ERROR;
}
/*
** implementation of libvlc input object
*/
const NPUTF8 * const LibvlcInputNPObject::propertyNames[] =
{
"length",
"position",
"time",
"fps",
"hasvout",
};
enum LibvlcInputNPObjectPropertyIds
{
ID_length,
ID_position,
ID_time,
ID_fps,
ID_hasvout,
};
const int LibvlcInputNPObject::propertyCount = sizeof(LibvlcInputNPObject::propertyNames)/sizeof(NPUTF8 *);
RuntimeNPObject::InvokeResult LibvlcInputNPObject::getProperty(int index, NPVariant *result)
{
VlcPlugin *p_plugin = reinterpret_cast<VlcPlugin *>(_instance->pdata);
if( p_plugin )
{
libvlc_exception_t ex;
libvlc_exception_init(&ex);
libvlc_input_t *p_input = libvlc_playlist_get_input(p_plugin->getVLC(), &ex);
if( libvlc_exception_raised(&ex) )
{
NPN_SetException(this, libvlc_exception_get_message(&ex));
libvlc_exception_clear(&ex);
return INVOKERESULT_GENERIC_ERROR;
}
switch( index )
{
case ID_length:
{
double val = (double)libvlc_input_get_length(p_input, &ex);
libvlc_input_free(p_input);
if( libvlc_exception_raised(&ex) )
{
NPN_SetException(this, libvlc_exception_get_message(&ex));
libvlc_exception_clear(&ex);
return INVOKERESULT_GENERIC_ERROR;
}
DOUBLE_TO_NPVARIANT(val, *result);
return INVOKERESULT_NO_ERROR;
}
case ID_position:
{
double val = libvlc_input_get_position(p_input, &ex);
libvlc_input_free(p_input);
if( libvlc_exception_raised(&ex) )
{
NPN_SetException(this, libvlc_exception_get_message(&ex));
libvlc_exception_clear(&ex);
return INVOKERESULT_GENERIC_ERROR;
}
DOUBLE_TO_NPVARIANT(val, *result);
return INVOKERESULT_NO_ERROR;
}
case ID_time:
{
double val = (double)libvlc_input_get_time(p_input, &ex);
libvlc_input_free(p_input);
if( libvlc_exception_raised(&ex) )
{
NPN_SetException(this, libvlc_exception_get_message(&ex));
libvlc_exception_clear(&ex);
return INVOKERESULT_GENERIC_ERROR;
}
DOUBLE_TO_NPVARIANT(val, *result);
return INVOKERESULT_NO_ERROR;
}
case ID_fps:
{
double val = libvlc_input_get_fps(p_input, &ex);
libvlc_input_free(p_input);