PDA

View Full Version : IDirectVobSub Interface and Delphi


BlackSun
10th May 2002, 08:23
Hi There,

I am having problems with getting the interface from the DirectVobSub filter using DirectShow.

I think the problem come with the pLangs:
char* pLangs[32] // pLangs[] needs to be preallocated before calling, use LANG_LEN for the length

Seems that I am not declaring it properly. Any help appreciated ;)


------------------------------------------------------------------------
unit DVobSubControls;

interface

uses DirectShow, ActiveX, Windows, Classes, Dialogs, SysUtils;

const
CLSID_DVobSubDecoder : TGuid = '{9852A670-F845-491B-9BE6-EBD841B8A613}';
IID_IDirectVobSubFilter : TGUID = (D1:$3a58b97b;D2:$a2cc;D3:$46b3;D4:($8A,$57,$48,$FA,$B1,$53,$AE,$EE));
IID_IDirectVobSubFilter2 : TGUID = (D1:$639a5c61;D2:$0d72;D3:$4921;D4:($AD,$1A,$B9,$C5,$EC,$A4,$CB,$AF));
// {639A5C61-0D72-4921-AD1A-B9C5ECA4CBAF}
type TLangs=array[1..32] of array[1..256] of char;
type MyLangs=array[1..256] of array[1..32] of char;
type
IDirectVobSubFilter = interface(IUnknown)
['{3A58B97B-A2CC-46b3-8A57-48FAB153AEEE}']
function get_MyFilterData(out fn:Char; out fFlipPicture:boolean; out fHideSubs: boolean; out fNoYUY2Colors:boolean): HResult; stdcall;
function put_MyFilterData(fn:Char; fFlipPicture:boolean; fHideSubs: boolean; fNoYUY2Colors:boolean): HResult; stdcall;
function get_VobSubSettings(out fBuffer:boolean; out iSelected:integer; out nLangs:integer; out pLangs:MyLangs): HResult; stdcall;
function put_VobSubSettings(fBuffer:boolean; iSelected:integer): HResult; stdcall;
function get_TextSettings(out lf:LOGFONT; out color:COLORREF; out fShadow:boolean; out fOutline:boolean; out fAdvancedRenderer:boolean): HResult; stdcall;
function put_TextSettings(lf:LOGFONT; color:COLORREF; fShadow:boolean; fOutline:boolean; fAdvancedRenderer:boolean): HResult; stdcall;
function UnknownFunction: HResult; stdcall;
end;

type
IDirectVobSubFilter2 = interface(IDirectVobSubFilter)
['{639A5C61-0D72-4921-AD1A-B9C5ECA4CBAF}']
function get_FileName(out fn:wChar): HResult; stdcall;
function UnknownFunction: HResult; stdcall;
end;

var
FGrp: IGraphBuilder;


function FindFilter(Cid: TGuid): IBaseFilter;

function IsDVobSubUsed: Boolean;
procedure GetTextSettings(out lf:LOGFONT; out color:COLORREF; out fShadow:boolean; out fOutline:boolean; out fAdvancedRenderer:boolean);
procedure SetTextSettings(lf:LOGFONT; color:COLORREF; fShadow:boolean; fOutline:boolean; fAdvancedRenderer:boolean);
procedure GetVobSubFilename(out fn:wchar);


implementation

procedure GetVobSubFilename(out fn:wchar);
var DVobSub: IbaseFilter;
Setup: IDirectVobSubFilter2;
v: integer;
begin
if FGrp = nil then Exit;
DVobSub:= FindFilter(CLSID_DVobSubDecoder); if DVobSub = nil then Exit;

DVobSub.QueryInterface(IID_IDirectVobSubFilter2, Setup);
if Setup = nil then begin DVobSub:= nil; exit; end;

Setup.get_FileName(fn);

DVobSub:= nil;
Setup:= nil;

end;

procedure SetTextSettings(lf:LOGFONT; color:COLORREF; fShadow:boolean; fOutline:boolean; fAdvancedRenderer:boolean);
var DVobSub: IBasefilter;
Setup: IDirectVobSubFilter;
v: Integer;
begin
if FGrp = nil then Exit;
DVobSub:= FindFilter(CLSID_DVobSubDecoder); if DVobSub = nil then Exit;

DVobSub.QueryInterface(IID_IDirectVobSubFilter, Setup);
if Setup = nil then begin DVobSub:= nil; exit; end;

// v:= Value; if v <-128 then v:=-128; if v>128 then v:=128;

Setup.put_TextSettings(lf,color,fShadow,fOutline,fAdvancedRenderer);

DVobSub:= nil;
Setup:= nil;
end;

procedure GetTextSettings(out lf:LOGFONT; out color:COLORREF; out fShadow:boolean; out fOutline:boolean; out fAdvancedRenderer:boolean);
var DVobSub: IbaseFilter;
Setup: IDirectVobSubFilter;
v: integer;
begin
if FGrp = nil then Exit;
DVobSub:= FindFilter(CLSID_DVobSubDecoder); if DVobSub = nil then Exit;

DVobSub.QueryInterface(IID_IDirectVobSubFilter, Setup);
if Setup = nil then begin DVobSub:= nil; exit; end;

Setup.get_TextSettings(lf,color,fShadow,fOutline,fAdvancedRenderer);

DVobSub:= nil;
Setup:= nil;

end;


function IsDVobSubUsed: Boolean;
begin
Result:= FindFilter(CLSID_DVobSubDecoder) <> nil;
end;

function FindFilter(Cid: TGUID): IBaseFilter;
var EnumF: IEnumFilters;
Fetched: ULong;
Fi: IBaseFilter;
g: TGuid;
FFi: TFilterInfo;
begin
Result:= nil;
if FGrp = nil then Exit;

FGrp.EnumFilters(EnumF);
while EnumF.Next(1, Fi, @Fetched)=S_Ok do begin
Fi.GetClassID(G);
Fi.QueryFilterInfo(FFi);
if IsEqualGUID(g, cid) then begin Result:= Fi; end;
end;
Fi:= nil;
EnumF:= nil;
end;



end.
-----------------------------------------------------------------------
#pragma once

#ifdef __cplusplus
extern "C" {
#endif

#define LANG_LEN 256

// {3A58B97B-A2CC-46b3-8A57-48FAB153AEEE}
DEFINE_GUID(IID_IDirectVobSubFilter,
0x3a58b97b, 0xa2cc, 0x46b3, 0x8a, 0x57, 0x48, 0xfa, 0xb1, 0x53, 0xae, 0xee);

DECLARE_INTERFACE_(IDirectVobSubFilter, IUnknown)
{
STDMETHOD(get_MyFilterData) (THIS_
char* fn, // obsolete, replaced by get_FileName
bool* fFlipPicture,
bool* fHideSubs,
bool* fNoYUY2Colors
) PURE;

STDMETHOD(put_MyFilterData) (THIS_
char* fn, // obsolete, replaced by put_FileName
bool fFlipPicture,
bool fHideSubs,
bool fNoYUY2Colors
) PURE;

STDMETHOD(get_VobSubSettings) (THIS_ // obsolete, replaced by get_VobSubSettings2 and get_Languages
bool* fBuffer,
int* iSelected,
int* nLangs,
char* pLangs[32] // pLangs[] needs to be preallocated before calling, use LANG_LEN for the length
) PURE;

STDMETHOD(put_VobSubSettings) (THIS_ // obsolete, replaced by put_VobSubSettings2 and put_Languages
bool fBuffer,
int iSelected
) PURE;

STDMETHOD(get_TextSettings) (THIS_
LOGFONT* lf,
COLORREF* color,
bool* fShadow,
bool* fOutline,
bool* fAdvancedRenderer
) PURE;

STDMETHOD(put_TextSettings) (THIS_
LOGFONT* lf,
COLORREF color,
bool fShadow,
bool fOutline,
bool fAdvancedRenderer
) PURE;
};

// {639A5C61-0D72-4921-AD1A-B9C5ECA4CBAF}
DEFINE_GUID(IID_IDirectVobSubFilter2,
0x639a5c61, 0xd72, 0x4921, 0xad, 0x1a, 0xb9, 0xc5, 0xec, 0xa4, 0xcb, 0xaf);

DECLARE_INTERFACE_(IDirectVobSubFilter2, IDirectVobSubFilter)
{
STDMETHOD(get_FileName) (THIS_
WCHAR* fn
) PURE;

STDMETHOD(put_FileName) (THIS_
WCHAR* fn
) PURE;

STDMETHOD(get_Languages) (THIS_
int* iSelected,
int* nLangs,
WCHAR* pLangs[32] // pLangs[] needs to be preallocated before calling, use LANG_LEN for the length
) PURE;

STDMETHOD(put_Languages) (THIS_
int iSelected
) PURE;

STDMETHOD(get_MyFilterData2) (THIS_
bool* fDoPreBuffering,
bool* fOSD
) PURE;

STDMETHOD(put_MyFilterData2) (THIS_
bool fDoPreBuffering,
bool fOSD
) PURE;

STDMETHOD(get_TextSettings2) (THIS_
bool* fOverridePlacement,
int* xperc,
int* yperc
) PURE;

STDMETHOD(put_TextSettings2) (THIS_
bool fOverridePlacement,
int xperc,
int yperc
) PURE;

STDMETHOD(get_VobSubSettings2) (THIS_
bool* fBuffer,
bool* fOnlyShowForcedSubs
) PURE;

STDMETHOD(put_VobSubSettings2) (THIS_
bool fBuffer,
bool fOnlyShowForcedSubs
) PURE;

STDMETHOD(get_Timing) (THIS_
int* delay,
int* speed
) PURE;

STDMETHOD(put_Timing) (THIS_
int delay,
int speed
) PURE;
};

// {CA0372C1-2DF8-426d-842C-AD7C7D720741}
DEFINE_GUID(IID_IDirectVobSubFilterZoom,
0xca0372c1, 0x2df8, 0x426d, 0x84, 0x2c, 0xad, 0x7c, 0x7d, 0x72, 0x7, 0x41);

DECLARE_INTERFACE_(IDirectVobSubFilterZoom, IUnknown)
{
STDMETHOD(get_ZoomRect) (THIS_
NORMALIZEDRECT* rect
) PURE;

STDMETHOD(put_ZoomRect) (THIS_
NORMALIZEDRECT rect
) PURE;
};

#ifdef __cplusplus
}
#endif

Swede
10th May 2002, 09:01
If I'm correct, char* pLangs[32], means a 32-item array of char-pointers.
Since Delphi uses AnsiString as default, which is the same as PChar, the Delhpi equivalent would be an: Array [1..32] of String;
The problem is then just to preallocate the strings before you do the call. for i:=1 to 32 do SetLength(arr[i],LANG_LEN);

(I think this is correct :) )

gabest
10th May 2002, 18:38
BlackSun: I see two BIG problems about doing such a thing yet :)

1. I like changing IDirectVobSubFilter2 without no respect to other applications :p

2. Though IDirectVobSubFilter may look finalized (unchanged for ages), but LOGFONT is different for the MBCS and Unicode build!!! (the different versions of the dlls install after the target OS, win9x or nt)

Because none of the interfaces are generally usable at the moment, you seem to be left without any choice :) Of course I could quickly create a third interface in pure unicode... Look for a new release in a few days.

Another thing:

I'm not a delphi guru, but isn't Fi and FFi.pGraph need to be released in this loop at the end?FGrp.EnumFilters(EnumF);
while EnumF.Next(1, Fi, @Fetched)=S_Ok do begin
Fi.GetClassID(G);
Fi.QueryFilterInfo(FFi);
// if(FFi.pGraph <> nil) FFi.pGraph = nil;<-- HERE
if IsEqualGUID(g, cid) then begin Result:= Fi; end;
// Fi = nil; <-- and HERE
end;
Fi:= nil;
EnumF:= nil;And I think you don't need @Fetched either if you only want to get one filter at a time ;)

gabest
10th May 2002, 19:20
And yet another thing :)

How wide is delphi's boolean? 1 or 4 bytes?

aquaplaning
10th May 2002, 20:19
SizeOf(boolean) = 1 byte

BlackSun
11th May 2002, 09:05
Originally posted by gabest
BlackSun: I see two BIG problems about doing such a thing yet :)

1. I like changing IDirectVobSubFilter2 without no respect to other applications :p

2. Though IDirectVobSubFilter may look finalized (unchanged for ages), but LOGFONT is different for the MBCS and Unicode build!!! (the different versions of the dlls install after the target OS, win9x or nt)


I have noticed that some obsolete values give me some crashes... Actually I got a lot of things working, LOGFONT work well but I can't get the lf.lf.fontfacename without a crash.

Maybe you can create another interface for me ? I need to know the languages, the current language, put the language and put_textsettings... ;)

THAiSi
30th October 2006, 11:00
Hi I'm trying to get DirectVobSub (VSFilter) working in Delphi, but put_filename() just doesn't show the subtitles...
It gives a S_OK Result when putting the filename but no subtitles are showing..

I'm Using the DirectShow Pack from progdigy.com.


if (not OpenDialog1.Execute) then Exit;
SubFileName := Copy(OpenDialog1.FileName, 1,
Length(OpenDialog1.FileName) - Length(ExtractFileExt(OpenDialog1.FileName)))
+ '.en.srt';
FilterGraph1.ClearGraph;
FilterGraph1.Active := True;

if (Succeeded((SubtitleFilter as IDirectVobSub2).put_FileName(StringToOleStr(SubFileName)))) then begin
ShowMessage('Subtitle file set!');
end;
FilterGraph1.RenderFile(OpenDialog1.FileName);
FilterGraph1.Play;



Does anyone know why there are no subtitles showing??
and yes, the file put does exist...

THAiSi
14th November 2006, 09:59
I'm getting really crazy about it ... I'm trying to get that VS filter working manually by code for months now and the stuff just won't work!

Has any forum member got this damn thing working? and so how??

if I do a put_filename wich results in S_OK and then call get_filename my program suddenly terminates...

Please help me!