0

so yeah, i am just making a program which plays music of my favourite game. Now what the thing is that when i call the playsound function of playsound(module) then, my programs lags and then eventually crashes. Here is my code:

import tkinter as tk
from playsound import playsound
import multiprocessing
class dynastyMusicer(tk.Tk):
    def __init__(self, screenName=None, baseName=None, className='Tk',
                 useTk=True, sync=False, use=None):
        super().__init__(screenName=screenName, baseName=baseName, className=className, useTk=useTk, sync=sync, use=use) 
        self.title("Dynasty Musicer")
        self.geometry("250x100")
        self.config(background="white")
        chooseL = tk.Label(self, text="Which music to play?", background="white")
        chooseL.place(x=50, y=0)
        ops = ["Dynasty Dojo", "Dynasty Dojo Fight"]
        self.stvar = tk.StringVar(self)
        self.stvar.set("Music")
        self.option = tk.OptionMenu(self, self.stvar, *ops)
        self.option.place(y=30)
        btn = tk.Button(self, text="Play", width=10, command=self.play)
        btn.place(y=70)
        stop = tk.Button(self, text="Stop", width=10, command=self.stop)
        stop.place(x=160,y=70)
    def stop(self):
        multiprocessing.Process(target=playsound, args=(self.stvar.get()+".mp3"))
    def play(self):
        if self.stvar.get() == "Dynasty Dojo":
                playsound(r"path")
        elif self.stvar.get() == "Dynasty Dojo Fight":
            playsound(r"path")
                
dm = dynastyMusicer()
dm.mainloop()

also because of this i can't test whether my stop function is working or not because when you'll click the play button then yeah, you guessed it, it would crash. if you wanna download the two music file i used, here are the links:

Dynasty Dojo

Dynasty dojo fight

random_hooman
  • 1,660
  • 7
  • 23

1 Answers1

1

There are many things to look at with your code. To being with:

  • tkinter is single threaded, running it from a separate thread will cause issue, though you can use multiprocessing if you can ensure the tk objects wont go into the other processes/thread.

  • However such pain is not unnecessary in this case, here you will not need to use any of this as playsound can be run without blocking the thread, like: playsound(..., block=False)

  • Also here I noticed a stop button, you cannot stop a started sound with playsound so now you have to start looking for some other threaded sound library and pygame is the best I can find. Though it has some support issues with files, it should be alright for most cases.

Here is the better code using pygame and modifying your current settings:

import tkinter as tk
import pygame # pip install pygame

class DynastyMusicer(tk.Tk): # Using Pascal Case notation for class names
    def __init__(self, *args, **kwargs): # Shorten all the optional arguments
        super().__init__(*args, **kwargs) # or tk.Tk.__init__(....)
        self.title("Dynasty Musicer")
        self.geometry("250x100")
        self.config(background="white")
        
        pygame.init() # Initialize pygame

        chooseL = tk.Label(self, text="Which music to play?", background="white")
        chooseL.place(x=50, y=0)
        
        self.ops = ["Dynasty Dojo", "Dynasty Dojo Fight"]
        self.stvar = tk.StringVar(self)
        self.stvar.set("Music")
        
        self.option = tk.OptionMenu(self, self.stvar, *self.ops)
        self.option.place(y=30)
        
        btn = tk.Button(self, text="Play", width=10, command=self.play)
        btn.place(y=70)
        
        stop = tk.Button(self, text="Stop", width=10, command=self.stop)
        stop.place(x=160,y=70)
    
    def stop(self):
        pygame.mixer.music.stop() # Stop the music being played

    def play(self):
        if self.stvar.get() != 'Music': # If not the default value, then
            pygame.mixer.music.load(rf"{self.stvar.get()}.mp3") # Load the song
            pygame.mixer.music.play() # Play the song
                
dm = DynastyMusicer()
dm.mainloop()

Here, your if statement is modified to be shorted because you follow whitelisting which disables any invalid input from going in(except 'Music').

Delrius Euphoria
  • 14,910
  • 3
  • 15
  • 46
  • 1
    Well, i didn't add the `__init__` function arguments myself it was just one of vscode's stupid snippet. i am lazy so i thought who would clear it for me and you did andddddd anyways thanks – random_hooman Jul 15 '21 at 04:42