Recent

Author Topic: [SOLVED] Load filename into Stringlist by extension  (Read 400 times)

d3crypti0n

  • New Member
  • *
  • Posts: 11
[SOLVED] Load filename into Stringlist by extension
« on: April 22, 2021, 03:16:43 pm »
In a previous thread I asked how to set one random sound-file to play in a constant loop as background music. I got advised to use a Stringlist. Since I want to add or delete songs after I compiled my project, I thought I might automate the adding of filenames to the list at the start of m program and read them by looking for the extension and load them into my list.

I'm a little stuck at the moment on how to properly load the filenames into the StringList and randomly choose one to play in the loop. My code so far:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.MusicPlayer();
  2. var
  3.    MusicList: TStringList;
  4.    music: String;
  5. begin
  6.    MusicList := FindAllFiles('..\Music\', '*.wav', true);
  7.    Random(MusicList) := music;
  8.    MusicList.Free;
  9.    PlaySound(music,0,SND_ASYNC or SND_LOOP);
  10. end;  

P.S.: I added FileUtil and MMSystem in my uses.
« Last Edit: April 22, 2021, 04:27:46 pm by d3crypti0n »

MarkMLl

  • Hero Member
  • *****
  • Posts: 2557
Re: Load filename into Stringlist by extension
« Reply #1 on: April 22, 2021, 03:30:51 pm »
What is in FindAllFiles()?

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

d3crypti0n

  • New Member
  • *
  • Posts: 11
Re: Load filename into Stringlist by extension
« Reply #2 on: April 22, 2021, 03:32:55 pm »
What is in FindAllFiles()?

MarkMLl

If you mean '..\Music\' that's the path where the WAVEs are stored.

wp

  • Hero Member
  • *****
  • Posts: 8410
Re: Load filename into Stringlist by extension
« Reply #3 on: April 22, 2021, 03:33:50 pm »
Untested:
Code: Pascal  [Select][+][-]
  1. var
  2.   MusicList: TStrings;
  3.  
  4. // Read the names of the music files into a stringlist when the program starts.
  5. procedure TForm1.FormCreate(Sender: TObject);
  6. begin
  7.   MusicList := TStringList.Create;
  8.   FindAllFiles(MusicList, '..\Music\', '.wav', true);
  9. end;
  10.  
  11. // Destroy the music list when the programs ends.
  12. procedure TForm1.FormDestroy(Sender: TObject);
  13. begin
  14.   MusicList.Free;
  15. end;
  16.  
  17. // Play a random song from the MusicList when Button1 is clicked
  18. procedure TForm1.Button1Click(Sender: TObject);
  19. var
  20.   song: String;
  21. begin
  22.   song := MusicList[random(MusicList.Count)];
  23.   PlaySound(song, 0, SND_ASYNC or SND_LOOP);
  24. end;
Mainly Lazarus trunk / fpc 3.2.0 / all 32-bit on Win-10, but many more...

MarkMLl

  • Hero Member
  • *****
  • Posts: 2557
Re: Load filename into Stringlist by extension
« Reply #4 on: April 22, 2021, 03:39:34 pm »
What is in FindAllFiles()?

MarkMLl

If you mean '..\Music\' that's the path where the WAVEs are stored.

No, I don't. I mean "you've just thrown a non-standard function at us. What is its implementation?".

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Zvoni

  • Hero Member
  • *****
  • Posts: 550
Re: Load filename into Stringlist by extension
« Reply #5 on: April 22, 2021, 03:42:52 pm »
No, I don't. I mean "you've just thrown a non-standard function at us. What is its implementation?".

MarkMLl
Huh?
Since when are Functions from FileUtil "non-standard"?
https://lazarus-ccr.sourceforge.io/docs/lazutils/fileutil/findallfiles.html
One System to rule them all, One IDE to find them,
One Code to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
People call me crazy, because i'm jumping out of perfectly fine aircraft

Zvoni

  • Hero Member
  • *****
  • Posts: 550
Re: Load filename into Stringlist by extension
« Reply #6 on: April 22, 2021, 03:44:34 pm »
Untested:
Code: Pascal  [Select][+][-]
  1. var
  2.   MusicList: TStrings;
  3.  
  4. // Read the names of the music files into a stringlist when the program starts.
  5. procedure TForm1.FormCreate(Sender: TObject);
  6. begin
  7.   MusicList := TStringList.Create;
  8.   FindAllFiles(MusicList, '..\Music\', '.wav', true);
  9. end;
  10.  
  11. // Destroy the music list when the programs ends.
  12. procedure TForm1.FormDestroy(Sender: TObject);
  13. begin
  14.   MusicList.Free;
  15. end;
  16.  
  17. // Play a random song from the MusicList when Button1 is clicked
  18. procedure TForm1.Button1Click(Sender: TObject);
  19. var
  20.   song: String;
  21. begin
  22.   song := MusicList[random(MusicList.Count)];
  23.   PlaySound(song, 0, SND_ASYNC or SND_LOOP);
  24. end;
Out of curiosity:
is there a specific reason, you use TStrings for MusicList instead of TStringList?
Yes, i know that TStringList inherits from TStrings. I'm just curious if there is a "deeper" reason behind your usage

EDIT: Is it because you use the procedure instead of the function FindAllFiles?
« Last Edit: April 22, 2021, 03:47:39 pm by Zvoni »
One System to rule them all, One IDE to find them,
One Code to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
People call me crazy, because i'm jumping out of perfectly fine aircraft

d3crypti0n

  • New Member
  • *
  • Posts: 11
Re: Load filename into Stringlist by extension
« Reply #7 on: April 22, 2021, 03:47:08 pm »
Untested:
Code: Pascal  [Select][+][-]
  1. var
  2.   MusicList: TStrings;
  3.  
  4. // Read the names of the music files into a stringlist when the program starts.
  5. procedure TForm1.FormCreate(Sender: TObject);
  6. begin
  7.   MusicList := TStringList.Create;
  8.   FindAllFiles(MusicList, '..\Music\', '.wav', true);
  9. end;
  10.  
  11. // Destroy the music list when the programs ends.
  12. procedure TForm1.FormDestroy(Sender: TObject);
  13. begin
  14.   MusicList.Free;
  15. end;
  16.  
  17. // Play a random song from the MusicList when Button1 is clicked
  18. procedure TForm1.Button1Click(Sender: TObject);
  19. var
  20.   song: String;
  21. begin
  22.   song := MusicList[random(MusicList.Count)];
  23.   PlaySound(song, 0, SND_ASYNC or SND_LOOP);
  24. end;

I tried it but got two errors:

unit1.pas(53,17) Error: Incompatible type for arg no. 1: Got "AnsiString", expected "PChar"
mmsystem.pp(2618,10) Hint: Found declaration: PlaySound(PChar;QWord;LongWord):LongBool; StdCall;

Zvoni

  • Hero Member
  • *****
  • Posts: 550
Re: Load filename into Stringlist by extension
« Reply #8 on: April 22, 2021, 03:48:56 pm »
Untested:
Code: Pascal  [Select][+][-]
  1. var
  2.   MusicList: TStrings;
  3.  
  4. // Read the names of the music files into a stringlist when the program starts.
  5. procedure TForm1.FormCreate(Sender: TObject);
  6. begin
  7.   MusicList := TStringList.Create;
  8.   FindAllFiles(MusicList, '..\Music\', '.wav', true);
  9. end;
  10.  
  11. // Destroy the music list when the programs ends.
  12. procedure TForm1.FormDestroy(Sender: TObject);
  13. begin
  14.   MusicList.Free;
  15. end;
  16.  
  17. // Play a random song from the MusicList when Button1 is clicked
  18. procedure TForm1.Button1Click(Sender: TObject);
  19. var
  20.   song: String;
  21. begin
  22.   song := MusicList[random(MusicList.Count)];
  23.   PlaySound(Pchar(song), 0, SND_ASYNC or SND_LOOP); //Cast it to PChar
  24. end;

I tried it but got two errors:

unit1.pas(53,17) Error: Incompatible type for arg no. 1: Got "AnsiString", expected "PChar"
mmsystem.pp(2618,10) Hint: Found declaration: PlaySound(PChar;QWord;LongWord):LongBool; StdCall;

I changed your Line 23
« Last Edit: April 22, 2021, 03:50:43 pm by Zvoni »
One System to rule them all, One IDE to find them,
One Code to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
People call me crazy, because i'm jumping out of perfectly fine aircraft

MarkMLl

  • Hero Member
  • *****
  • Posts: 2557
Re: Load filename into Stringlist by extension
« Reply #9 on: April 22, 2021, 03:50:05 pm »
No, I don't. I mean "you've just thrown a non-standard function at us. What is its implementation?".

MarkMLl
Huh?
Since when are Functions from FileUtil "non-standard"?
https://lazarus-ccr.sourceforge.io/docs/lazutils/fileutil/findallfiles.html

My apologies to everybody. I was looking at the RTL and FCL documentation since this is under programming/general rather than a Lazarus section of the forum.

Consider me duly shutted up :-)

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Zvoni

  • Hero Member
  • *****
  • Posts: 550
Re: Load filename into Stringlist by extension
« Reply #10 on: April 22, 2021, 03:52:11 pm »
Mark, now you made me wonder:
What does FindAllFiles has to do with Lazarus?

Agreed. I would have expected the Function in the FPC-part of the docs, not the Laz-Part
One System to rule them all, One IDE to find them,
One Code to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
People call me crazy, because i'm jumping out of perfectly fine aircraft

d3crypti0n

  • New Member
  • *
  • Posts: 11
Re: Load filename into Stringlist by extension
« Reply #11 on: April 22, 2021, 04:02:51 pm »
Untested:
Code: Pascal  [Select][+][-]
  1. var
  2.   MusicList: TStrings;
  3.  
  4. // Read the names of the music files into a stringlist when the program starts.
  5. procedure TForm1.FormCreate(Sender: TObject);
  6. begin
  7.   MusicList := TStringList.Create;
  8.   FindAllFiles(MusicList, '..\Music\', '.wav', true);
  9. end;
  10.  
  11. // Destroy the music list when the programs ends.
  12. procedure TForm1.FormDestroy(Sender: TObject);
  13. begin
  14.   MusicList.Free;
  15. end;
  16.  
  17. // Play a random song from the MusicList when Button1 is clicked
  18. procedure TForm1.Button1Click(Sender: TObject);
  19. var
  20.   song: String;
  21. begin
  22.   song := MusicList[random(MusicList.Count)];
  23.   PlaySound(Pchar(song), 0, SND_ASYNC or SND_LOOP); //Cast it to PChar
  24. end;

I tried it but got two errors:

unit1.pas(53,17) Error: Incompatible type for arg no. 1: Got "AnsiString", expected "PChar"
mmsystem.pp(2618,10) Hint: Found declaration: PlaySound(PChar;QWord;LongWord):LongBool; StdCall;

I changed your Line 23

Alright the message window doesn't show me errors but the project won't compile due to "List index (0) out of bounds"...

MarkMLl

  • Hero Member
  • *****
  • Posts: 2557
Re: Load filename into Stringlist by extension
« Reply #12 on: April 22, 2021, 04:09:53 pm »
Mark, now you made me wonder:
What does FindAllFiles has to do with Lazarus?

Agreed. I would have expected the Function in the FPC-part of the docs, not the Laz-Part

It's not under the docs at https://www.freepascal.org/docs.html which tends to be my normal reference for stuff that I don't know is GUI-related. It's at https://lazarus-ccr.sourceforge.io/docs/ which has a separate copy of the RTL and FCL docs... which I'd presume pertain to the version of FPC currently with release/stable Lazarus (which might lag release/stable FPC) rather than being a straight duplicate... looking at HTML and sourcetree dates suggest Lazarus docs are still 3.0.2.

I've certainly asked about the distinction between RTC and FCL packages in the past, and was told that it was pretty arbitrary. I'd presume that FileUtils etc. is separate since Lazarus is in theory at least a separate project from FPC with different contributors.

In any event, my Lazarus documentation browser tab was for the LCL, so was one level more specific than was really useful... now fixed :-)

MarkMLl
« Last Edit: April 22, 2021, 06:22:57 pm by MarkMLl »
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

GetMem

  • Hero Member
  • *****
  • Posts: 4017
Re: Load filename into Stringlist by extension
« Reply #13 on: April 22, 2021, 04:15:57 pm »
@d3crypti0n
Quote
Alright the message window doesn't show me errors but the project won't compile due to "List index (0) out of bounds"..
Your list is empty, change the following line:
Code: Pascal  [Select][+][-]
  1. FindAllFiles(MusicList, '..\Music\', '.wav', true);
to
Code: Pascal  [Select][+][-]
  1. FindAllFiles(MusicList, '..\Music\', '*.wav', true);

Also before playing, you should check if the list has items.
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   song: String;
  4. begin
  5.   if MusicList.Count > 0 then
  6.   begin
  7.     song := MusicList[random(MusicList.Count)];
  8.     PlaySound(PChar(song), 0, SND_ASYNC or SND_LOOP);
  9.   end
  10.   else
  11.      ShowMessage('Nothing to play!');
  12. end

Finally you need a randomize on form create, otherwise random won't work:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. begin
  3.   Randomize;
  4.   MusicList := TStringList.Create;
  5.   FindAllFiles(MusicList, '..\Music\', '*.wav', true);
  6. end;
   

d3crypti0n

  • New Member
  • *
  • Posts: 11
Re: Load filename into Stringlist by extension
« Reply #14 on: April 22, 2021, 04:27:29 pm »
@d3crypti0n
Quote
Alright the message window doesn't show me errors but the project won't compile due to "List index (0) out of bounds"..
Your list is empty, change the following line:
Code: Pascal  [Select][+][-]
  1. FindAllFiles(MusicList, '..\Music\', '.wav', true);
to
Code: Pascal  [Select][+][-]
  1. FindAllFiles(MusicList, '..\Music\', '*.wav', true);

Also before playing, you should check if the list has items.
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   song: String;
  4. begin
  5.   if MusicList.Count > 0 then
  6.   begin
  7.     song := MusicList[random(MusicList.Count)];
  8.     PlaySound(PChar(song), 0, SND_ASYNC or SND_LOOP);
  9.   end
  10.   else
  11.      ShowMessage('Nothing to play!');
  12. end

Finally you need a randomize on form create, otherwise random won't work:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. begin
  3.   Randomize;
  4.   MusicList := TStringList.Create;
  5.   FindAllFiles(MusicList, '..\Music\', '*.wav', true);
  6. end;


Thank you! It finally works!  :D

 

TinyPortal © 2005-2018