4

For my first project, I'm working on building a soundboard using a Raspberry Pi as the base. I would like to have several buttons, each of which plays a random sound file from different lists on each press.

I'm using several built in libraries, specifically pygame, glob, random, and Button to make things easier. Glob is being used to generate a list of possible files to play, and random is being used to pick one of them.

pygame.init()

h = glob.glob('/file path/*.wav')

btn_0 = Button(2)

btn_0.when_pressed = pygame.mixer.Sound(random.choice(h)).play

From my admittedly basic understanding, this should call up a list of all files ending in .wav from the specific file path, and on the button press, randomly pick one to play through pygame.

What it is doing, though, is randomly picking a file from the list, and then playing that on a press. When I restart and run the code again, a different file is picked, so I know the list is being seen correctly.

Am I just missing something very obvious? Should I be using a different method? I'm just lost here.

1 Answers1

2

This line

btn_0.when_pressed = pygame.mixer.Sound(random.choice(h)).play

assigns one file to .when_pressed; this will NOT change throughout the whole execution of the program.

Have you tried to assign a function or lambda to .when_pressed instead, so that this function gets executed on every button press? Maybe like this:

h = glob.glob('/file path/*.wav')
btn_0.when_pressed = lambda: pygame.mixer.Sound(random.choice(h)).play()

Does that work? I cannot test it right now on my machine.


Of course, you could also instantiate glob.glob('/file path/*.wav') from scratch on each button press; that would allow you to add/remove files without closing the Python program because it will do a new filesystem search on each button press.

btn_0.when_pressed = lambda: pygame.mixer.Sound(
    random.choice(glob.glob('/file path/*.wav'))).play()
Ralf
  • 16,086
  • 4
  • 44
  • 68
  • If you have the lambda function, you should actually invoke the `play` method of the `Sound` instance. So it would be `lambda: pygame.mixer.Sound(random.choice(h)).play()`. – Chathan Driehuys Oct 16 '19 at 19:04
  • @ChathanDriehuys that makes sense; I changed it. – Ralf Oct 16 '19 at 19:05
  • then I agree with this answer :) – Chathan Driehuys Oct 16 '19 at 19:06
  • That function will also use the value of `h` when the button is pressed, not the value of `h` when the function is created. That may or may not be the intention of the OP. – chepner Oct 16 '19 at 19:08
  • @chepner added an observation about that to my answer – Ralf Oct 16 '19 at 19:12
  • @AnthonyHalloway can you be a bit more specific? Which code from my answer are you testing? Any errors that are being raised or logged? – Ralf Oct 16 '19 at 19:16