Search code examples
media-playerinno-setuppascalscript

Fade TDirectShow Player (Inno Media Player) volume gradually in Inno Setup


I wrote following code to fade out the Video Playback volume as descending gradually when the installer finishes installing my program.

procedure CurPageChanged(CurPageID: Integer);
var
   X: Integer;
begin
  ... 
  if CurPageID = wpFinished then
  begin
    VideoHandler.Release;
    VideoHandler.Close;
    DSSetVolume(-0);
    X := 0;
    repeat
      DSSetVolume(X);
      Log(IntToStr(X));
      X = X - 1;
    until X = -10000;
    DSStopMediaPlay;
  ...
  end;
  ...
end;

Above code outputs the X value as I expecting to reduce volume gradually and I can see it like -1 , -2 ... -10000 in the log well. But when this repeat process starts,

  • WizardForm appears normally, but nothing is displaying in its wpFinished Page. Only an empty form is displaying. There is nothing is drawn in the form except WizardForm.Caption. It behaves like freezing until the repeat process (loop) finishes.

  • Volume never reduces normally or to a gradual descending order.

  • After the loop finishes and Log outputs -10000, WizardForm displays normally and page also showing normally. Volume stops suddenly because I set to DSStopMediaPlay.

How can I do the above process (gradual reduction of video playback sound) correctly without any freezing or exception?

UPDATE

Following Code can give best results when the User's System Sound has been set to 20% in Sound Control Panel in Windows.

procedure VolumeFadeTimerProc(HandleW, msg, idEvent, TimeSys: LongWord);
begin
  MPEGVideoVolume := MPEGVideoVolume - 15;
  if MPEGVideoVolume < -4000 then
  begin
    DSStopMediaPlay;
    KillTimer( 0, TimerID);
    KillTimer( 0, VolumeFadeTimer);
    Log('Volume Fade Timer has been reset.');
  end
    else
  begin
    Log('MPEG Video Volume has been set to: ' + IntToStr(MPEGVideoVolume));
    DSSetVolume(MPEGVideoVolume);
  end;
end;

Volume Reducing Amount is 15

Maximum Reducing Volume Amount is -4000

Following Code can give best results when the User's System Sound has been set to 100% in Sound Control Panel in Windows.

procedure VolumeFadeTimerProc(HandleW, msg, idEvent, TimeSys: LongWord);
begin
  MPEGVideoVolume := MPEGVideoVolume - 35;
  if MPEGVideoVolume < -10000 then
  begin
    DSStopMediaPlay;
    KillTimer( 0, TimerID);
    KillTimer( 0, VolumeFadeTimer);
    Log('Volume Fade Timer has been reset.');
  end
    else
  begin
    Log('MPEG Video Volume has been set to: ' + IntToStr(MPEGVideoVolume));
    DSSetVolume(MPEGVideoVolume);
  end;
end;

Volume Reducing Amount is 35

Maximum Reducing Volume Amount is -10000

Do I need to automatically change Volume Reducing Amount and Maximum Reducing Volume according to the Amount of user's System Sound set to?

Thanks in advance.


Solution

  • Because you stop the window message pump in your loop. What freezes the window and probably also prevents the volume fade out.

    You have to use a timer to fade out the volume without freezing the message pump.

    [Code]
    
    function SetTimer(
      hWnd: longword; nIDEvent, uElapse: LongWord; lpTimerFunc: LongWord): LongWord;
      external 'SetTimer@user32.dll stdcall';
    
    var
      Volume: Integer;
      VolumeFadeTimer: LongWord;
    
    procedure VolumeFadeTimerProc(
      H: LongWord; Msg: LongWord; IdEvent: LongWord; Time: LongWord);
    begin
      { Fade by -1000 every 100 ms }
      Volume := Volume - 1000;
      if Volume <= -10000 then
      begin
        DSStopMediaPlay;
        KillTimer(0, VolumeFadeTimer);
      end
        else
      begin
        DSSetVolume(Volume);
      end;
    end;
    
    procedure CurPageChanged(CurPageID: Integer);
    begin
      if CurPageID = wpFinished then
      begin
         VideoHandler.Release;
         VideoHandler.Close;
    
         Volume := 0;
         { call VolumeFadeCallback every 100 ms }
         VolumeFadeTimer := SetTimer(0, 0, 100, CreateCallback(@VolumeFadeTimerProc));
         DSSetVolume(Volume);
      end;
    end;
    

    For CreateCallback function, you need Inno Setup 6. If you are stuck with Inno Setup 5, you can use WrapCallback function from InnoTools InnoCallback library.