Bryan Black
Bryan Black

Reputation: 371

Stop Winsound / Stop a thread on Python

Im writing a litle game on python using Tkinter (And by the way, i am not allowed to use any other non built in modules) and I want to play a background song when on the main window, wich is the one that holds the title, and the buttons to go to other windows and stuff...

So the thing is that I need that sound to stop when I enter to another window, but when I hit the button to go, to another window, the song keeps playing...

I'm using the winsound module, and had define a couple of functions, (That by the way, are wicked as hell) to play the song when I first run the program using threads...

So here is the deal, I want something to put in the function "killsound" so that I can add it to every button, and then when I press any button to open any other window, the sound will be killed.

I was hoping something like 'a.kill()' or 'a.stop()' but it didnt worked.

And I really don´t know how to use the SND_PURGE thing on winsound... Although I understand that SND_PURGE is no longer working on new windows OS (Got Win8.1)

Could you please help me?

Thank You! (And Sorry for the creepy english...)

def Play(nombre): #This function Is the core of the winsound function
   ruta = os.path.join('Audio',nombre)
   Reproducir= winsound.PlaySound(ruta,winsound.SND_FILENAME)
   return Reproducir

def PlayThis(): 
   while flag_play:
       try:
           return Play('prettiest weed.wav')
       except:
           return "Error"

def PlayThisThread():
   global flag_play
   flag_play= True
   a=Thread(target=PlayThis, args=())
   a.daemon = True
   a.start()

   PlayThisThread()


def killsound():  #This is the function I want, for killing sound.
   global flag_play
   flag_play = False

Upvotes: 2

Views: 3688

Answers (3)

Andrew Mohan
Andrew Mohan

Reputation: 1

I also created a 0.5 sec wavfile in Adobe Audition containing silence and attached it to the stop button, and this basically "stopped" playback of the previously played audio clip.

Upvotes: 0

Bryan Black
Bryan Black

Reputation: 371

I found a way to do it, by adding a 0.5sec sound to a button, so that when I press the button it stops the background one to play the button one, and then stops all sounds on program.

Upvotes: -1

Martin Stancik
Martin Stancik

Reputation: 339

There are 2 major problems in your code:

  1. global variable flag_play has to be placed inside the sound playback loop, in your case within the PlayThis() function
  2. the Winsound module is aiming simple non-threaded usage. while the sound is playbacked, there is no chance to "softly" interrupt. It does not support any playback status reporting e.g. .isPlaying() nor any kind of .stop() that you need in order to kill it.

Solution:

  • try PyMedia package. Pymedia allows lower-level audio manipulation therefore more details have to be provided at the initialisation:

    import time, wave, pymedia.audio.sound as sound
    
    # little to do on the proper audio setup
    
    f= wave.open( 'prettiest weed.wav', 'rb' )
    sampleRate= f.getframerate() # reads framerate from the file
    channels= f.getnchannels()
    format= sound.AFMT_S16_LE  # this sets the audio format to most common WAV with 16-bit codec PCM Linear Little Endian, use either pymedia or any external utils such as FFMPEG to check / corvert audio into a proper format.
    audioBuffer = 300000  # you are able to control how much audio data is read
    

with the following assigment the "snd" becomes an instance of the class sound.Output and gives you bunch of useful audio methods:

    snd= sound.Output( sampleRate, channels, format )
    s= f.readframes( audioBuffer )
    snd.play( s )

and finally your threaded playback loop might look as follows:

    while snd.isPlaying():
      global flag_play
      if not flag_play: snd.stop()  #here is where the playback gets interupted.
      time.sleep( 0.05 )

    f.close()

Please, let me know if you need more support on this.

Upvotes: 3

Related Questions