Stop Winsound / Stop a thread on Python - 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

There are 2 major problems in your code:
global variable flag_play has to be placed inside the sound playback loop, in your case within the PlayThis() function
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.

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.

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.

Related

Qmediaplayer setposition QtPython

I am trying to set up a simple media player with Qt.
I want to choose the start position of the video on startup of the player. I bound this to an isSeekable event to make sure media is loaded and seekable.
Still the player does not work as expected. Either I am gettings errors (0xC00D6D60) or the video just starts from the beginning.
This is my code:
def seekable_changed(self, is_seekable):
if (is_seekable):
self._player.pause()
self._player.setPosition(videostartmsdiff) # milliseconds
self._player.play()
I tried different combinations with or without pause() and play()
How do I set start position in Qt to let it work as expected?
Thanks
You should connect to QMediaPlayer::stateChanged(QMediaPlayer::State state) signal and call setPosition when state becomes QMediaPlayer::PlayingState.

Music player for Python not working

I want to be able to play multiple songs through a playlist using python, but it will only play the last song on the list. Please help.
from pygame import mixer # Load the required library
from os import listdir
k = listdir('C:/LOCAL')
print(k)
mixer.init()
for x in k:
y = "C:/LOCAL/" + x
print y
mixer.music.queue(y)
mixer.music.load(y)
mixer.music.play()
Your problem is that you assume that playing music with pygame will pause the program until the music is finished - which is not the case. As a result, it tries starting a song, and then it's starting another, and another, etc.
There are a few ways of trying to correct this. You could either:
Use pygame events and "tell" pygame to fire an event when the song finishes (though this requires a display surface (window) to be opened within pygame), or
Detect the length of the song, and sleep for that amount of time (which is more compatible with your current code).
I'm going to assume that you would like to do option 2, since your code works better with it.
To get the length of an MP3 file (I've not tried it with any other types), you could use the Mutagen library.
Some example code to get the length of an MP3 file (in seconds):
from mutagen.mp3 import MP3
tracklength = MP3("/path/to/song.mp3").info.length
Then you could substitute the path with y, and time.sleep for the amount of time returned, before continuing to the next iteration of the loop.
Hope that helps.
(also, you don't need to queue a file before loading it - just load and play)

Python gtts vlc plays too quickly to hear the first couple words

In python, using the module gTTS and VLC-python, I've created a Text to speech program, which is quite simple to do.
But the thing which is bugging me is when I get to playing the mp3 file created by gTTS it skips the first word or two.
So if I have the string "The weather today will be cloudy". It'll speak out "today will be cloudy"
Even if I adjust the string, it seems to miss out the first word or two, sometimes it starts mid word.
When I play the audio file outside of the code, it plays normally, sometimes it stutters on the first word but if I rewind and have it wait a second, it plays perfectly.
Is there a way to load the audio clip or buffer it before playing so it starts smoothly?
In your code you are going to have something along the lines of:
self.Media = self.Instance.media_new_path('my.mp3')
self.player.set_media(self.Media)
self.player.set_xwindow(self.panel1.GetHandle())
which defines what is going to be played.
Then you will have something like:
if self.player.play() == -1:
print("Error playing file")
else:
pass
where you tell vlc to start playing the file.
put a time.sleep(3) before that play command or actuate the play function from a separate button or something.
This is the equivalent of the:
vlc --no-playlist-autostart vp.mp3
or
vlc --start-paused vp.mp3 command line options.
i.e. load the file but don't start playing it, until I tell you.
I found another library called playsound which plays the audio files back without any clipping:
from gtts import gTTS
from playsound import playsound
text = "Say something."
speech = gTTS(text = text, lang = 'en', slow = False)
mp3_file = 'text.mp3'
speech.save(mp3_file)
playsound(mp3_file)
I think this is a better solution than VLC, even if there was no clipping of audio in VLC, because using the vlc library requires you to have VLC Media Player installed on your computer, whereas this playsound library doesn't require you to install anything else for it to work.

What is preventing the sound files from being played in this pygame Mixer set up?

I'm trying to write a small bit of code to play music files in the background of a game. The problem I'm coming across is that despite all the code being laid out and phrased properly no sound files will play. I put several print statements in the code and it seems to suggest that the sound file is either not loading or is simply not playing once it loads?
import pygame
def musicPlayer():
print "Playing music now"
pygame.init()
pygame.mixer.music.load('01ANightOfDizzySpells.mp3')
print "load song1"
pygame.mixer.music.play(loops=0, start=0.0)
print "play song1"
pygame.mixer.music.queue('01HHavok-intro.mp3')
pygame.mixer.music.queue('02HHavok-main.mp3')
pygame.mixer.music.queue('02Underclockedunderunderclockedmix.mp3')
pygame.mixer.music.queue('03ChibiNinja.mp3')
pygame.mixer.music.queue('04AllofUs.mp3')
pygame.mixer.music.queue('05ComeandFindMe.mp3')
pygame.mixer.music.queue('06Searching.mp3')
pygame.mixer.music.queue('07WeretheResistors.mp3')
pygame.mixer.music.queue('08Ascending.mp3')
pygame.mixer.music.queue('09ComeandFindMe-Bmix.mp3')
pygame.mixer.music.queue('10Arpanauts.mp3')
pygame.mixer.music.queue('DigitalNative.mp3')
pygame.mixer.music.set_endevent()
#musicPlayer()
musicPlayer()
Am I missing something basic? Or could it have to do with my computer not the code?
Edit: this is the output from running the code
Playing music now
load song1
play song1
As you can see it throws no errors.
I tried your code with a mid file, it works fine, but there's some adjustments:
import pygame
def musicPlayer():
pygame.init()
pygame.mixer.music.load('test.mid')
print "load song1"
pygame.mixer.music.play()
print "play song1"
pygame.mixer.music.queue('test_2.mid')
musicPlayer()
while pygame.mixer.music.get_busy():
pygame.time.Clock().tick(10)
print "DONE"
if the script ends the play won't happend, for that you need to get_busy() in a while loop.
in the documentation of pygame.music it states: Be aware that MP3 support is limited [...] Consider using OGG instead.
I played a little with the Sound class.
Here's what I came up:
import pygame
def musicPlayer():
pygame.mixer.init()
channel = pygame.mixer.Channel(1)
sound = pygame.mixer.Sound('test.ogg')
channel.play(sound)
musicPlayer()
while pygame.mixer.get_busy():
pygame.time.Clock().tick(10)
print "DONE"
I'm not very familiar with pygame and its methods, but my guess is that either it cannot find the file correctly, or it's not able to correctly handle the file that it finds.
I would suggest putting the full path to audio files to see if that helps. That would rule out the issue of it not finding the files properly (although hardcoding this is obviously not a good idea long-term as any changes you make to the organizational structure of your program will likely break those paths).
And according to their documentation, their MP3 support is limited. You might try using .ogg files instead (http://www.pygame.org/docs/ref/music.html) as it could just be an issue with the encoding not being fully supported.

tkSnack: how to play a second sound when first one is ended

I would love my script to play a second sound when the first one is ended. From tkSnack documentation:
play ( )
Plays the sound. All options are ignored if play() is used to resume a paused play options.
If a play() command is issued while another one is in progress,
the latter one is queued up and starts to play as soon as possible.
So, I thought that calling the play method on the sound object while a song was being played would result in the second song to be started when this one's finished.
Unfortunately, this doesn't seem to happen. In fact, as I call the read method on the sound object, in order to load the audio file, the player stops to play.
How should I load the audio?
I've also tried to use two different sound object, but this results in an overlapping playing.
So far, the only solution I've found is to use the blocking option for the play method. And add it in a loop:
for song in songList:
SoundObject.read(song)
SoundObject.play(blocking=True)
This is however far from a good solution, since it blocks the whole application, even if I start it in a daemon thread.
Here is a sample code:
import Tkinter, tkSnack, time
win = Tkinter.Tk()
tkSnack.initializeSnack(win)
snd = tkSnack.Sound()
def play1():
snd.read('/home/francesco/Musica/Andrea Bocelli - Ave Maria.mp3')
snd.play()
def play2():
snd.read('/home/francesco/Musica/Andrea Bocelli - La voce del silenzio.mp3')
snd.play()
b1 = Tkinter.Button(win, text="play1", command = play1)
b2 = Tkinter.Button(win, text="play2", command = play2)
b1.pack()
b2.pack()
win.mainloop()
I would love that clicking play2 it will "append" the soundtrack to the current one and start it as soon as the first one is ended.

Categories

Resources