(************************************************************************
 *                                                                      *
 *   (C) 2006 Antoine Potten                                            *
 *   http://www.antp.be/software                                        *
 *                                                                      *
 ************************************************************************
 *                                                                      *
 *   This program is free software; you can redistribute it and/or      *
 *   modify it under the terms of the GNU General Public License        *
 *   as published by the Free Software Foundation; either version 2     *
 *   of the License, or (at your option) any later version.             *
 *                                                                      *
 *   This program is distributed in the hope that it will be useful,    *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of     *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      *
 *   GNU General Public License for more details.                       *
 *                                                                      *
 ************************************************************************)

unit MediaInfo;

interface

uses
  Classes, Windows, SysUtils;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

const
  MedaInfoExpectedVersion = '0.7';

type
  TMediaInfoHandle = Pointer;

  TMediaInfoStream =( misStreamGeneral, misStreamVideo, misStreamAudio, misStreamText, misStreamChapters, misStreamImage, misStreamMax );
  TMediaInfoInfo = ( miiInfoName, miiInfoText, miiInfoMeasure, miiInfoOptions, miiInfoNameText, miiInfoMeasureText, miiInfoInfo, miiInfoHowTo, miiInfoMax );

  TMediaInfoProcNew = function (): TMediaInfoHandle; stdcall;
  TMediaInfoProcOption = function (AHandle: TMediaInfoHandle; AOption: PWideChar; AValue: PWideChar): PWideChar; stdcall;
  TMediaInfoProcOpen = function (AHandle: TMediaInfoHandle; AFile: PWideChar): Integer; stdcall;
  TMediaInfoProcGet = function (AHandle: TMediaInfoHandle; AStreamKind: Integer; AStreamNumber: Integer; AParameter: PWideChar; AKindOfInfo: Integer; AKindOfSearch: Integer): PWideChar; stdcall;
  TMediaInfoProcGetI = function (AHandle: TMediaInfoHandle; AStreamKind: Integer; AStreamNumber: Integer; AParameter: Integer; AKindOfInfo: Integer): PWideChar; stdcall;
  TMediaInfoProcDelete = procedure (AHandle: TMediaInfoHandle); stdcall;

  TMediaInfo = class(TObject)
  private
    FLib: Cardinal;
    FHandle: TMediaInfoHandle;
    FProcNew : TMediaInfoProcNew;
    FProcOption: TMediaInfoProcOption;
    FProcOpen: TMediaInfoProcOpen;
    FProcGet: TMediaInfoProcGet;
    FProcGetI: TMediaInfoProcGetI;
    FProcDelete: TMediaInfoProcDelete;
  protected
  public
    constructor Create(const ADLLPath: TFileName; const CheckVersion: Boolean);
    destructor Destroy; override;
    function Version: WideString;
    function Parameters: WideString;
    function Open(const AFileName: WideString): Integer;
    function Get(const AStreamKind: TMediaInfoStream; const AStreamNumber: Integer; const AParameter: WideString; const AKindOfInfo: TMediaInfoInfo = miiInfoText; const AKindOfSearch: TMediaInfoInfo = miiInfoName): string;
    function GetI(const AStreamKind: TMediaInfoStream; const AStreamNumber: Integer; const AParameter: Integer; const AKindOfInfo: TMediaInfoInfo = miiInfoText): string;
  end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

implementation

uses
  functions_str;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

constructor TMediaInfo.Create(const ADLLPath: TFileName; const CheckVersion: Boolean);
var
  MajorVersion: string;
begin
  FLib := LoadLibrary(PChar(ADLLPath));
  if FLib = 0 then
    RaiseLastOSError;
  if CheckVersion then
  begin
    MajorVersion := Version;
    if not StartsStr(MedaInfoExpectedVersion, MajorVersion) then
      raise Exception.Create(Format('%s: wrong version, expected "%s" but found "%s"', [ExtractFileName(ADLLPath), MedaInfoExpectedVersion, MajorVersion]));
  end;
  @FProcNew := GetProcAddress(FLib, 'MediaInfo_New');
  if @FProcNew = nil then
    RaiseLastOSError;
  FHandle := FProcNew();
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

destructor TMediaInfo.Destroy;
begin
  @FProcDelete := GetProcAddress(FLib, 'MediaInfo_Delete');
  if @FProcDelete <> nil then
    FProcDelete(FHandle);
  FreeLibrary(FLib);
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

function TMediaInfo.Version: WideString;
var
  s1, s2: string;
begin
  if @FProcOption = nil then
    @FProcOption := GetProcAddress(FLib, 'MediaInfo_Option');
  if @FProcOption = nil then
    RaiseLastOSError;
  Result := FProcOption(nil, PWideChar(WideString('Info_Version')), PWideChar(WideString('')));
  Split(Result, ' - ', s1, s2, False);
  Result := s2;
  Split(Result, ' - ', s1, s2, True);
  Result := s1;
  if (Length(Result) > 0) and (Result[1] = 'v') then
    Delete(Result, 1, 1);
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

function TMediaInfo.Open(const AFileName: WideString): Integer;
begin
  if @FProcOpen = nil then
    @FProcOpen := GetProcAddress(FLib, 'MediaInfo_Open');
  if @FProcOpen = nil then
    RaiseLastOSError;
  Result := FProcOpen(FHandle, PWideChar(AFileName));
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

function TMediaInfo.Get(const AStreamKind: TMediaInfoStream; const AStreamNumber: Integer; const AParameter: WideString; const AKindOfInfo, AKindOfSearch: TMediaInfoInfo): string;
begin
  if @FProcGet = nil then
    @FProcGet := GetProcAddress(FLib, 'MediaInfo_Get');
  if @FProcGet = nil then
    RaiseLastOSError;
  Result := FProcGet(FHandle, Integer(AStreamKind), AStreamNumber, PWideChar(AParameter), Integer(AKindOfInfo), Integer(AKindOfSearch));
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

function TMediaInfo.GetI(const AStreamKind: TMediaInfoStream; const AStreamNumber: Integer; const AParameter: Integer; const AKindOfInfo: TMediaInfoInfo): string;
begin
  if @FProcGetI = nil then
    @FProcGetI := GetProcAddress(FLib, 'MediaInfo_GetI');
  if @FProcGetI = nil then
    RaiseLastOSError;
  Result := FProcGetI(FHandle, Integer(AStreamKind), AStreamNumber, AParameter, Integer(AKindOfInfo));
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

function TMediaInfo.Parameters: WideString;
begin
  if @FProcOption = nil then
    @FProcOption := GetProcAddress(FLib, 'MediaInfo_Option');
  if @FProcOption = nil then
    RaiseLastOSError;
  Result := FProcOption(nil, PWideChar(WideString('Info_Parameters')), PWideChar(WideString('')));
end;

{-------------------------------------------------------------------------------
-------------------------------------------------------------------------------}

end.
