{$MODESWITCH AUTODEREF}
{$I deng_defines.inc}
unit DMusic;

interface

uses
  {$IFNDEF DENG_USE_NOMUSIC}
  DEngBase,
  {$ENDIF}
  {$IFDEF DENG_USE_MUSIC_OPENAL}
  dopenal,
  {$ENDIF}
  dstrnum,
  dstream,
  dtypes;

type
PMusicStream = ^TMusicStream;
TMusicStream = object
protected
  FReady: Boolean;
  FChannels: LongInt;
  FRate: LongInt;
public
  constructor Init;
  destructor Done; virtual;
  function ReadPCM(Data: PByte; Size: LongInt): LongInt; virtual;
  procedure Rewind; virtual;
  property Ready: Boolean read FReady;
  property Channels: LongInt read FChannels;
  property Rate: LongInt read FRate;
end;

PMusicLoader = ^TMusicLoader;
TMusicLoader = object
public
  constructor Init;
  destructor Done; virtual;
  function Load(Stream: PStream): PMusicStream; virtual;
end;

PMusic = ^TMusic;
TMusic = object
private const
  BUFFER_SIZE = 64 * 1024;
  BUFFERS_COUNT = 4;
{$IFDEF DENG_USE_MUSIC_OPENAL}
private
  FSourceId: ALuint;
  FBufferSize: LongInt;
  FBuffers: array[0 .. BUFFERS_COUNT - 1] of ALuint;
{$ENDIF}
private
  FData: TData;
  FVolume: LongInt;
  FPlayer: PMusicStream;
  FPCM: array[0 .. BUFFER_SIZE] of Byte;
public
  constructor Init;
  destructor Done; virtual;
  procedure OnInit;
  procedure OnDone;
  procedure Update;
  function Play(Data: TData): Boolean; overload;
  //function Play(Stream: PStream; const Owner: Boolean = True): Boolean; overload; deprecated 'use data version';
  //function Play(const FileName: TString): Boolean; overload; deprecated 'use data version';
  procedure Stop; inline;
  procedure Pause; inline;
  procedure SetVolume(Volume: LongInt); inline;
  function IsPlaying: Boolean; inline;
  property Volume: LongInt read FVolume write SetVolume;
end;

procedure RegisterMusicLoader(const Loader: TMusicLoader);

implementation

uses
  DEng;

var
  MusicLoaders: array of PMusicLoader;

constructor TMusicStream.Init;
begin
  FReady := True;
  FChannels := 2;
  FRate := 44100;
end;

destructor TMusicStream.Done;
begin
end;

function TMusicStream.ReadPCM(Data: PByte; Size: LongInt): LongInt;
begin
  Result := 0;
end;

procedure TMusicStream.Rewind;
begin
end;

constructor TMusicLoader.Init;
begin
end;

destructor TMusicLoader.Done;
begin
end;

function TMusicLoader.Load(Stream: PStream): PMusicStream;
begin
  Result := nil;
end;

{$IFDEF DENG_USE_NOMUSIC}
{$I DMusic_no.inc}
{$ENDIF}

{$IFDEF DENG_USE_MUSIC_OPENAL}
{$I DMusic_openal.inc}
{$ENDIF}

procedure RegisterMusicLoader(const Loader: TMusicLoader);
begin
  SetLength(MusicLoaders, Length(MusicLoaders) + 1);
  MusicLoaders[High(MusicLoaders)] := @Loader;
end;

procedure FreeMusicLoaders;
var
  I: LongInt;
begin
  for I := 0 to High(MusicLoaders) do
    MusicLoaders[I]^.Done;
end;

finalization
  FreeMusicLoaders;
end.
