Playing sound during an Inno Setup install

1. Inno Media Player

You can use the Inno Media Player library (sorry for self promotion). Here is an example of its use for playing audio file stored as a temporary file inside of a setup.

Please note, that Inno Media Player is a Unicode library, and so you can use it only with Unicode versions of Inno Setup, not with ANSI ones! There is no support for ANSI versions of Inno Setup…!

[Setup]
AppName=Media Player Project
AppVersion=1.0
DefaultDirName={pf}\Media Player Project

[Files]
Source: "AudioFile.mp3"; Flags: dontcopy
Source: "MediaPlayer.dll"; Flags: dontcopy

[Code]
const
  EC_COMPLETE = $01;
type
  TDirectShowEventProc = procedure(EventCode, Param1, Param2: Integer);

function DSGetLastError(var ErrorText: WideString): HRESULT;
  external 'DSGetLastError@files:mediaplayer.dll stdcall';
function DSPlayMediaFile: Boolean;
  external 'DSPlayMediaFile@files:mediaplayer.dll stdcall';
function DSStopMediaPlay: Boolean;
  external 'DSStopMediaPlay@files:mediaplayer.dll stdcall';
function DSSetVolume(Value: LongInt): Boolean;
  external 'DSSetVolume@files:mediaplayer.dll stdcall';
function DSInitializeAudioFile(FileName: WideString; 
  CallbackProc: TDirectShowEventProc): Boolean; 
  external 'DSInitializeAudioFile@files:mediaplayer.dll stdcall';

procedure OnMediaPlayerEvent(EventCode, Param1, Param2: Integer); 
begin
  if EventCode = EC_COMPLETE then
  begin
    { playback is done, so you can e.g. play the stream again, play another }
    { one using the same code as in InitializeWizard (in that case would be }
    { better to wrap that in some helper function) or do just nothing }
  end;
end;

procedure InitializeWizard;
var
  ErrorCode: HRESULT;
  ErrorText: WideString;   
begin
  ExtractTemporaryFile('AudioFile.mp3');
  if DSInitializeAudioFile(ExpandConstant('{tmp}\AudioFile.mp3'), 
    @OnMediaPlayerEvent) then
  begin
    DSSetVolume(-2500);
    DSPlayMediaFile;
  end
  else
  begin
    ErrorCode := DSGetLastError(ErrorText);
    MsgBox('TDirectShowPlayer error: ' + IntToStr(ErrorCode) + '; ' + 
      ErrorText, mbError, MB_OK);
  end;
end;

procedure DeinitializeSetup;
begin
  DSStopMediaPlay;
end;

2. Bass Audio Library

Or you can use for instance the Bass Audio Library library, which is free for non-commercial use. To play for instance an infinite loop with that library, you might use script like follows.

This script and the library are compatible with both versions of Inno Setup, ANSI and Unicode.

[Setup]
AppName=Bass Audio Project
AppVersion=1.0
DefaultDirName={pf}\Bass Audio Project

[Files]
Source: "Bass.dll"; Flags: dontcopy
Source: "AudioFile.mp3"; Flags: dontcopy

[Code]
const  
  BASS_SAMPLE_LOOP = 4;
  BASS_UNICODE = $80000000;
  BASS_CONFIG_GVOL_STREAM = 5;
const
  #ifndef UNICODE
    EncodingFlag = 0;
  #else
    EncodingFlag = BASS_UNICODE;
  #endif
type
  HSTREAM = DWORD;

function BASS_Init(device: LongInt; freq, flags: DWORD; 
  win: HWND; clsid: Cardinal): BOOL;
  external 'BASS_Init@files:bass.dll stdcall';
function BASS_StreamCreateFile(mem: BOOL; f: string; offset1: DWORD; 
  offset2: DWORD; length1: DWORD; length2: DWORD; flags: DWORD): HSTREAM;
  external 'BASS_StreamCreateFile@files:bass.dll stdcall';
function BASS_ChannelPlay(handle: DWORD; restart: BOOL): BOOL; 
  external 'BASS_ChannelPlay@files:bass.dll stdcall';
function BASS_SetConfig(option: DWORD; value: DWORD ): BOOL;
  external 'BASS_SetConfig@files:bass.dll stdcall';
function BASS_Free: BOOL;
  external 'BASS_Free@files:bass.dll stdcall';

procedure InitializeWizard;
var
  StreamHandle: HSTREAM;
begin
  ExtractTemporaryFile('AudioFile.mp3');
  if BASS_Init(-1, 44100, 0, 0, 0) then
  begin
    StreamHandle := BASS_StreamCreateFile(False, 
      ExpandConstant('{tmp}\AudioFile.mp3'), 0, 0, 0, 0, 
      EncodingFlag or BASS_SAMPLE_LOOP);
    BASS_SetConfig(BASS_CONFIG_GVOL_STREAM, 2500);
    BASS_ChannelPlay(StreamHandle, False);
  end;
end;

procedure DeinitializeSetup;
begin
  BASS_Free;
end;

Leave a Comment