ActiveX: Improve subtitle and audio track JS bindings
authorCyril Mathé <cmathe@actech-innovation.com>
Mon, 18 May 2009 09:19:44 +0000 (11:19 +0200)
committerJean-Baptiste Kempf <jb@videolan.org>
Tue, 26 May 2009 12:29:45 +0000 (14:29 +0200)
- audio.count: give the number of available audio track
  - audio.description(int n): give the name of the n-th audio track
  - subtitle.count: give the number of available subtitle track
  - subtitle.description(int n): give the name of the n-th subtitle track
  - subtitle.track: get and set the subtitle track to show (similar as video.subtitle)

Signed-off-by: Jean-Baptiste Kempf <jb@videolan.org>
projects/activex/axvlc.idl
projects/activex/vlccontrol2.cpp
projects/activex/vlccontrol2.h

index 3965b52..8944074 100644 (file)
@@ -42,6 +42,7 @@ library AXVLC
     interface IVLCMessageIterator;\r
     interface IVLCMessages;\r
     interface IVLCPlaylist;\r
+    interface IVLCSubtitle;\r
     interface IVLCVideo;\r
     interface IVLCControl2;\r
     dispinterface DVLCEvents;\r
@@ -208,6 +209,11 @@ library AXVLC
         [propput, helpstring("Returns/sets audio track used/to use.")]\r
         HRESULT track([in] long track);\r
 \r
+        [propget, helpstring("Returns the number of audio tracks available.")]\r
+        HRESULT count([out, retval] long* trackNumber);\r
+        [helpstring("Returns audio track name.")]\r
+        HRESULT description([in] long trackID, [out, retval] BSTR* name);\r
+\r
         [propget, helpstring("Returns audio channel [1-5] indicating; stereo, reverse stereo, left, right, dolby.")]\r
         HRESULT channel([out, retval] long* channel);\r
         [propput, helpstring("Sets audio channel to [1-5] indicating; stereo, reverse stereo, left, right, dolby.")]\r
@@ -400,6 +406,26 @@ library AXVLC
         HRESULT items([out, retval] IVLCPlaylistItems** obj);\r
     };\r
 \r
+    [\r
+      odl,\r
+      uuid(465E787A-0556-452F-9477-954E4A940003),\r
+      helpstring("VLC Subtitle APIs"),\r
+      dual,\r
+      oleautomation\r
+    ]\r
+    interface IVLCSubtitle : IDispatch\r
+    {\r
+        [propget, helpstring("Returns video subtitle used.")]\r
+        HRESULT track([out, retval] long* spu);\r
+        [propput, helpstring("Sets video subtitle to use.")]\r
+        HRESULT track([in] long spu);\r
+\r
+        [propget, helpstring("Returns the number of video subtitles available.")]\r
+        HRESULT count([out, retval] long* spuNumber);\r
+        [helpstring("Returns video subtitle name.")]\r
+        HRESULT description([in] long nameID, [out, retval] BSTR* name);\r
+    };\r
+\r
     [\r
       odl,\r
       uuid(0AAEDF0B-D333-4B27-A0C6-BBF31413A42E),\r
@@ -525,6 +551,9 @@ library AXVLC
         [propget, helpstring("Returns the playlist object.")]\r
         HRESULT playlist([out, retval] IVLCPlaylist** obj);\r
 \r
+        [propget, helpstring("Returns the audio object.")]\r
+        HRESULT subtitle([out, retval] IVLCSubtitle** obj);\r
+\r
         [propget, helpstring("Returns the audio object.")]\r
         HRESULT video([out, retval] IVLCVideo** obj);\r
     };\r
index 169f220..daebef7 100644 (file)
@@ -238,6 +238,90 @@ STDMETHODIMP VLCAudio::put_track(long track)
     return hr;
 };
 
+STDMETHODIMP VLCAudio::get_count(long* trackNumber)
+{
+    if( NULL == trackNumber )
+        return E_POINTER;
+
+    libvlc_media_player_t* p_md;
+    HRESULT hr = _p_instance->getMD(&p_md);
+    if( SUCCEEDED(hr) )
+    {
+        libvlc_exception_t ex;
+        libvlc_exception_init(&ex);
+        // get the number of audio track available and return it
+        *trackNumber = libvlc_audio_get_track_count(p_md, &ex);
+        if( libvlc_exception_raised(&ex) )
+        {
+            _p_instance->setErrorInfo(IID_IVLCAudio,
+                         libvlc_exception_get_message(&ex));
+            libvlc_exception_clear(&ex);
+            return E_FAIL;
+        }
+        return NOERROR;
+    }
+    return hr;
+};
+
+
+STDMETHODIMP VLCAudio::description(long trackID, BSTR* name)
+{
+    if( NULL == name )
+        return E_POINTER;
+
+    libvlc_media_player_t* p_md;
+    libvlc_exception_t ex;
+    libvlc_exception_init(&ex);
+
+    HRESULT hr = _p_instance->getMD(&p_md);
+    if( SUCCEEDED(hr) )
+    {
+        int i, i_limit;
+        const char *psz_name;
+        libvlc_track_description_t *p_trackDesc;
+
+        // get tracks description
+        p_trackDesc = libvlc_audio_get_track_description(p_md, &ex);
+        if(  libvlc_exception_raised(&ex) )
+        {
+            _p_instance->setErrorInfo(IID_IVLCAudio, libvlc_exception_get_message(&ex));
+            libvlc_exception_clear(&ex);
+            return E_FAIL;
+        }
+
+        //get the number of available track
+        i_limit = libvlc_audio_get_track_count(p_md, &ex);
+        if(  libvlc_exception_raised(&ex) )
+        {
+            _p_instance->setErrorInfo(IID_IVLCAudio, libvlc_exception_get_message(&ex));
+            libvlc_exception_clear(&ex);
+            return E_FAIL;
+        }
+
+        // check if the number given is a good one
+        if ( ( trackID > ( i_limit -1 ) ) || ( trackID < 0 ) )
+                return E_FAIL;
+
+        // get the good trackDesc
+        for( i = 0 ; i < trackID ; i++ )
+        {
+            p_trackDesc = p_trackDesc->p_next;
+        }
+        // get the track name
+        psz_name = p_trackDesc->psz_name;
+
+        // return it
+        if( psz_name != NULL )
+        {
+            *name = BSTRFromCStr(CP_UTF8, psz_name);
+            return (NULL == *name) ? E_OUTOFMEMORY : NOERROR;
+        }
+        *name = NULL;
+        return E_FAIL;
+    }
+    return hr;
+};
+
 STDMETHODIMP VLCAudio::get_channel(long *channel)
 {
     if( NULL == channel )
@@ -1645,6 +1729,213 @@ STDMETHODIMP VLCPlaylist::get_items(IVLCPlaylistItems** obj)
 
 /*******************************************************************************/
 
+VLCSubtitle::~VLCSubtitle()
+{
+    if( _p_typeinfo )
+        _p_typeinfo->Release();
+};
+
+HRESULT VLCSubtitle::loadTypeInfo(void)
+{
+    HRESULT hr = NOERROR;
+    if( NULL == _p_typeinfo )
+    {
+        ITypeLib *p_typelib;
+
+        hr = _p_instance->getTypeLib(LOCALE_USER_DEFAULT, &p_typelib);
+        if( SUCCEEDED(hr) )
+        {
+            hr = p_typelib->GetTypeInfoOfGuid(IID_IVLCSubtitle, &_p_typeinfo);
+            if( FAILED(hr) )
+            {
+                _p_typeinfo = NULL;
+            }
+            p_typelib->Release();
+        }
+    }
+    return hr;
+};
+
+STDMETHODIMP VLCSubtitle::GetTypeInfoCount(UINT* pctInfo)
+{
+    if( NULL == pctInfo )
+        return E_INVALIDARG;
+
+    if( SUCCEEDED(loadTypeInfo()) )
+        *pctInfo = 1;
+    else
+        *pctInfo = 0;
+
+    return NOERROR;
+};
+
+STDMETHODIMP VLCSubtitle::GetTypeInfo(UINT iTInfo, LCID lcid, LPTYPEINFO* ppTInfo)
+{
+    if( NULL == ppTInfo )
+        return E_INVALIDARG;
+
+    if( SUCCEEDED(loadTypeInfo()) )
+    {
+        _p_typeinfo->AddRef();
+        *ppTInfo = _p_typeinfo;
+        return NOERROR;
+    }
+    *ppTInfo = NULL;
+    return E_NOTIMPL;
+};
+
+STDMETHODIMP VLCSubtitle::GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames,
+        UINT cNames, LCID lcid, DISPID* rgDispID)
+{
+    if( SUCCEEDED(loadTypeInfo()) )
+    {
+        return DispGetIDsOfNames(_p_typeinfo, rgszNames, cNames, rgDispID);
+    }
+    return E_NOTIMPL;
+};
+
+STDMETHODIMP VLCSubtitle::Invoke(DISPID dispIdMember, REFIID riid,
+        LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
+        VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
+{
+    if( SUCCEEDED(loadTypeInfo()) )
+    {
+        return DispInvoke(this, _p_typeinfo, dispIdMember, wFlags, pDispParams,
+                pVarResult, pExcepInfo, puArgErr);
+    }
+    return E_NOTIMPL;
+};
+
+STDMETHODIMP VLCSubtitle::get_track(long* spu)
+{
+    if( NULL == spu )
+        return E_POINTER;
+
+    libvlc_media_player_t *p_md;
+    HRESULT hr = _p_instance->getMD(&p_md);
+    if( SUCCEEDED(hr) )
+    {
+        libvlc_exception_t ex;
+        libvlc_exception_init(&ex);
+
+        *spu = libvlc_video_get_spu(p_md, &ex);
+        if( ! libvlc_exception_raised(&ex) )
+        {
+            return NOERROR;
+        }
+        _p_instance->setErrorInfo(IID_IVLCSubtitle, libvlc_exception_get_message(&ex));
+        libvlc_exception_clear(&ex);
+        return E_FAIL;
+    }
+    return hr;
+};
+
+STDMETHODIMP VLCSubtitle::put_track(long spu)
+{
+    libvlc_media_player_t *p_md;
+    HRESULT hr = _p_instance->getMD(&p_md);
+    if( SUCCEEDED(hr) )
+    {
+        libvlc_exception_t ex;
+        libvlc_exception_init(&ex);
+
+        libvlc_video_set_spu(p_md, spu, &ex);
+        if( libvlc_exception_raised(&ex) )
+        {
+            _p_instance->setErrorInfo(IID_IVLCSubtitle, libvlc_exception_get_message(&ex));
+            libvlc_exception_clear(&ex);
+            return E_FAIL;
+        }
+        return NOERROR;
+    }
+    return hr;
+};
+
+STDMETHODIMP VLCSubtitle::get_count(long* spuNumber)
+{
+    if( NULL == spuNumber )
+        return E_POINTER;
+
+    libvlc_media_player_t *p_md;
+    HRESULT hr = _p_instance->getMD(&p_md);
+    if( SUCCEEDED(hr) )
+    {
+        libvlc_exception_t ex;
+        libvlc_exception_init(&ex);
+        // get the number of video subtitle available and return it
+        *spuNumber = libvlc_video_get_spu_count(p_md, &ex);
+        if( libvlc_exception_raised(&ex) )
+        {
+           _p_instance->setErrorInfo(IID_IVLCSubtitle, libvlc_exception_get_message(&ex));
+            libvlc_exception_clear(&ex);
+            return E_FAIL;
+        }
+        return NOERROR;
+    }
+    return hr;
+};
+
+
+STDMETHODIMP VLCSubtitle::description(long nameID, BSTR* name)
+{
+    if( NULL == name )
+       return E_POINTER;
+
+    libvlc_media_player_t* p_md;
+    libvlc_exception_t ex;
+    libvlc_exception_init(&ex);
+
+    HRESULT hr = _p_instance->getMD(&p_md);
+    if( SUCCEEDED(hr) )
+    {
+        int i, i_limit;
+        const char *psz_name;
+        libvlc_track_description_t *p_spuDesc;
+
+        // get subtitles description
+        p_spuDesc = libvlc_video_get_spu_description(p_md, &ex);
+        if(  libvlc_exception_raised(&ex) )
+        {
+            _p_instance->setErrorInfo(IID_IVLCSubtitle, libvlc_exception_get_message(&ex));
+            libvlc_exception_clear(&ex);
+            return E_FAIL;
+        }
+
+        // get the number of available subtitle
+        i_limit = libvlc_video_get_spu_count(p_md, &ex);
+        if( libvlc_exception_raised(&ex) )
+        {
+            _p_instance->setErrorInfo(IID_IVLCSubtitle, libvlc_exception_get_message(&ex));
+            libvlc_exception_clear(&ex);
+            return E_FAIL;
+        }
+
+        // check if the number given is a good one
+        if ( ( nameID > ( i_limit -1 ) ) || ( nameID < 0 ) )
+            return E_FAIL;
+
+        // get the good spuDesc
+        for( i = 0 ; i < nameID ; i++ )
+        {
+            p_spuDesc = p_spuDesc->p_next;
+        }
+        // get the subtitle name
+        psz_name = p_spuDesc->psz_name;
+
+        // return it
+        if( psz_name != NULL )
+        {
+            *name = BSTRFromCStr(CP_UTF8, psz_name);
+            return (NULL == *name) ? E_OUTOFMEMORY : NOERROR;
+        }
+        *name = NULL;
+        return E_FAIL;
+    }
+    return hr;
+};
+
+/*******************************************************************************/
+
 VLCVideo::~VLCVideo()
 {
     if( _p_typeinfo )
@@ -2104,18 +2395,21 @@ VLCControl2::VLCControl2(VLCPlugin *p_instance) :
     _p_vlcaudio(NULL),
     _p_vlcinput(NULL),
     _p_vlcplaylist(NULL),
+    _p_vlcsubtitle(NULL),
     _p_vlcvideo(NULL)
 {
     _p_vlcaudio     = new VLCAudio(p_instance);
     _p_vlcinput     = new VLCInput(p_instance);
     _p_vlclog       = new VLCLog(p_instance);
     _p_vlcplaylist  = new VLCPlaylist(p_instance);
+    _p_vlcsubtitle  = new VLCSubtitle(p_instance);
     _p_vlcvideo     = new VLCVideo(p_instance);
 };
 
 VLCControl2::~VLCControl2()
 {
     delete _p_vlcvideo;
+    delete _p_vlcsubtitle;
     delete _p_vlcplaylist;
     delete _p_vlclog;
     delete _p_vlcinput;
@@ -2427,6 +2721,20 @@ STDMETHODIMP VLCControl2::get_playlist(IVLCPlaylist** obj)
     return E_OUTOFMEMORY;
 };
 
+STDMETHODIMP VLCControl2::get_subtitle(IVLCSubtitle** obj)
+{
+    if( NULL == obj )
+        return E_POINTER;
+
+    *obj = _p_vlcsubtitle;
+    if( NULL != _p_vlcsubtitle )
+    {
+        _p_vlcsubtitle->AddRef();
+        return NOERROR;
+    }
+    return E_OUTOFMEMORY;
+};
+
 STDMETHODIMP VLCControl2::get_video(IVLCVideo** obj)
 {
     if( NULL == obj )
index ee52d53..5e06fdf 100644 (file)
@@ -68,9 +68,11 @@ public:
     STDMETHODIMP put_volume(long);
     STDMETHODIMP get_track(long*);
     STDMETHODIMP put_track(long);
+    STDMETHODIMP get_count(long*);
     STDMETHODIMP get_channel(long*);
     STDMETHODIMP put_channel(long);
     STDMETHODIMP toggleMute();
+    STDMETHODIMP description(long, BSTR*);
 
 protected:
     HRESULT loadTypeInfo();
@@ -489,6 +491,54 @@ private:
     VLCPlaylistItems*    _p_vlcplaylistitems;
 };
 
+class VLCSubtitle : public IVLCSubtitle
+{
+public:
+    VLCSubtitle(VLCPlugin *p_instance) :
+        _p_instance(p_instance), _p_typeinfo(NULL) {};
+    virtual ~VLCSubtitle();
+
+    // IUnknown methods
+    STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
+    {
+        if( NULL == ppv )
+          return E_POINTER;
+        if( (IID_IUnknown == riid)
+         || (IID_IDispatch == riid)
+         || (IID_IVLCSubtitle == riid) )
+        {
+            AddRef();
+            *ppv = reinterpret_cast<LPVOID>(this);
+            return NOERROR;
+        }
+        // behaves as a standalone object
+        return E_NOINTERFACE;
+    };
+
+    STDMETHODIMP_(ULONG) AddRef(void) { return _p_instance->pUnkOuter->AddRef(); };
+    STDMETHODIMP_(ULONG) Release(void) { return _p_instance->pUnkOuter->Release(); };
+
+    // IDispatch methods
+    STDMETHODIMP GetTypeInfoCount(UINT*);
+    STDMETHODIMP GetTypeInfo(UINT, LCID, LPTYPEINFO*);
+    STDMETHODIMP GetIDsOfNames(REFIID,LPOLESTR*,UINT,LCID,DISPID*);
+    STDMETHODIMP Invoke(DISPID,REFIID,LCID,WORD,DISPPARAMS*,VARIANT*,EXCEPINFO*,UINT*);
+
+    // IVLCSubtitle methods
+    STDMETHODIMP get_track(long*);
+    STDMETHODIMP put_track(long);
+    STDMETHODIMP get_count(long*);
+    STDMETHODIMP description(long, BSTR*);
+
+protected:
+    HRESULT loadTypeInfo();
+
+private:
+    VLCPlugin*      _p_instance;
+    ITypeInfo*      _p_typeinfo;
+
+};
+
 class VLCVideo : public IVLCVideo
 {
 public:
@@ -606,6 +656,7 @@ public:
     STDMETHODIMP get_input(IVLCInput**);
     STDMETHODIMP get_log(IVLCLog**);
     STDMETHODIMP get_playlist(IVLCPlaylist**);
+    STDMETHODIMP get_subtitle(IVLCSubtitle**);
     STDMETHODIMP get_video(IVLCVideo**);
 
 protected:
@@ -619,6 +670,7 @@ private:
     VLCInput*       _p_vlcinput;
     VLCLog  *       _p_vlclog;
     VLCPlaylist*    _p_vlcplaylist;
+    VLCSubtitle*    _p_vlcsubtitle;
     VLCVideo*       _p_vlcvideo;
 };