Libvlc wrapperの改良

libvlc_new_from_pathlibvlc_audio_set_volumeの追加

以前の記事で作成していたLibvlcのwarpperを少しだけ補強します。ローカルマシンの動画ファイルの再生ができるようにしつつ、再生時のオーディオのレベルも変更できるようにします。変更するのは、vlcwrapper.hになります。それほど長くないので、まるまる掲載してしまいますかね。

#ifndef vlcwrapper
#define vlcwrapper

#ifndef _WIN64
#error compile 64bit mode
#endif
#include <vcl.h>
#include <vlc/vlc.h>
#include <windows.h>
#include <Registry.hpp>


AnsiString GetVLCLibPath()
{
	AnsiString S;
	AnsiString KeyName = "Software\\VideoLAN\\VLC";

	TRegistry *Registry = new TRegistry(KEY_READ);
	try {
		Registry->RootKey = HKEY_LOCAL_MACHINE;
	 // 存在しない場合は作成しないので、False
		Registry->OpenKey(KeyName, false);
		S = Registry->ReadString("InstallDir");
	 }
	 __finally {
		delete Registry;
	 }
	 return S;

}

//LIBVLC_API int libvlc_audio_set_volume( libvlc_media_player_t *p_mi, int i_volume );



class VLC {
	private:

	typedef int  WINAPI (*plibvlc_audio_set_volume)(libvlc_media_player_t*,int);
	typedef libvlc_instance_t* WINAPI (*plibvlcnew)(int , const char*);
	typedef libvlc_media_t* WINAPI (*plibvlcmedianewlocation)(libvlc_instance_t* , const char*);
	typedef libvlc_media_t* WINAPI (*plibvlcmedianewpath)(libvlc_instance_t* , const char*);
	typedef libvlc_media_player_t* WINAPI (*plibvlcmediaplayernewfrommedia)(libvlc_media_t*);
	typedef void WINAPI (*plibvlcmediarelease)(libvlc_media_t*);
	typedef void WINAPI (*plibvlcvideosetscale)(libvlc_media_player_t*,float);
	typedef void WINAPI (*plibvlcmediaplayerplay)(libvlc_media_player_t*);
	typedef void WINAPI (*plibvlcmediaaddoption)(libvlc_media_t*,const char*);
	typedef bool WINAPI (*plibvlcmediaplayerisplaying)(libvlc_media_player_t *);
	typedef void WINAPI (*plibvlcmediaplayersethwnd)(libvlc_media_player_t *,HWND);
	typedef void WINAPI (*plibvlcmediaplayerstop)(libvlc_media_player_t*);
	typedef void WINAPI (*plibvlcmediaplayerrelease)(libvlc_media_player_t*);
	typedef void WINAPI (*plibvlcrelease)(libvlc_instance_t*);

	HMODULE avlccore;
	HMODULE avlc;
	HMODULE axvlc;

	//plibvlcmediaaddoption libvlc_media_add_option;
	plibvlc_audio_set_volume libvlc_audio_set_volume;
	plibvlcnew libvlc_new;
	plibvlcmedianewlocation libvlc_media_new_location;
	plibvlcmedianewpath libvlc_media_new_path;
	plibvlcmediaplayernewfrommedia libvlc_media_player_new_from_media;
	plibvlcmediarelease libvlc_media_release;
	plibvlcmediaplayerplay libvlc_media_player_play;
	plibvlcmediaplayersethwnd libvlc_media_player_set_hwnd;
	plibvlcvideosetscale libvlc_video_set_scale;
	plibvlcmediaaddoption libvlc_media_add_option;
	plibvlcmediaplayerisplaying libvlc_media_player_is_playing;
	plibvlcmediaplayerstop libvlc_media_player_stop;
	plibvlcmediaplayerrelease libvlc_media_player_release;
	plibvlcrelease libvlc_release;

	/*
        if (libvlc_audio_set_volume(media_player, 50) == -1) {
        printf("Failed to set volume.\n");
    } else {
        printf("Volume set to 50%%.\n");
    }
*/

	libvlc_media_player_t* media_player;
	libvlc_instance_t* instance;
	libvlc_media_t* VlcMedia;


	void initaddress(){
			AnsiString path;
			char buf[100];

		path = GetVLCLibPath();

		//ShowMessage(path);

		path += "\\";

		AnsiString p1 = path + "libvlc.dll";
		AnsiString p2 = path + "libvlccore.dll";
		AnsiString p3 = path + "axvlc.dll";


		avlccore = LoadLibraryA(p2.c_str());
		avlc = LoadLibraryA(p1.c_str());
		axvlc = LoadLibraryA(p3.c_str());

		//	avlccore = LoadLibraryA(p2.c_str());

		if( !avlc )
			ShowMessage("libvlc.dll loading error");

		if( !avlccore )
			ShowMessage("libvlccore.dll loading error");

		if( !axvlc )
			ShowMessage("axvlc.dll loading error");

		FARPROC proc = GetProcAddress(avlc,"libvlc_new");
		if(proc == NULL ){
			ShowMessage("getting libvlc_new is failed");
		}
	//plibvlcmediaplayerisplaying glibvlc_media_player_is_playing;

		libvlc_new = reinterpret_cast <plibvlcnew>(proc);

		FARPROC proc2 = GetProcAddress(avlc,"libvlc_media_new_location");
		if(proc2 == NULL ){
			ShowMessage("getting libvlc_media_new_location is failed");
		}

		libvlc_media_new_location = reinterpret_cast <plibvlcmedianewlocation>(proc2);

		//---------------------------------------
		FARPROC proc2x = GetProcAddress(avlc,"libvlc_media_new_path");
		if(proc2x == NULL ){
			ShowMessage("getting libvlc_media_new_path is failed");
		}

		libvlc_media_new_path = reinterpret_cast <plibvlcmedianewpath>(proc2x);

		//---------------------------------------------------------
		FARPROC proc2xy = GetProcAddress(avlc,"libvlc_audio_set_volume");
		if(proc2xy == NULL ){
			ShowMessage("getting libvlc_autio_set_volume is failed");
		}

		libvlc_audio_set_volume = reinterpret_cast <plibvlc_audio_set_volume>(proc2xy);

		//---------------------------------------------------------

		FARPROC proc3 = GetProcAddress(avlc,"libvlc_media_player_new_from_media");
			if(proc3 == NULL ){
				ShowMessage("getting libvlc_player_new_from_media is failed");
			}

		libvlc_media_player_new_from_media = reinterpret_cast <plibvlcmediaplayernewfrommedia>(proc3);


		FARPROC proc4 = GetProcAddress(avlc,"libvlc_media_release");
		if( proc4  == NULL ){
			ShowMessage("getting libvlc_media_release is failed");
		}

		libvlc_media_release = reinterpret_cast <plibvlcmediarelease>(proc4);

		FARPROC proc5 = GetProcAddress(avlc,"libvlc_video_set_scale");
		if(proc5 == NULL ){
			ShowMessage("getting libvlc_video_set_scale is failed");
		}

		libvlc_video_set_scale = reinterpret_cast <plibvlcvideosetscale>(proc5);

		FARPROC proc6 = GetProcAddress(avlc,"libvlc_media_player_play");
		if(proc6 == NULL ){
			ShowMessage("getting libvlc_media_player_play is failed");
		}

		libvlc_media_player_play = reinterpret_cast <plibvlcmediaplayerplay>(proc6);


		FARPROC proc7 = GetProcAddress(avlc,"libvlc_media_add_option");

		if(proc7 == NULL ){
			ShowMessage("getting libvlc_media_add_option is failed");
		}

		libvlc_media_add_option = reinterpret_cast <plibvlcmediaaddoption>(proc7);

		FARPROC proc8 = GetProcAddress(avlc,"libvlc_media_add_option");

		if(proc8 == NULL ){
			ShowMessage("getting libvlc_media_player_is_playing is failed");
		}

		libvlc_media_player_is_playing = reinterpret_cast <plibvlcmediaplayerisplaying>(proc8);


		FARPROC proc9 = GetProcAddress(avlc,"libvlc_media_player_set_hwnd");

		if(proc9 == NULL ){
			ShowMessage("getting libvlc_media_player_set_hwnd is failed");
		}

		libvlc_media_player_set_hwnd = reinterpret_cast <plibvlcmediaplayersethwnd>(proc9);



		FARPROC proc10 = GetProcAddress(avlc,"libvlc_media_player_stop");

		if(proc10 == NULL ){
			ShowMessage("getting libvlc_media_player_stop is failed");
		}

		libvlc_media_player_stop = reinterpret_cast <plibvlcmediaplayerstop>(proc10);

		FARPROC proc11 = GetProcAddress(avlc,"libvlc_media_player_release");

		if(proc11 == NULL ){
			ShowMessage("getting libvlc_media_player_release is failed");
		}

		libvlc_media_player_release = reinterpret_cast <plibvlcmediaplayerrelease>(proc11);

		FARPROC proc12 = GetProcAddress(avlc,"libvlc_release");

		if(proc12 == NULL ){
			ShowMessage("getting libvlc_release is failed");
		}

		libvlc_release = reinterpret_cast <plibvlcrelease>(proc12);


	}

	public:


	VLC(AnsiString location){

		initaddress();
		instance = libvlc_new(0, NULL);

		if( FileExists(location) )
			VlcMedia = libvlc_media_new_path(instance,location.c_str());
		else
			VlcMedia =  libvlc_media_new_location(instance,location.c_str());

		media_player = libvlc_media_player_new_from_media(VlcMedia);
		libvlc_media_release(VlcMedia);
	}

	void SetHWND(HWND Handle){
		 libvlc_media_player_set_hwnd(media_player,Handle);
	}

	void Option(AnsiString option){

		libvlc_media_add_option(VlcMedia,option.c_str());
		//libvlc_media_add_option(VlcMedia,option);

	}

	void SetVolume(int vol)
	{
		libvlc_audio_set_volume(media_player,vol);

    }
	void Play(void){
		 libvlc_media_player_play(media_player);
	}

	void Stop(void){

		if(!media_player)
			return;

		libvlc_media_player_stop(media_player);

		libvlc_media_player_release(media_player);



		libvlc_release(instance);
	}

};

#endif

冒頭にも書いたように、libvlcの関数を二つ追加して、コンストラクタをちょいとだけ修正しました。

VLC(AnsiString location){

		initaddress();
		instance = libvlc_new(0, NULL);

		if( FileExists(location) )
			VlcMedia = libvlc_media_new_path(instance,location.c_str());
		else
			VlcMedia =  libvlc_media_new_location(instance,location.c_str());

		media_player = libvlc_media_player_new_from_media(VlcMedia);
		libvlc_media_release(VlcMedia);
}

要するにlocationがローカルファイルを指していれば、libvlc_media_new_pathを呼び、それ以外のrtsp://云々やらdshow://云々だったらlibvlc_media_new_locationを呼ぶというだけのことです。aviファイルの再生を含めたテストプログラムの外観は、

こんな感じで、ボタンx4、TPanelx1、TOpenDialogx1,TTrackBarx1を配置します。

Unit1.cppは、

#include <vcl.h>
#pragma hdrstop

#include "vlcwrapper.h"

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
int volume = 0;
VLC* vlc;

//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{

}
//---------------------------------------------------------------------------
void __fastcall TForm1::PlayClick(TObject *Sender)
{
	if( OpenDialog1->Execute()){

		vlc = new VLC(OpenDialog1->FileName);
		vlc->SetHWND(Panel1->Handle);
		vlc->SetVolume(volume);
		vlc->Play();

	}


}
//---------------------------------------------------------------------------
void __fastcall TForm1::TrackBar1Change(TObject *Sender)
{
    volume = TrackBar1->Position;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::StopClick(TObject *Sender)
{
	vlc->Stop();
	delete vlc;

}
//---------------------------------------------------------------------------

void __fastcall TForm1::dshowClick(TObject *Sender)
{
	vlc = new VLC("dshow://");
			vlc->SetHWND(Panel1->Handle);
		vlc->SetVolume(volume);
		vlc->Play();

}
//---------------------------------------------------------------------------

void __fastcall TForm1::rtspClick(TObject *Sender)
{
	vlc = new VLC("rtsp://admin:password@192.168.0.xxx");
	vlc->SetHWND(Panel1->Handle);
		vlc->SetVolume(volume);
		vlc->Play();

}
//---------------------------------------------------------------------------

Buildして起動すると、

TrackBar1をドラッグして適宜音量変えて、“Play”をクリック。下のようにファイル選択ダイアログが出るので、選んで“開く”をクリック。

動作中は、

ちなみに再生中に音量レベルは変更できません。

一応動いているようです。同時に複数のaviファイルを再生するためには、VLCのインスタンスをクラスに内包するような変更が必要ですので注意してください。すくなくともglobalなVLC* vlcを使ってはダメですよね。

コメント