Difference between revisions of "Play Sound Multiplatform"

From Lazarus wiki
Jump to navigationJump to search
(Improved PlaySound proc to include more command-line players)
Line 54: Line 54:
 
*Here's the PlaySound procedure
 
*Here's the PlaySound procedure
 
<syntaxhighlight>
 
<syntaxhighlight>
procedure PlaySound(Const szSoundFilename:String);
+
procedure PlaySound(const szSoundFilename: string);
Var
+
var
   flags:Word;
+
   flags: word;
   linuxplaycommand:String;
+
   szNonWindowsPlayCommand: string;
 
begin
 
begin
linuxplaycommand:='';
+
  szNonWindowsPlayCommand := '';
 
{$IFDEF WINDOWS}
 
{$IFDEF WINDOWS}
        If fPlayStyle = psASync then flags:=SND_ASYNC OR SND_NODEFAULT
+
  if fPlayStyle = psASync then
        else flags:=SND_SYNC OR SND_NODEFAULT;
+
    flags := SND_ASYNC or SND_NODEFAULT
        TRY
+
  else
        sndPlaySound(PChar(szSoundFilename:String),flags);
+
    flags := SND_SYNC or SND_NODEFAULT;
        except
+
  try
          ShowMessage('Unable to play ' + szSoundFilename:String);
+
    sndPlaySound(PChar(szSoundFilename), flags);
        end;
+
  except
 +
    ShowMessage(C_UnableToPlay + szSoundFilename);
 +
  end;
 
{$ELSE}
 
{$ELSE}
      // How to play in Linux? Use generic Linux commands
+
  // How to play in Linux? Use generic Linux commands
      // Use asyncprocess to play sound as SND_ASYNC
+
  // Use asyncprocess to play sound as SND_ASYNC
 
+
  // Try play
// Try play
+
  if (FindDefaultExecutablePath('play') <> '') then
If (FindDefaultExecutablePath('play') <> '') then linuxplaycommand:='play';
+
    szNonWindowsPlayCommand := 'play';
// Try aplay
+
  // Try aplay
If (linuxplaycommand='') then
+
  if (szNonWindowsPlayCommand = '') then
  If (FindDefaultExecutablePath('aplay') <> '') Then linuxplaycommand:='aplay';
+
    if (FindDefaultExecutablePath('aplay') <> '') then
// Try paplay
+
      szNonWindowsPlayCommand := 'aplay -q ';
If (linuxplaycommand='') then
+
  // Try paplay
  If (FindDefaultExecutablePath('paplay') <> '') Then linuxplaycommand:='paplay';
+
  if (szNonWindowsPlayCommand = '') then
// proceed if we managed to find a valid command
+
    if (FindDefaultExecutablePath('paplay') <> '') then
If (linuxplaycommand <> '') then
+
      szNonWindowsPlayCommand := 'paplay';
BEGIN
+
  // Try mplayer
      If fPlayStyle = psASync then
+
  if (szNonWindowsPlayCommand = '') then
      begin
+
    if (FindDefaultExecutablePath('mplayer') <> '') then
            If SoundPlayerAsyncProcess=Nil then SoundPlayerAsyncProcess:=Tasyncprocess.Create(Nil);
+
      szNonWindowsPlayCommand := 'mplayer -really-quiet ';
            SoundPlayerAsyncProcess.CurrentDirectory:=ExtractFileDir(szSoundFilename);
+
  // Try CMus
            SoundPlayerAsyncProcess.Executable:=FindDefaultExecutablePath(linuxplaycommand);
+
  if (szNonWindowsPlayCommand = '') then
            SoundPlayerAsyncProcess.Parameters.Clear;
+
    if (FindDefaultExecutablePath('CMus') <> '') then
            SoundPlayerAsyncProcess.Parameters.Add(szSoundFilename);
+
      szNonWindowsPlayCommand := 'CMus ';
            TRY
+
  // Try pacat
            SoundPlayerAsyncProcess.Execute;
+
  if (szNonWindowsPlayCommand = '') then
            except
+
    if (FindDefaultExecutablePath('pacat') <> '') then
              ShowMessage('Playstyle=paASync: Unable to play ' + szSoundFilename);
+
      szNonWindowsPlayCommand := 'pacat -p ';
            end;
+
  // Try ffplay
      end
+
  if (szNonWindowsPlayCommand = '') then
      else
+
    if (FindDefaultExecutablePath('ffplay') <> '') then
      begin
+
      szNonWindowsPlayCommand := 'ffplay -autoexit -nodisp ';
          If SoundPlayerSyncProcess=Nil then SoundPlayerSyncProcess:=Tprocess.Create(Nil);
+
  // Try cvlc
          SoundPlayerSyncProcess.CurrentDirectory:=ExtractFileDir(szSoundFilename);
+
  if (szNonWindowsPlayCommand = '') then
          SoundPlayerSyncProcess.Executable:=FindDefaultExecutablePath(linuxplaycommand);
+
    if (FindDefaultExecutablePath('cvlc') <> '') then
          SoundPlayersyncProcess.Parameters.Clear;
+
      szNonWindowsPlayCommand := 'cvlc -q --play-and-exit ';
          SoundPlayerSyncProcess.Parameters.Add(szSoundFilename);
+
  // Try canberra-gtk-play
          TRY
+
  if (szNonWindowsPlayCommand = '') then
          SoundPlayerSyncProcess.Execute;
+
    if (FindDefaultExecutablePath('canberra-gtk-play') <> '') then
          SoundPlayersyncProcess.WaitOnExit;
+
      szNonWindowsPlayCommand := 'canberra-gtk-play -c never -f ';
          except
+
  // Try Macintosh command?
            ShowMessage('Playstyle=paSync: Unable to play ' + szSoundFilename);
+
  if (szNonWindowsPlayCommand = '') then
          end;
+
    if (FindDefaultExecutablePath('afplay') <> '') then
      end;
+
      szNonWindowsPlayCommand := 'afplay';
END;
+
  // proceed if we managed to find a valid command
 +
  if (szNonWindowsPlayCommand <> '') then
 +
  begin
 +
    if fPlayStyle = psASync then
 +
    begin
 +
      if SoundPlayerAsyncProcess = nil then
 +
        SoundPlayerAsyncProcess := Tasyncprocess.Create(nil);
 +
      SoundPlayerAsyncProcess.CurrentDirectory := ExtractFileDir(szSoundFilename);
 +
      SoundPlayerAsyncProcess.Executable :=
 +
        FindDefaultExecutablePath(szNonWindowsPlayCommand);
 +
      SoundPlayerAsyncProcess.Parameters.Clear;
 +
      SoundPlayerAsyncProcess.Parameters.Add(szSoundFilename);
 +
      try
 +
        SoundPlayerAsyncProcess.Execute;
 +
      except
 +
        On E: Exception do
 +
          E.CreateFmt('Playstyle=paASync: ' + C_UnableToPlay +
 +
            '%s Message:%s', [szSoundFilename, E.Message]);
 +
      end;
 +
    end
 +
    else
 +
    begin
 +
      if SoundPlayerSyncProcess = nil then
 +
        SoundPlayerSyncProcess := Tprocess.Create(nil);
 +
      SoundPlayerSyncProcess.CurrentDirectory := ExtractFileDir(szSoundFilename);
 +
      SoundPlayerSyncProcess.Executable :=
 +
        FindDefaultExecutablePath(szNonWindowsPlayCommand);
 +
      SoundPlayersyncProcess.Parameters.Clear;
 +
      SoundPlayerSyncProcess.Parameters.Add(szSoundFilename);
 +
      try
 +
        SoundPlayerSyncProcess.Execute;
 +
        SoundPlayersyncProcess.WaitOnExit;
 +
      except
 +
        On E: Exception do
 +
          E.CreateFmt('Playstyle=paSync: ' + C_UnableToPlay +
 +
            '%s Message:%s', [szSoundFilename, E.Message]);
 +
      end;
 +
    end;
 +
  end
 +
  else
 +
    raise Exception.CreateFmt('The play command %s does not work on your system',
 +
      [szNonWindowsPlayCommand]);
 
{$ENDIF}
 
{$ENDIF}
 
end;
 
end;

Revision as of 10:52, 13 September 2014

Summary

  • The object is to play a simple WAV sound both in Windows and Linux (Sync and ASync)
  • There are lots of libraries to do this in a complicated way, but this code should suffice for simple use

Download Component

Download from the lazarus CCR here

Installation of component

  • Download the 'playsoundpackage' package from the Lazarus CCR repository and copy the folder to a folder off your lazarus components folder
  • Install the package (open it, Compile then Install it) and TPlaysound will appear on your 'LazControls' components tab
  • Drop onto a form, set properties and you are good to go
  • Opening the demo application will give you a good idea how to set the additional properties and use the component

Version

  • As reported in the IDE. Initial version is 0.0.1

License

  • LGPLv2

Code

  • Here is the Uses clause in the Implementation section:
..other units..
FileUtil{$IFDEF WINDOWS},mmsystem{$ELSE},asyncprocess,process{$ENDIF}
..other units..
  • Declare a type:
TPlayStyle = (psAsync,psSync);
  • Declare some variables:
{$IFDEF LINUX}
SoundPlayerAsyncProcess:Tasyncprocess;
SoundPlayerSyncProcess:Tprocess;
{$ENDIF}
fPathToSoundFile:String;
fPlayStyle:TPlayStyle;
  • And a worker function:
procedure PlaySound(Const szSoundFilename:String);
  • And a couple of constants:
{$IFDEF LINUX}
CONST // Defined in mmsystem
  SND_SYNC=0;
  SND_ASYNC=1;
  SND_NODEFAULT=2;
{$ENDIF}
  • Now you are good to go:
fPlayStyle := psASync;
fPathToSoundFile:='mysound.wav';
If FileExistsUTF8(fPathToSoundFile) then PlaySound(fPathToSoundFile);
  • Here's the PlaySound procedure
procedure PlaySound(const szSoundFilename: string);
var
  flags: word;
  szNonWindowsPlayCommand: string;
begin
  szNonWindowsPlayCommand := '';
{$IFDEF WINDOWS}
  if fPlayStyle = psASync then
    flags := SND_ASYNC or SND_NODEFAULT
  else
    flags := SND_SYNC or SND_NODEFAULT;
  try
    sndPlaySound(PChar(szSoundFilename), flags);
  except
    ShowMessage(C_UnableToPlay + szSoundFilename);
  end;
{$ELSE}
  // How to play in Linux? Use generic Linux commands
  // Use asyncprocess to play sound as SND_ASYNC
  // Try play
  if (FindDefaultExecutablePath('play') <> '') then
    szNonWindowsPlayCommand := 'play';
  // Try aplay
  if (szNonWindowsPlayCommand = '') then
    if (FindDefaultExecutablePath('aplay') <> '') then
      szNonWindowsPlayCommand := 'aplay -q ';
  // Try paplay
  if (szNonWindowsPlayCommand = '') then
    if (FindDefaultExecutablePath('paplay') <> '') then
      szNonWindowsPlayCommand := 'paplay';
  // Try mplayer
  if (szNonWindowsPlayCommand = '') then
    if (FindDefaultExecutablePath('mplayer') <> '') then
      szNonWindowsPlayCommand := 'mplayer -really-quiet ';
  // Try CMus
  if (szNonWindowsPlayCommand = '') then
    if (FindDefaultExecutablePath('CMus') <> '') then
      szNonWindowsPlayCommand := 'CMus ';
  // Try pacat
  if (szNonWindowsPlayCommand = '') then
    if (FindDefaultExecutablePath('pacat') <> '') then
      szNonWindowsPlayCommand := 'pacat -p ';
  // Try ffplay
  if (szNonWindowsPlayCommand = '') then
    if (FindDefaultExecutablePath('ffplay') <> '') then
      szNonWindowsPlayCommand := 'ffplay -autoexit -nodisp ';
  // Try cvlc
  if (szNonWindowsPlayCommand = '') then
    if (FindDefaultExecutablePath('cvlc') <> '') then
      szNonWindowsPlayCommand := 'cvlc -q --play-and-exit ';
  // Try canberra-gtk-play
  if (szNonWindowsPlayCommand = '') then
    if (FindDefaultExecutablePath('canberra-gtk-play') <> '') then
      szNonWindowsPlayCommand := 'canberra-gtk-play -c never -f ';
  // Try Macintosh command?
  if (szNonWindowsPlayCommand = '') then
    if (FindDefaultExecutablePath('afplay') <> '') then
      szNonWindowsPlayCommand := 'afplay';
  // proceed if we managed to find a valid command
  if (szNonWindowsPlayCommand <> '') then
  begin
    if fPlayStyle = psASync then
    begin
      if SoundPlayerAsyncProcess = nil then
        SoundPlayerAsyncProcess := Tasyncprocess.Create(nil);
      SoundPlayerAsyncProcess.CurrentDirectory := ExtractFileDir(szSoundFilename);
      SoundPlayerAsyncProcess.Executable :=
        FindDefaultExecutablePath(szNonWindowsPlayCommand);
      SoundPlayerAsyncProcess.Parameters.Clear;
      SoundPlayerAsyncProcess.Parameters.Add(szSoundFilename);
      try
        SoundPlayerAsyncProcess.Execute;
      except
        On E: Exception do
          E.CreateFmt('Playstyle=paASync: ' + C_UnableToPlay +
            '%s Message:%s', [szSoundFilename, E.Message]);
      end;
    end
    else
    begin
      if SoundPlayerSyncProcess = nil then
        SoundPlayerSyncProcess := Tprocess.Create(nil);
      SoundPlayerSyncProcess.CurrentDirectory := ExtractFileDir(szSoundFilename);
      SoundPlayerSyncProcess.Executable :=
        FindDefaultExecutablePath(szNonWindowsPlayCommand);
      SoundPlayersyncProcess.Parameters.Clear;
      SoundPlayerSyncProcess.Parameters.Add(szSoundFilename);
      try
        SoundPlayerSyncProcess.Execute;
        SoundPlayersyncProcess.WaitOnExit;
      except
        On E: Exception do
          E.CreateFmt('Playstyle=paSync: ' + C_UnableToPlay +
            '%s Message:%s', [szSoundFilename, E.Message]);
      end;
    end;
  end
  else
    raise Exception.CreateFmt('The play command %s does not work on your system',
      [szNonWindowsPlayCommand]);
{$ENDIF}
end;
  • Destroy the process objects in your Destroy procedure:
FreeAndNil(SoundPlayerSyncProcess);
FreeAndNil(SoundPlayerAsyncProcess);



minesadorada