Commit 5cd1ab48 authored by Pierre Lamot's avatar Pierre Lamot Committed by Jean-Baptiste Kempf

activex: allow to parse item and retreive information before playing

  VLC ActiveX API doesn't follow libvlc API and doesn't expose Media to the user
  so preparse is made by allowing to preparse a specific item from the playlist.

  Informations about the media can be retreive using the same API (video.width, ...),
  throught a fallback when the MediaPlayer isn't playing.

  parse will only allow parsing the first item of the playlist, as other item, and information
  about them, are only accessible by playing them.
Signed-off-by: Jean-Baptiste Kempf's avatarJean-Baptiste Kempf <jb@videolan.org>
parent aa98041e
...@@ -349,6 +349,9 @@ library AXVLC ...@@ -349,6 +349,9 @@ library AXVLC
[propget, helpstring("Returns the playlist items collection object.")] [propget, helpstring("Returns the playlist items collection object.")]
HRESULT items([out, retval] IVLCPlaylistItems** obj); HRESULT items([out, retval] IVLCPlaylistItems** obj);
[helpstring("Parse the head media from playlist")]
HRESULT parse([in] long options, [in] long timeout_ms, [out, retval] long* status);
}; };
[ [
......
...@@ -466,7 +466,32 @@ STDMETHODIMP VLCAudio::get_count(long* trackNumber) ...@@ -466,7 +466,32 @@ STDMETHODIMP VLCAudio::get_count(long* trackNumber)
if( NULL == trackNumber ) if( NULL == trackNumber )
return E_POINTER; return E_POINTER;
*trackNumber = negativeToZero( _plug->get_player().get_mp().audioTrackCount() ); libvlc_state_t state = _plug->get_player().get_mp().state();
switch (state)
{
case libvlc_Buffering:
case libvlc_Playing:
case libvlc_Paused:
{
*trackNumber = negativeToZero( _plug->get_player().get_mp().audioTrackCount() );
break;
}
default:
{
auto media = _plug->get_player().get_media(0);
if ( !media )
{
*trackNumber = 0;
return S_OK;
}
int count = 0;
for (auto track: media->tracks())
if (track.type() == VLC::MediaTrack::Type::Audio)
count++;
*trackNumber = count;
break;
}
}
return S_OK; return S_OK;
} }
...@@ -476,11 +501,37 @@ STDMETHODIMP VLCAudio::description(long trackId, BSTR* name) ...@@ -476,11 +501,37 @@ STDMETHODIMP VLCAudio::description(long trackId, BSTR* name)
if( NULL == name ) if( NULL == name )
return E_POINTER; return E_POINTER;
auto tracks = _plug->get_player().get_mp().audioTrackDescription(); libvlc_state_t state = _plug->get_player().get_mp().state();
if ( trackId >= tracks.size() ) switch (state)
{
case libvlc_Buffering:
case libvlc_Playing:
case libvlc_Paused:
{
auto tracks = _plug->get_player().get_mp().audioTrackDescription();
if ( trackId >= tracks.size() )
return E_INVALIDARG;
*name = BSTRFromCStr( CP_UTF8, tracks[trackId].name().c_str() );
return (NULL == *name) ? E_OUTOFMEMORY : S_OK;
}
default:
{
auto media = _plug->get_player().get_media(0);
if ( !media )
return E_INVALIDARG;
for (auto track: media->tracks())
if (track.type() == VLC::MediaTrack::Type::Audio)
{
if (trackId == 0)
{
*name = BSTRFromCStr( CP_UTF8, track.description().c_str() );
return (NULL == *name) ? E_OUTOFMEMORY : S_OK;
}
trackId--;
}
return E_INVALIDARG; return E_INVALIDARG;
*name = BSTRFromCStr( CP_UTF8, tracks[trackId].name().c_str() ); }
return (NULL == *name) ? E_OUTOFMEMORY : S_OK; }
} }
STDMETHODIMP VLCAudio::get_channel(long *channel) STDMETHODIMP VLCAudio::get_channel(long *channel)
...@@ -633,7 +684,30 @@ STDMETHODIMP VLCInput::get_length(double* length) ...@@ -633,7 +684,30 @@ STDMETHODIMP VLCInput::get_length(double* length)
if( NULL == length ) if( NULL == length )
return E_POINTER; return E_POINTER;
*length = static_cast<double>(_plug->get_player().get_mp().length() );
libvlc_state_t state = _plug->get_player().get_mp().state();
switch (state)
{
case libvlc_Buffering:
case libvlc_Playing:
case libvlc_Paused:
{
*length = static_cast<double>(_plug->get_player().get_mp().length() );
break;
}
default:
{
auto media = _plug->get_player().get_media(0);
if ( !media )
{
*length = 0.0;
return S_OK;
}
*length = static_cast<double>(media->duration());
break;
}
}
return S_OK; return S_OK;
} }
...@@ -706,7 +780,11 @@ STDMETHODIMP VLCInput::get_fps(double* fps) ...@@ -706,7 +780,11 @@ STDMETHODIMP VLCInput::get_fps(double* fps)
auto media = _plug->get_player().get_mp().media(); auto media = _plug->get_player().get_mp().media();
if ( media == nullptr ) if ( media == nullptr )
return E_FAIL; {
media = _plug->get_player().get_media(0);
if ( media == nullptr )
return E_FAIL;
}
auto tracks = media->tracks(); auto tracks = media->tracks();
for ( const auto& t : tracks ) for ( const auto& t : tracks )
{ {
...@@ -1001,6 +1079,16 @@ STDMETHODIMP VLCPlaylist::get_items(IVLCPlaylistItems** obj) ...@@ -1001,6 +1079,16 @@ STDMETHODIMP VLCPlaylist::get_items(IVLCPlaylistItems** obj)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
STDMETHODIMP VLCPlaylist::parse(long options, long timeout, long *status)
{
if ( timeout < 0 )
return E_INVALIDARG;
if ( status == nullptr )
return E_POINTER;
*status = _plug->get_player().preparse_item_sync( 0, options, timeout );
return S_OK;
}
/****************************************************************************/ /****************************************************************************/
STDMETHODIMP VLCSubtitle::get_track(long* spu) STDMETHODIMP VLCSubtitle::get_track(long* spu)
...@@ -1027,20 +1115,72 @@ STDMETHODIMP VLCSubtitle::get_count(long* spuNumber) ...@@ -1027,20 +1115,72 @@ STDMETHODIMP VLCSubtitle::get_count(long* spuNumber)
if( NULL == spuNumber ) if( NULL == spuNumber )
return E_POINTER; return E_POINTER;
*spuNumber = _plug->get_player().get_mp().spuCount(); libvlc_state_t state = _plug->get_player().get_mp().state();
switch (state)
{
case libvlc_Buffering:
case libvlc_Playing:
case libvlc_Paused:
{
*spuNumber = _plug->get_player().get_mp().spuCount();
break;
}
default:
{
auto media = _plug->get_player().get_media(0);
if ( !media )
{
*spuNumber = 0;
return S_OK;
}
int count = 0;
for (auto track: media->tracks())
if (track.type() == VLC::MediaTrack::Type::Subtitle)
count++;
*spuNumber = count;
break;
}
}
return S_OK; return S_OK;
} }
STDMETHODIMP VLCSubtitle::description(long nameID, BSTR* name) STDMETHODIMP VLCSubtitle::description(long nameID, BSTR* name)
{ {
if( NULL == name ) if( NULL == name )
return E_POINTER; return E_POINTER;
auto tracks = _plug->get_player().get_mp().spuDescription(); libvlc_state_t state = _plug->get_player().get_mp().state();
if ( nameID >= tracks.size() ) switch (state)
{
case libvlc_Buffering:
case libvlc_Playing:
case libvlc_Paused:
{
auto tracks = _plug->get_player().get_mp().spuDescription();
if ( nameID >= tracks.size() )
return E_INVALIDARG;
*name = BSTRFromCStr( CP_UTF8, tracks[nameID].name().c_str() );
return (NULL == *name) ? E_OUTOFMEMORY : S_OK;
}
default:
{
auto media = _plug->get_player().get_media(0);
if ( !media )
return E_INVALIDARG;
for (auto track: media->tracks())
if (track.type() == VLC::MediaTrack::Type::Subtitle)
{
if (nameID == 0)
{
*name = BSTRFromCStr( CP_UTF8, track.description().c_str() );
return (NULL == *name) ? E_OUTOFMEMORY : S_OK;
}
nameID--;
}
return E_INVALIDARG; return E_INVALIDARG;
*name = BSTRFromCStr( CP_UTF8, tracks[nameID].name().c_str() ); }
return (NULL == *name) ? E_OUTOFMEMORY : S_OK; }
} }
/****************************************************************************/ /****************************************************************************/
...@@ -1066,8 +1206,36 @@ STDMETHODIMP VLCVideo::get_width(long* width) ...@@ -1066,8 +1206,36 @@ STDMETHODIMP VLCVideo::get_width(long* width)
if( NULL == width ) if( NULL == width )
return E_POINTER; return E_POINTER;
unsigned int height; libvlc_state_t state = _plug->get_player().get_mp().state();
_plug->get_player().get_mp().size( 0, (unsigned int*)width, &height ); switch (state)
{
case libvlc_Buffering:
case libvlc_Playing:
case libvlc_Paused:
{
unsigned int height;
_plug->get_player().get_mp().size( 0, (unsigned int*)width, &height );
break;
}
default:
{
auto media = _plug->get_player().get_media(0);
if ( !media )
{
*width = 0;
return S_OK;
}
for ( auto track : media->tracks() )
{
if (track.type() == VLC::MediaTrack::Type::Video)
{
*width = track.width();
break;
}
}
break;
}
}
return S_OK; return S_OK;
} }
...@@ -1076,8 +1244,37 @@ STDMETHODIMP VLCVideo::get_height(long* height) ...@@ -1076,8 +1244,37 @@ STDMETHODIMP VLCVideo::get_height(long* height)
if( NULL == height ) if( NULL == height )
return E_POINTER; return E_POINTER;
unsigned int width;
_plug->get_player().get_mp().size( 0, &width, (unsigned int*)height ); libvlc_state_t state = _plug->get_player().get_mp().state();
switch (state)
{
case libvlc_Buffering:
case libvlc_Playing:
case libvlc_Paused:
{
unsigned int width;
_plug->get_player().get_mp().size( 0, &width, (unsigned int*)height );
break;
}
default:
{
auto media = _plug->get_player().get_media(0);
if ( !media )
{
*height = 0;
return S_OK;
}
for ( auto track : media->tracks() )
{
if (track.type() == VLC::MediaTrack::Type::Video)
{
*height = track.height();
break;
}
}
break;
}
}
return S_OK; return S_OK;
} }
...@@ -1321,7 +1518,32 @@ STDMETHODIMP VLCVideo::get_count(long* trackNumber) ...@@ -1321,7 +1518,32 @@ STDMETHODIMP VLCVideo::get_count(long* trackNumber)
if( NULL == trackNumber ) if( NULL == trackNumber )
return E_POINTER; return E_POINTER;
*trackNumber = negativeToZero( _plug->get_player().get_mp().videoTrackCount() ); libvlc_state_t state = _plug->get_player().get_mp().state();
switch (state)
{
case libvlc_Buffering:
case libvlc_Playing:
case libvlc_Paused:
{
*trackNumber = negativeToZero( _plug->get_player().get_mp().videoTrackCount() );
break;
}
default:
{
auto media = _plug->get_player().get_media(0);
if ( !media )
{
*trackNumber = 0;
return S_OK;
}
int count = 0;
for (auto track: media->tracks())
if (track.type() == VLC::MediaTrack::Type::Video)
count++;
*trackNumber = count;
break;
}
}
return S_OK; return S_OK;
} }
...@@ -1331,11 +1553,37 @@ STDMETHODIMP VLCVideo::description(long trackId, BSTR* name) ...@@ -1331,11 +1553,37 @@ STDMETHODIMP VLCVideo::description(long trackId, BSTR* name)
if( NULL == name ) if( NULL == name )
return E_POINTER; return E_POINTER;
auto tracks = _plug->get_player().get_mp().videoTrackDescription(); libvlc_state_t state = _plug->get_player().get_mp().state();
if ( trackId >= tracks.size() ) switch (state)
{
case libvlc_Buffering:
case libvlc_Playing:
case libvlc_Paused:
{
auto tracks = _plug->get_player().get_mp().videoTrackDescription();
if ( trackId >= tracks.size() )
return E_INVALIDARG;
*name = BSTRFromCStr( CP_UTF8, tracks[trackId].name().c_str() );
return (NULL == *name) ? E_OUTOFMEMORY : S_OK;
}
default:
{
auto media = _plug->get_player().get_media(0);
if ( !media )
return E_INVALIDARG;
for (auto track: media->tracks())
if (track.type() == VLC::MediaTrack::Type::Video)
{
if (trackId == 0)
{
*name = BSTRFromCStr( CP_UTF8, track.description().c_str() );
return (NULL == *name) ? E_OUTOFMEMORY : S_OK;
}
trackId--;
}
return E_INVALIDARG; return E_INVALIDARG;
*name = BSTRFromCStr( CP_UTF8, tracks[trackId].name().c_str() ); }
return (NULL == *name) ? E_OUTOFMEMORY : S_OK; }
} }
STDMETHODIMP VLCVideo::get_marquee(IVLCMarquee** obj) STDMETHODIMP VLCVideo::get_marquee(IVLCMarquee** obj)
...@@ -1421,7 +1669,11 @@ STDMETHODIMP VLCMediaDescription::get_meta(BSTR* val, libvlc_meta_t e_meta) ...@@ -1421,7 +1669,11 @@ STDMETHODIMP VLCMediaDescription::get_meta(BSTR* val, libvlc_meta_t e_meta)
auto media = _plug->get_player().get_mp().media(); auto media = _plug->get_player().get_mp().media();
if ( media == nullptr ) if ( media == nullptr )
return E_FAIL; {
media = _plug->get_player().get_media(0);
if ( media == nullptr )
return E_FAIL;
}
auto info = media->meta( e_meta ); auto info = media->meta( e_meta );
*val = BSTRFromCStr( CP_UTF8, info.c_str() ); *val = BSTRFromCStr( CP_UTF8, info.c_str() );
return *val ? S_OK : E_FAIL; return *val ? S_OK : E_FAIL;
......
...@@ -309,6 +309,7 @@ public: ...@@ -309,6 +309,7 @@ public:
STDMETHODIMP clear(); STDMETHODIMP clear();
STDMETHODIMP removeItem(long); STDMETHODIMP removeItem(long);
STDMETHODIMP get_items(IVLCPlaylistItems**); STDMETHODIMP get_items(IVLCPlaylistItems**);
STDMETHODIMP parse(long options, long timeout, long* status);
private: private:
VLCPlaylistItems* _p_vlcplaylistitems; VLCPlaylistItems* _p_vlcplaylistitems;
......
...@@ -23,6 +23,12 @@ ...@@ -23,6 +23,12 @@
#include "config.h" #include "config.h"
#endif #endif
#if defined(_WIN32)
# include <windows.h>
#else
# include <future>
#endif
#include "vlc_player.h" #include "vlc_player.h"
bool vlc_player::open(VLC::Instance& inst) bool vlc_player::open(VLC::Instance& inst)
...@@ -95,6 +101,73 @@ void vlc_player::clear_items() ...@@ -95,6 +101,73 @@ void vlc_player::clear_items()
} }
} }
int vlc_player::preparse_item_sync(unsigned int idx, int options, unsigned int timeout)
{
int retval = -1;
VLC::MediaList::Lock lock( _ml );
auto media = _ml.itemAtIndex( idx );
if ( !media )
return -1;
auto em = media->eventManager();
#if LIBVLC_VERSION_INT >= LIBVLC_VERSION(3, 0, 0, 0)
# if defined(_WIN32)
HANDLE barrier = CreateEvent(nullptr, true, false, nullptr);
if ( barrier == nullptr )
return -1;
auto event = em.onParsedChanged(
[&barrier, &retval](VLC::Media::ParsedStatus status )
{
retval = int( status );
SetEvent( barrier );
});
media->parseWithOptions( VLC::Media::ParseFlags( options ), timeout );
DWORD waitResult = WaitForSingleObject( barrier, INFINITE );
switch ( waitResult ) {
case WAIT_OBJECT_0:
break;
default:
retval = -1;
break;
}
CloseHandle( barrier );
event->unregister();
# else
std::promise<int> promise;
std::future<int> future = promise.get_future();
auto event = em.onParsedChanged(
[&promise]( VLC::Media::ParsedStatus status )
{
promise.set_value( int( status ) );
});
media->parseWithOptions( VLC::Media::ParseFlags( options ), timeout );
future.wait();
retval = future.get();
event->unregister();
# endif
#else
media->parse();
if ( media->isParsed() )
retval = int( VLC::Media::ParsedStatus::Done );
else
retval = int( VLC::Media::ParsedStatus::Failed );
#endif
return retval;
}
std::shared_ptr<VLC::Media> vlc_player::get_media(unsigned int idx)
{
return _ml.itemAtIndex(idx);
}
void vlc_player::play() void vlc_player::play()
{ {
if( 0 == items_count() ) if( 0 == items_count() )
......
...@@ -48,6 +48,8 @@ public: ...@@ -48,6 +48,8 @@ public:
void play(); void play();
int preparse_item_sync(unsigned int idx, int options, unsigned int timeout);
VLC::MediaPlayer& get_mp() VLC::MediaPlayer& get_mp()
{ {
return _mp; return _mp;
...@@ -58,6 +60,8 @@ public: ...@@ -58,6 +60,8 @@ public:
return _ml_p; return _ml_p;
} }
std::shared_ptr<VLC::Media> get_media( unsigned int idx );
int currentAudioTrack(); int currentAudioTrack();
int currentSubtitleTrack(); int currentSubtitleTrack();
int currentVideoTrack(); int currentVideoTrack();
......
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