0

I am trying to create a program that plays sound and shows the wave. However, when I try to call the multiprocessing.Process method so that I can cancel the playback if the user clicks the play button before the sound has finished. However, instead of calling my actualPlaySound method, it seems to recall my code and another tkinter window opens. Please help!

from tkinter import *
import math, time, threading, winsound, os, multiprocessing
def update ():
    global modded
    if not modded:
        modded = True
        stringAmplitude.set (str (amplitude.get ()))
        stringFrequency.set (str (frequency.get ()))
        modded = False
    c.delete (ALL)
    width, height = c.winfo_width (), c.winfo_height () / 2
    freq = frequency.get ()
    c.create_line (0, 25, width, 25)
    c.create_polygon (15, 10, 0, 25, 15, 40)
    c.create_polygon (width - 15, 10, width, 25, width - 15, 40)
    if freq <= 100: c.create_text (width / 2, 15, text = "1 second")
    elif freq <= 1000:
        c.create_text (width / 2, 15, text = "10 milliseconds")
        freq = freq / 100
    else:
        c.create_text (width / 2, 15, text = "1 millisecond")
        freq = freq / 1000
    ampl, freq = amplitude.get () ** 0.5, freq * math.pi * 2
    for x in range (width):
        c.create_line (x, math.sin (x * freq / width) * ampl * (height - 30 if height > 30 else 0) / 10 + (height if height > 35 else 35), x + 1, math.sin ((x + 1) * freq / width) * ampl * (height - 30 if height > 30 else 0) / 10 + (height if height > 35 else 35))
def stringUpdate ():
    global modded
    if not modded:
        modded = True
        try: amplitude.set (float (stringAmplitude.get ()))
        except: pass
        try: frequency.set (float (stringFrequency.get ()))
        except: pass
        modded = False
def playSound ():
    global p
    if not p or not p.is_alive ():
        p = multiprocessing.Process (target = actualPlaySound)
        p.start ()
    else: p.terminate ()
def actualPlaySound ():
    freq = int (frequency.get ())
    if freq < 37:
        l.config (text = "Too low!")
    elif freq > 32767:
        l.config (text = "Too high!")
    else:
        l.config (text = "Playing...")
        winsound.Beep (freq, 5000)
        l.config (text = "Played!")
modded, p = False, None
root = Tk ()
root.title ("Waves")
amplitude, frequency, stringAmplitude, stringFrequency = DoubleVar (), DoubleVar (), StringVar (), StringVar ()
amplitude.set (50)
frequency.set (1000)
stringAmplitude.set ("50")
stringFrequency.set ("1000")
amplitude.trace ("w", lambda a, b, c: update ())
frequency.trace ("w", lambda a, b, c: update ())
stringAmplitude.trace ("w", lambda a, b, c: stringUpdate ())
stringFrequency.trace ("w", lambda a, b, c: stringUpdate ())
root.bind ("<Configure>", lambda event: update ())
Label (root, text = "Frequency").grid (row = 0, column = 0)
Scale (root, from_ = 50, to = 32000, orient = "horizontal", variable = frequency).grid (row = 1, column = 0)
Entry (root, textvariable = stringFrequency).grid (row = 2, column = 0)
Frame (root, height = 50).grid (row = 3, column = 0)
Label (root, text = "Amplitude (this doesn't\nchange playback volume)").grid (row = 4, column = 0)
Scale (root, orient = "horizontal", variable = amplitude).grid (row = 5, column = 0)
Entry (root, textvariable = stringAmplitude).grid (row = 6, column = 0)
l = Label (root, text = "Ready to go!")
l.grid (row = 7, column = 0)
Button (root, text = "Play", command = lambda: threading.Thread (target = playSound).start ()).grid (row = 8, column = 0)
c = Canvas (root, bg = "white", width = 500, height = 400)
c.grid (row = 0, column = 1, rowspan = 20, sticky = "nsew")
Grid.columnconfigure (root, 1, weight = 1)
for y in range (20): Grid.rowconfigure (root, y, weight = 1)
update ()
root.mainloop ()
os._exit (0)
Minion Jim
  • 1,239
  • 13
  • 30
  • The `multiprocessing` module on Windows absolutely requires that there be NO top-level code in your script outside of an `if __name__ == "__main__":` block. – jasonharper Feb 21 '18 at 20:33
  • I added this as recommended but it still didn't run my `actualPlaySound` method – Minion Jim Feb 21 '18 at 20:36

0 Answers0