Commit b4284eea authored by Daniel Amm's avatar Daniel Amm Committed by Jean-Baptiste Kempf

add support for titles and chapters

Signed-off-by: Jean-Baptiste Kempf's avatarJean-Baptiste Kempf <jb@videolan.org>
parent ea030598
......@@ -38,12 +38,14 @@ library AXVLC
{
// Forward declare all types defined in this typelib
interface IVLCAudio;
interface IVLCChapter;
interface IVLCInput;
interface IVLCLogo;
interface IVLCDeinterlace;
interface IVLCMarquee;
interface IVLCPlaylist;
interface IVLCSubtitle;
interface IVLCTitle;
interface IVLCVideo;
interface IVLCControl2;
dispinterface DVLCEvents;
......@@ -411,6 +413,57 @@ library AXVLC
};
[
odl,
uuid(b5def5a1-ffb6-4e68-b3d8-a12ac60fda54),
helpstring("VLC Title APIs"),
dual,
oleautomation
]
interface IVLCTitle : IDispatch
{
[propget, helpstring("Returns the number of title tracks available.")]
HRESULT count([out, retval] long* countTracks);
[propget, helpstring("Returns/sets title track used/to use.")]
HRESULT track([out, retval] long* track);
[propput, helpstring("Returns/sets title track used/to use.")]
HRESULT track([in] long track);
[helpstring("Returns the current title track name.")]
HRESULT description([in] long track, [out, retval] BSTR* name);
};
[
odl,
uuid(5af314cf-8849-4a79-a3fc-8de6625d9e72),
helpstring("VLC Chapter APIs"),
dual,
oleautomation
]
interface IVLCChapter : IDispatch
{
[propget, helpstring("Returns the number of chapter tracks available.")]
HRESULT count([out, retval] long* countTracks);
[helpstring("Returns the number of chapter tracks available of a specific title.")]
HRESULT countForTitle([in] long title, [out, retval] long* countTracks);
[propget, helpstring("Returns/sets chapter track used/to use.")]
HRESULT track([out, retval] long* track);
[propput, helpstring("Returns/sets chapter track used/to use.")]
HRESULT track([in] long track);
[helpstring("Returns the current chapter track name.")]
HRESULT description([in] long title, [in] long chapter, [out, retval] BSTR* name);
[helpstring("Advance to next chapter in current title.")]
HRESULT next();
[helpstring("Advance to previous chapter in current title.")]
HRESULT prev();
};
[
odl,
uuid(0AAEDF0B-D333-4B27-A0C6-BBF31413A42E),
......@@ -469,6 +522,12 @@ library AXVLC
[propget, helpstring("Returns the logo object.")]
HRESULT deinterlace([out, retval] IVLCDeinterlace** obj);
[propget, helpstring("Returns the title object.")]
HRESULT title([out, retval] IVLCTitle** obj);
[propget, helpstring("Returns the chapter object.")]
HRESULT chapter([out, retval] IVLCChapter** obj);
};
[
......
......@@ -31,12 +31,14 @@ using namespace std;
STDMETHODIMP VLCSupportErrorInfo::InterfaceSupportsErrorInfo(REFIID riid)
{
if( (riid == IID_IVLCAudio)
|| (riid == IID_IVLCChapter)
|| (riid == IID_IVLCInput)
|| (riid == IID_IVLCMarquee)
|| (riid == IID_IVLCLogo)
|| (riid == IID_IVLCPlaylist)
|| (riid == IID_IVLCPlaylistItems)
|| (riid == IID_IVLCSubtitle)
|| (riid == IID_IVLCTitle)
|| (riid == IID_IVLCVideo)
|| (riid == IID_IVLCControl2) )
{
......
......@@ -59,6 +59,8 @@ BIND_INTERFACE( VLCInput )
BIND_INTERFACE( VLCMarquee )
BIND_INTERFACE( VLCLogo )
BIND_INTERFACE( VLCDeinterlace )
BIND_INTERFACE( VLCTitle )
BIND_INTERFACE( VLCChapter )
BIND_INTERFACE( VLCPlaylistItems )
BIND_INTERFACE( VLCPlaylist )
BIND_INTERFACE( VLCVideo )
......@@ -915,6 +917,107 @@ STDMETHODIMP VLCSubtitle::description(long nameID, BSTR* name)
/****************************************************************************/
STDMETHODIMP VLCTitle::get_count(long* countTracks)
{
if( NULL == countTracks )
return E_POINTER;
*countTracks = _plug->get_player().get_mp().titleCount();
return S_OK;
}
STDMETHODIMP VLCTitle::get_track(long* track)
{
if( NULL == track )
return E_POINTER;
*track = _plug->get_player().get_mp().title();
return S_OK;
}
STDMETHODIMP VLCTitle::put_track(long track)
{
_plug->get_player().get_mp().setTitle(track);
return S_OK;
}
STDMETHODIMP VLCTitle::description(long track, BSTR* name)
{
if( NULL == name )
return E_POINTER;
auto tracks = _plug->get_player().get_mp().titleDescription();
if ( track >= tracks.size() )
return E_INVALIDARG;
*name = BSTRFromCStr( CP_UTF8, tracks[track].name().c_str() );
return (NULL == *name) ? E_OUTOFMEMORY : S_OK;
}
/****************************************************************************/
STDMETHODIMP VLCChapter::get_count(long* countTracks)
{
if( NULL == countTracks )
return E_POINTER;
*countTracks = _plug->get_player().get_mp().chapterCount();
return S_OK;
}
STDMETHODIMP VLCChapter::countForTitle(long track, long* countTracks)
{
if( NULL == countTracks )
return E_POINTER;
*countTracks = _plug->get_player().get_mp().chapterCountForTitle(track);
return S_OK;
}
STDMETHODIMP VLCChapter::get_track(long* track)
{
if( NULL == track )
return E_POINTER;
*track = _plug->get_player().get_mp().chapter();
return S_OK;
}
STDMETHODIMP VLCChapter::put_track(long track)
{
_plug->get_player().get_mp().setChapter(track);
return S_OK;
}
STDMETHODIMP VLCChapter::description(long title, long chapter, BSTR* name)
{
if( NULL == name )
return E_POINTER;
auto titleTracks = _plug->get_player().get_mp().titleDescription();
if ( title >= titleTracks.size() )
return E_INVALIDARG;
auto tracks = _plug->get_player().get_mp().chapterDescription(title);
if ( chapter >= tracks.size() )
return E_INVALIDARG;
*name = BSTRFromCStr( CP_UTF8, tracks[chapter].name().c_str() );
return (NULL == *name) ? E_OUTOFMEMORY : S_OK;
}
STDMETHODIMP VLCChapter::next()
{
_plug->get_player().get_mp().nextChapter();
return S_OK;
}
STDMETHODIMP VLCChapter::prev()
{
_plug->get_player().get_mp().previousChapter();
return S_OK;
}
/****************************************************************************/
STDMETHODIMP VLCVideo::get_fullscreen(VARIANT_BOOL* fullscreen)
{
if( NULL == fullscreen )
......@@ -1158,6 +1261,16 @@ STDMETHODIMP VLCVideo::get_deinterlace(IVLCDeinterlace** obj)
return object_get(obj,_p_vlcdeint);
}
STDMETHODIMP VLCVideo::get_title(IVLCTitle** obj)
{
return object_get(obj,_p_vlctitle);
}
STDMETHODIMP VLCVideo::get_chapter(IVLCChapter** obj)
{
return object_get(obj,_p_vlcchapter);
}
/****************************************************************************/
HRESULT VLCLogo::do_put_int(unsigned idx, LONG val)
......
......@@ -236,6 +236,33 @@ public:
STDMETHODIMP disable();
};
class VLCTitle : public VLCInterface<VLCTitle,IVLCTitle>
{
public:
VLCTitle(VLCPlugin *p): VLCInterface<VLCTitle,IVLCTitle>(p) { }
// IVLCTitle methods
STDMETHODIMP get_count(long*);
STDMETHODIMP get_track(long*);
STDMETHODIMP put_track(long);
STDMETHODIMP description(long, BSTR*);
};
class VLCChapter : public VLCInterface<VLCChapter,IVLCChapter>
{
public:
VLCChapter(VLCPlugin *p): VLCInterface<VLCChapter,IVLCChapter>(p) { }
// IVLCChapter methods
STDMETHODIMP get_count(long*);
STDMETHODIMP countForTitle(long, long*);
STDMETHODIMP get_track(long*);
STDMETHODIMP put_track(long);
STDMETHODIMP description(long, long, BSTR*);
STDMETHODIMP next();
STDMETHODIMP prev();
};
class VLCPlaylistItems: public VLCInterface<VLCPlaylistItems,IVLCPlaylistItems>
{
public:
......@@ -293,11 +320,14 @@ class VLCVideo: public VLCInterface<VLCVideo,IVLCVideo>
public:
VLCVideo(VLCPlugin *p): VLCInterface<VLCVideo,IVLCVideo>(p),
_p_vlcmarquee(new VLCMarquee(p)), _p_vlclogo(new VLCLogo(p)),
_p_vlcdeint(new VLCDeinterlace(p)) { }
_p_vlcdeint(new VLCDeinterlace(p)), _p_vlctitle(new VLCTitle(p)),
_p_vlcchapter(new VLCChapter(p)) { }
virtual ~VLCVideo() {
_p_vlcmarquee->Release();
_p_vlclogo->Release();
_p_vlcdeint->Release();
_p_vlctitle->Release();
_p_vlcchapter->Release();
}
// IVLCVideo methods
......@@ -316,6 +346,8 @@ public:
STDMETHODIMP get_marquee(IVLCMarquee**);
STDMETHODIMP get_logo(IVLCLogo**);
STDMETHODIMP get_deinterlace(IVLCDeinterlace**);
STDMETHODIMP get_title(IVLCTitle**);
STDMETHODIMP get_chapter(IVLCChapter**);
STDMETHODIMP takeSnapshot(LPPICTUREDISP*);
STDMETHODIMP toggleFullscreen();
STDMETHODIMP toggleTeletext();
......@@ -324,6 +356,8 @@ private:
IVLCMarquee *_p_vlcmarquee;
IVLCLogo *_p_vlclogo;
IVLCDeinterlace *_p_vlcdeint;
IVLCTitle *_p_vlctitle;
IVLCChapter *_p_vlcchapter;
};
class VLCMediaDescription:
......
......@@ -1275,6 +1275,8 @@ LibvlcVideoNPObject::~LibvlcVideoNPObject()
if( marqueeObj ) NPN_ReleaseObject(marqueeObj);
if( logoObj ) NPN_ReleaseObject(logoObj);
if( deintObj ) NPN_ReleaseObject(deintObj);
if( titleObj ) NPN_ReleaseObject(titleObj);
if( chapterObj ) NPN_ReleaseObject(chapterObj);
}
}
......@@ -1290,6 +1292,8 @@ const NPUTF8 * const LibvlcVideoNPObject::propertyNames[] =
"marquee",
"logo",
"deinterlace",
"title",
"chapter",
};
enum LibvlcVideoNPObjectPropertyIds
......@@ -1304,6 +1308,8 @@ enum LibvlcVideoNPObjectPropertyIds
ID_video_marquee,
ID_video_logo,
ID_video_deinterlace,
ID_video_title,
ID_video_chapter,
};
COUNTNAMES(LibvlcVideoNPObject,propertyCount,propertyNames);
......@@ -1380,6 +1386,18 @@ LibvlcVideoNPObject::getProperty(int index, npapi::OutVariant& result)
result = deintObj;
return INVOKERESULT_NO_ERROR;
}
case ID_video_title:
{
InstantObj<LibvlcTitleNPObject>( titleObj );
result = titleObj;
return INVOKERESULT_NO_ERROR;
}
case ID_video_chapter:
{
InstantObj<LibvlcChapterNPObject>( chapterObj );
result = chapterObj;
return INVOKERESULT_NO_ERROR;
}
}
}
return INVOKERESULT_GENERIC_ERROR;
......@@ -1901,3 +1919,297 @@ LibvlcDeinterlaceNPObject::invoke(int index, const NPVariant *args,
}
return INVOKERESULT_NO_ERROR;
}
/*
** implementation of libvlc title object
*/
const NPUTF8 * const LibvlcTitleNPObject::propertyNames[] =
{
"count",
"track",
};
COUNTNAMES(LibvlcTitleNPObject,propertyCount,propertyNames);
enum LibvlcTitleNPObjectPropertyIds
{
ID_title_count,
ID_title_track,
};
RuntimeNPObject::InvokeResult
LibvlcTitleNPObject::getProperty(int index, npapi::OutVariant& result)
{
/* is plugin still running */
if( isPluginRunning() )
{
VlcPluginBase* p_plugin = getPrivate<VlcPluginBase>();
auto& mp = p_plugin->getMD();
if( !mp )
RETURN_ON_ERROR;
switch( index )
{
case ID_title_count:
{
result = mp.titleCount();
return INVOKERESULT_NO_ERROR;
}
case ID_title_track:
{
result = mp.title();
return INVOKERESULT_NO_ERROR;
}
default:
;
}
}
return INVOKERESULT_GENERIC_ERROR;
}
RuntimeNPObject::InvokeResult
LibvlcTitleNPObject::setProperty(int index, const NPVariant &value)
{
/* is plugin still running */
if( isPluginRunning() )
{
VlcPluginBase* p_plugin = getPrivate<VlcPluginBase>();
auto& mp = p_plugin->getMD();
if( !mp )
RETURN_ON_ERROR;
const npapi::Variant v( value );
switch( index )
{
case ID_title_track:
{
if( !v.is<int>() )
return INVOKERESULT_INVALID_VALUE;
mp.setTitle( v );
return INVOKERESULT_NO_ERROR;
}
default:
;
}
}
return INVOKERESULT_GENERIC_ERROR;
}
const NPUTF8 * const LibvlcTitleNPObject::methodNames[] =
{
"description",
};
COUNTNAMES(LibvlcTitleNPObject,methodCount,methodNames);
enum LibvlcTitleNPObjectMethodIds
{
ID_title_description,
};
RuntimeNPObject::InvokeResult
LibvlcTitleNPObject::invoke(int index, const NPVariant *args,
uint32_t argCount, npapi::OutVariant& result)
{
/* is plugin still running */
if( isPluginRunning() )
{
VlcPluginBase* p_plugin = getPrivate<VlcPluginBase>();
auto& mp = p_plugin->getMD();
if( !mp )
RETURN_ON_ERROR;
switch( index )
{
case ID_title_description:
{
if ( argCount < 1 )
return INVOKERESULT_INVALID_ARGS;
const npapi::Variant v( args[0] );
if( v.is<int>() )
{
auto tracks = mp.titleDescription();
if ( v >= tracks.size() )
return INVOKERESULT_INVALID_VALUE;
/* display the name of the track chosen */
result = tracks[v].name();
return INVOKERESULT_NO_ERROR;
}
return INVOKERESULT_NO_SUCH_METHOD;
}
default:
;
}
}
return INVOKERESULT_GENERIC_ERROR;
}
/*
** implementation of libvlc chapter object
*/
const NPUTF8 * const LibvlcChapterNPObject::propertyNames[] =
{
"count",
"track",
};
COUNTNAMES(LibvlcChapterNPObject,propertyCount,propertyNames);
enum LibvlcChapterNPObjectPropertyIds
{
ID_chapter_count,
ID_chapter_track,
};
RuntimeNPObject::InvokeResult
LibvlcChapterNPObject::getProperty(int index, npapi::OutVariant& result)
{
/* is plugin still running */
if( isPluginRunning() )
{
VlcPluginBase* p_plugin = getPrivate<VlcPluginBase>();
auto& mp = p_plugin->getMD();
if( !mp )
RETURN_ON_ERROR;
switch( index )
{
case ID_chapter_count:
{
result = mp.chapterCount();
return INVOKERESULT_NO_ERROR;
}
case ID_chapter_track:
{
result = mp.chapter();
return INVOKERESULT_NO_ERROR;
}
default:
;
}
}
return INVOKERESULT_GENERIC_ERROR;
}
RuntimeNPObject::InvokeResult
LibvlcChapterNPObject::setProperty(int index, const NPVariant &value)
{
/* is plugin still running */
if( isPluginRunning() )
{
VlcPluginBase* p_plugin = getPrivate<VlcPluginBase>();
auto& mp = p_plugin->getMD();
if( !mp )
RETURN_ON_ERROR;
const npapi::Variant v( value );
switch( index )
{
case ID_chapter_track:
{
if( !v.is<int>() )
return INVOKERESULT_INVALID_VALUE;
mp.setChapter( v );
return INVOKERESULT_NO_ERROR;
}
default:
;
}
}
return INVOKERESULT_GENERIC_ERROR;
}
const NPUTF8 * const LibvlcChapterNPObject::methodNames[] =
{
"countForTitle",
"description",
"next",
"prev",
};
COUNTNAMES(LibvlcChapterNPObject,methodCount,methodNames);
enum LibvlcChapterNPObjectMethodIds
{
ID_chapter_count_for_title,
ID_chapter_description,
ID_chapter_next,
ID_chapter_prev,
};
RuntimeNPObject::InvokeResult
LibvlcChapterNPObject::invoke(int index, const NPVariant *args,
uint32_t argCount, npapi::OutVariant& result)
{
/* is plugin still running */
if( isPluginRunning() )
{
VlcPluginBase* p_plugin = getPrivate<VlcPluginBase>();
auto& mp = p_plugin->getMD();
if( !mp )
RETURN_ON_ERROR;
switch( index )
{
case ID_chapter_count_for_title:
{
if ( argCount < 1 )
return INVOKERESULT_INVALID_ARGS;
const npapi::Variant v( args[0] );
if( v.is<int>() )
{
result = mp.chapterCountForTitle( v );
return INVOKERESULT_NO_ERROR;
}
return INVOKERESULT_NO_SUCH_METHOD;
}
case ID_chapter_description:
{
if ( argCount < 2 )
return INVOKERESULT_INVALID_ARGS;
const npapi::Variant titleId( args[0] );
const npapi::Variant v( args[1] );
if( !titleId.is<int>() )
return INVOKERESULT_INVALID_VALUE;
auto titleTracks = mp.titleDescription();
if ( titleId >= titleTracks.size() )
return INVOKERESULT_INVALID_VALUE;
if( v.is<int>() )
{
auto tracks = mp.chapterDescription( titleId );
if ( v >= tracks.size() )
return INVOKERESULT_INVALID_VALUE;
/* display the name of the track chosen */
result = tracks[v].name();
return INVOKERESULT_NO_ERROR;
}
return INVOKERESULT_NO_SUCH_METHOD;
}
case ID_chapter_next:
{
if( argCount == 0 )
{
mp.nextChapter();
return INVOKERESULT_NO_ERROR;
}
return INVOKERESULT_NO_SUCH_METHOD;
}
case ID_chapter_prev:
{
if( argCount == 0 )
{
mp.previousChapter();
return INVOKERESULT_NO_ERROR;
}
return INVOKERESULT_NO_SUCH_METHOD;
}
default:
;
}
}
return INVOKERESULT_GENERIC_ERROR;
}
......@@ -201,7 +201,7 @@ protected:
LibvlcVideoNPObject(NPP instance, const NPClass *aClass) :
RuntimeNPObject(instance, aClass),
marqueeObj(NULL), logoObj(NULL), deintObj(NULL) { }
marqueeObj(NULL), logoObj(NULL), deintObj(NULL), titleObj(NULL), chapterObj(NULL) { }
virtual ~LibvlcVideoNPObject();
static const int propertyCount;
......@@ -219,6 +219,8 @@ private:
NPObject *marqueeObj;
NPObject *logoObj;
NPObject *deintObj;
NPObject *titleObj;
NPObject *chapterObj;
};
class LibvlcMarqueeNPObject: public RuntimeNPObject
......@@ -284,3 +286,44 @@ protected:
virtual InvokeResult invoke(int index, const NPVariant *args, uint32_t argCount, npapi::OutVariant &result) override;
};
class LibvlcTitleNPObject: public RuntimeNPObject
{
protected:
friend class RuntimeNPClass<LibvlcTitleNPObject>;
LibvlcTitleNPObject(NPP instance, const NPClass *aClass) :
RuntimeNPObject(instance, aClass) { }
virtual ~LibvlcTitleNPObject() { }
static const int propertyCount;
static const NPUTF8 * const propertyNames[];
virtual InvokeResult getProperty(int index, npapi::OutVariant& result) override;
virtual InvokeResult setProperty(int index, const NPVariant &value) override;
static const int methodCount;
static const NPUTF8 * const methodNames[];
virtual InvokeResult invoke(int index, const NPVariant *args, uint32_t argCount, npapi::OutVariant &result) override;
};
class LibvlcChapterNPObject: public RuntimeNPObject
{
protected:
friend class RuntimeNPClass<LibvlcChapterNPObject>;
LibvlcChapterNPObject(NPP instance, const NPClass *aClass) :
RuntimeNPObject(instance, aClass) { }
virtual ~LibvlcChapterNPObject() { }
static const int propertyCount;
static const NPUTF8 * const propertyNames[];
virtual InvokeResult getProperty(int index, npapi::OutVariant& result) override;
virtual InvokeResult setProperty(int index, const NPVariant &value) override;
static const int methodCount;
static const NPUTF8 * const methodNames[];
virtual InvokeResult invoke(int index, const NPVariant *args, uint32_t argCount, npapi::OutVariant &result) override;
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment