Recent

Author Topic: PlaySoundPackage in lazarus-ccr  (Read 6012 times)

wp

  • Hero Member
  • *****
  • Posts: 11853
PlaySoundPackage in lazarus-ccr
« on: July 20, 2016, 02:50:33 pm »
Yesterday I came across the nice playsoundpackage in lazarus-ccr and adapted it for my updated port of TurboPower VisualPlanIt.

I saw, however, that there are cases where it does not work correctly in non-windows systems: The PlaySound routine looks for an executable in GetNonWindowsExecutable and finds "aplay -q" on my Mint system. This string is passed to  "FindDefaultExecutablePath" which, however, returns an empty string in this case because a commandline parameter is included (-q) - a file "aplay -q" simply does not exist while a file "aplay" does. So what is missing is a separation of the string into an executable and optional parameters which can be done by means of a stringlist:

Code: Pascal  [Select][+][-]
  1. var
  2.   L: TStrings;
  3.  
  4. ...
  5.   if (fPlayCommand <> '') then
  6.   begin
  7.     // Since the playcommand found above can contain parameters we must
  8.     // separate executable and parameters.
  9.     L := TStringList.Create;            // wp: added from here...
  10.     try
  11.       L.Delimiter := ' ';
  12.       L.DelimitedText := fPlayCommand;  // ... to here
  13.       if fPlayStyle = psAsync then
  14.       begin
  15.         if SoundPlayerAsyncProcess = nil then
  16.           SoundPlayerAsyncProcess := TAsyncProcess.Create(nil);
  17.         SoundPlayerAsyncProcess.CurrentDirectory := ExtractFileDir(szSoundFilename);
  18.         SoundPlayerAsyncProcess.Executable := FindDefaultExecutablePath(L[0]);    // wp: use L[0] here
  19.         SoundPlayerAsyncProcess.Parameters.Clear;
  20.         for i:=1 to L.Count-1 do                              // wp: added
  21.           SoundPlayerAsyncProcess.Parameters.Add(L[i]);       // wp: added
  22.         SoundPlayerAsyncProcess.Parameters.Add(szSoundFilename);
  23.         try
  24.           SoundPlayerAsyncProcess.Execute;
  25.         except
  26.           on E: Exception do
  27.             E.CreateFmt('PlayStyle=psAsync: ' + C_UnableToPlay +
  28.               '%s Message:%s', [szSoundFilename, E.Message]);
  29.         end;
  30.       end
  31.       else
  32.       begin
  33.         if SoundPlayerSyncProcess = nil then
  34.           SoundPlayerSyncProcess := TProcess.Create(nil);
  35.         SoundPlayerSyncProcess.CurrentDirectory := ExtractFileDir(szSoundFilename);
  36.         SoundPlayerSyncProcess.Executable := FindDefaultExecutablePath(L[0]);  // wp: use L[0] here
  37.         SoundPlayersyncProcess.Parameters.Clear;
  38.         for i:=1 to L.Count-1 do                          // wp: added
  39.           SoundPlayerSyncProcess.Parameters.Add(L[i]);    // wp: added
  40.         SoundPlayerSyncProcess.Parameters.Add(szSoundFilename);
  41.         try
  42.           SoundPlayerSyncProcess.Execute;
  43.           SoundPlayersyncProcess.WaitOnExit;
  44.         except
  45.           On E: Exception do
  46.             E.CreateFmt('PlayStyle = psSync: ' + C_UnableToPlay +
  47.               '%s Message:%s', [szSoundFilename, E.Message]);
  48.         end;
  49.       end;
  50.  
  51.     finally
  52.       L.Free;  // wp: added
  53.     end;                                                    
With these additions sound plays fine on Linux Mint. Without it, there is an exception of TProcess saying "Cannot execute an empty command line" - I wonder if that package ever worked correctly.

Another issue is that unit LazFileUtils is found missing on Laz trunk.

Another bug is in StopSound which requires an integer parameter in the call to process.Terminate:
Code: Pascal  [Select][+][-]
  1.   if SoundPlayerSyncProcess <> nil then SoundPlayerSyncProcess.Terminate(1);     // any number would be ok
  2.   if SoundPlayerAsyncProcess <> nil then SoundPlayerAsyncProcess.Terminate(1);

The demo program has two small issues which may cause new users to turn away: It contains a hard-coded sound file on the author's harddisk. And the property "Playcommand" is not empty and thus overrides the automatic detection of the player software in Linux - an empty string would work fine.

I could fix these issue myself, but since this package is relatively new I am hesitant because its author could still be around here - and maybe there's something behind this code which I do not know.

In the attachment, there's a patch with all modifications (except for the demo).

[EDIT]
BTW: If the author reads this: Why do you make this a component and not a simple procedure? A procedure would be a 1-liner
Code: Pascal  [Select][+][-]
  1.   PlaySound(filename, psSync);
while a component always requires 2-3 lines
Code: Pascal  [Select][+][-]
  1.   PlaySound1.SoundFile := filename;
  2.   PlaySound1.PlayStyle := psSync;  // could be dropped in case of psAsync
  3.   PlaySound1.Execute;
« Last Edit: July 20, 2016, 04:47:42 pm by wp »

minesadorada

  • Sr. Member
  • ****
  • Posts: 452
  • Retired
Re: PlaySoundPackage in lazarus-ccr
« Reply #1 on: July 20, 2016, 07:47:45 pm »
Hi @wp

I wrote PlaySound because I had an old windows game which used WAV files, and wanted to do a Linux port. I figured other programmers might want to do the same.  The existing multi-platform sound libraries seemed overcomplicated (to me!) for such a simple task.   So it has a simple and specific purpose, and to make it even simpler to use - I made it a drop-in component.

I really appreciate your analysis and fixes and welcome them.  Are you able to update the package in lazarus-ccr?
GPL Apps: Health MonitorRetro Ski Run
OnlinePackageManager Components: LazAutoUpdate, LongTimer, PoweredBy, ScrollText, PlaySound, CryptINI

wp

  • Hero Member
  • *****
  • Posts: 11853
Re: PlaySoundPackage in lazarus-ccr
« Reply #2 on: July 20, 2016, 08:43:27 pm »
Are you able to update the package in lazarus-ccr?
Yes, I can do this. Is it ok for you if I expose "PlaySound" and "StopSound" as separate (i.e. non-component) procedures as well? This would reduce the requirement to install the component into the component palette. And I also would like to move the component from the new tab "LazControls" to "Misc"

I like this component because it is very easy.

[EDIT]
Applied my changes to svn. The demo is now playing fine in Windows and Linux (only Mint tested). If the property PlayCommand is an empty string the play command is determined automatically. In addition, however, automatic detection can be overridden by specifying a dedicated play command in the OI.
« Last Edit: July 20, 2016, 10:25:01 pm by wp »

minesadorada

  • Sr. Member
  • ****
  • Posts: 452
  • Retired
Re: PlaySoundPackage in lazarus-ccr
« Reply #3 on: July 21, 2016, 09:13:49 am »
Applied my changes to svn. The demo is now playing fine in Windows and Linux (only Mint tested). If the property PlayCommand is an empty string the play command is determined automatically. In addition, however, automatic detection can be overridden by specifying a dedicated play command in the OI.

Thanks @wp
I think one of Lazarus' many strengths is simple RAD, where drop-in components 'solve the immediate issue' and allow the novice developer to write creative code elsewhere.  Playsound was written for that purpose and I'm grateful for your improvements.
GPL Apps: Health MonitorRetro Ski Run
OnlinePackageManager Components: LazAutoUpdate, LongTimer, PoweredBy, ScrollText, PlaySound, CryptINI

RWC

  • Jr. Member
  • **
  • Posts: 92
Re: PlaySoundPackage in lazarus-ccr
« Reply #4 on: July 21, 2016, 04:21:42 pm »
Quote
I think one of Lazarus' many strengths is simple RAD, where drop-in components 'solve the immediate issue' and allow the novice developer to write creative code elsewhere.  Playsound was written for that purpose
@minesadorada: Playsound looks very interesting – does ‘drop-in component’ mean drag it from the component tab & drop it on the Form?  I’ve searched for ‘how to use a drop-in component in Lazarus’ and found hundreds of drop-in components but nothing about it’s meaning or how to install or use them. Best regards, RWC (a novice that doesn’t even know what ‘simple RAD’ means). %)

P.S. My ultimate aim is to have a dynamic array holding the 16bit values of a sound file (like PCM WAV, i.e. 0…65536 or 32768…0...32767 per sample) to use for generating a landscape while playing the sound at the same time. Ideally starting with a mp3 or other compressed audio file since WAV’s are bit big!
LAZARUS  : Lazarus-1.4.2-fpc-2.6.4-win32. OS   : Windows Vista 32bit Home Premium SP2.
CPU  : Intel Core2 Quad CPU Q6600 2.4GHz. RAM : 3GB. PCIE : NVIDIA GeForce GT610. Audo : NVIDIA HD Audio.

Graeme

  • Hero Member
  • *****
  • Posts: 1428
    • Graeme on the web
Re: PlaySoundPackage in lazarus-ccr
« Reply #5 on: July 22, 2016, 12:16:43 pm »
May I suggest you rather take a look at UOS - it works universally across multiple platforms and has excellent support and latency. It is also easy to use and comes with a couple of examples.

  https://fredvs.github.io/uos/
--
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/

minesadorada

  • Sr. Member
  • ****
  • Posts: 452
  • Retired
Re: PlaySoundPackage in lazarus-ccr
« Reply #6 on: July 22, 2016, 02:25:38 pm »
@minesadorada: Playsound looks very interesting – does ‘drop-in component’ mean drag it from the component tab & drop it on the Form?  I’ve searched for ‘how to use a drop-in component in Lazarus’ and found hundreds of drop-in components but nothing about it’s meaning or how to install or use them. Best regards, RWC (a novice that doesn’t even know what ‘simple RAD’ means). %)
RAD = Rapid Application Development - the idea that you can make a useful app using pre-built visual components with minimal code to tie them together.

By 'drop-in component' I meant a component icon on the Lazarus toolbar (like a TButton or TLabel) which you doubleclick on to place on a form, and then use the Object Inspector to tweak its properties.  With the PlaySound component, you set properties in the O.I. then call the Execute method in code to play the sound - quick and easy.


P.S. My ultimate aim is to have a dynamic array holding the 16bit values of a sound file (like PCM WAV, i.e. 0…65536 or 32768…0...32767 per sample) to use for generating a landscape while playing the sound at the same time. Ideally starting with a mp3 or other compressed audio file since WAV’s are bit big!
I suspect Graeme's excellent suggestion to learn and use the UOS library would be more appropriate for your project.
GPL Apps: Health MonitorRetro Ski Run
OnlinePackageManager Components: LazAutoUpdate, LongTimer, PoweredBy, ScrollText, PlaySound, CryptINI

RWC

  • Jr. Member
  • **
  • Posts: 92
Re: PlaySoundPackage in lazarus-ccr
« Reply #7 on: July 22, 2016, 04:20:23 pm »
@minesadorada: thank you - your Playsound demo works well on this WinVista 32bit system and thanks too for the clarification & advice.

@Graeme: Thanks to you too Graeme - fredvs /UOS looks amazing – can’t wait to try it. :)
LAZARUS  : Lazarus-1.4.2-fpc-2.6.4-win32. OS   : Windows Vista 32bit Home Premium SP2.
CPU  : Intel Core2 Quad CPU Q6600 2.4GHz. RAM : 3GB. PCIE : NVIDIA GeForce GT610. Audo : NVIDIA HD Audio.

 

TinyPortal © 2005-2018