0

I have a GUI for the purpose of recording audio. There are two buttons, start and stop recording. There is a loop inside the function for start recording which i cannot remove. When the start recording button is pressed, the stop button doesn't respond (because of the loop in start which I cannot remove for a few reasons). I would like to know if there is a way to solve this issue and get both buttons to respond even when the program is in the loop of start recording which is an infinite loop.I'm using python2. The code looks something like the following,

class RecAUD:

    def __init__(self, chunk=4000, frmat=pyaudio.paInt16, channels=1, rate=44100, py=pyaudio.PyAudio()):

        # Start Tkinter and set Title
        self.main = tk.Tk()
        self.collections = []
        self.var = StringVar()
        self.var.set('READY')
        self.main.geometry('1200x500')
        self.main.title('Demo')
        self.CHUNK = chunk
        self.FORMAT = frmat
        self.CHANNELS = channels
        self.RATE = rate
        self.p = py
        self.st = 1
        print("----------------------record device list---------------------")
        info = self.p.get_host_api_info_by_index(0)
        numdevices = info.get('deviceCount')
        for i in range(0, numdevices):
                if (self.p.get_device_info_by_host_api_device_index(0, i).get('maxInputChannels')) > 0:
                    print("Input Device id ", i, " - ", self.p.get_device_info_by_host_api_device_index(0, i).get('name'))

        print("-------------------------------------------------------------")

        self.index = int(input())
        print("recording via index "+str(self.index))

        self.stream = self.p.open(format=self.FORMAT, channels=self.CHANNELS, rate=self.RATE, input=True,input_device_index = self.index, frames_per_buffer=self.CHUNK)
        self.buttons = tkinter.Frame(self.main, padx=1, pady=50)
        self.buttons.pack(fill=tk.BOTH)     
        photo = PhotoImage(file = r"stt.png")
        photoimage = photo.subsample(5, 5) 
        self.strt_rec = tkinter.Button(self.buttons, width=100, padx=8, pady=25, text='\n\n\n\nStart Recording', command=lambda: self.start_record(), bg='white', image = photoimage, compound = CENTER)
        self.strt_rec.grid(row=0, column=0, columnspan=2, padx=50, pady=5)

        self.stop_rec = tkinter.Button(self.buttons, width=100, padx=8, pady=25, text='\n\n\n\nStop Recording', command=lambda: self.stop_record(), bg='white', image = photoimage, compound = CENTER)
        self.stop_rec.grid(row=0, column=1, columnspan=2, padx=450, pady=5) 

        self.op_text = Label(self.main,textvariable = self.var,foreground="green",font = "Times 30 bold italic")
        self.op_text.place(x=350,y=100,anchor=NW)
        self.op_text.pack()
        tkinter.mainloop()

    def start_record(self):
        WAVE_OUTPUT_FILENAME = "recordedFile.wav"
        while True:
            data_frame = self.stream.read(self.CHUNK)
            data_int16_frame = list(struct.unpack(str(self.CHUNK) + 'h', data_frame))
            ...
            ...
    def stop_record(self):
        self.stream.stop_stream()
        self.stream.close()
        self.p.terminate()

guiAUD = RecAUD()

How do I go about solving this issue, what should I add to the above code to make the buttons responsive at anytime? Is multithreading required? If yes, how can I introduce it for the buttons in the above code? Any suggestions are much appreciated! Thanks in advance!

3
  • I think this is a case where update can be used. In the loop, you have to let your GUI "alive". Commented Apr 16, 2020 at 6:25
  • Thank you, but I'm not sure how that works. Can you kindly explain it in a little bit more detail. The processing inside the loop shouldn't be affected though. Commented Apr 16, 2020 at 6:29
  • I suggest you insert a self.buttons.update() (or something like this) inside your loop (while True I suppose) at the end. EDIT: you should apply update just to the stop button. Commented Apr 16, 2020 at 6:34

2 Answers 2

2

You can use threading a module used to make threads

import threading

class cls():
     def __init__():
         self.thrun = True

     def start_record(self):
         WAVE_OUTPUT_FILENAME = "recordedFile.wav"
         while self.thrun:
             data_frame = self.stream.read(self.CHUNK)
             data_int16_frame = list(struct.unpack(str(self.CHUNK) + 'h', data_frame))


     def click(self):
         self.th = threading.Thread(target=start_record)

     def stop(self):
         self.thrun = False
         self.th.join()
Sign up to request clarification or add additional context in comments.

Comments

-1

For example, you can add a update in a while True to kke the GUI "alive". In the code below, press first OK, it enters in a while True loop but with update, GUI reacts when you press KO:

import tkinter as tk

a = 0

def action():
    global a
    while True:
        if a == 0:
            b.configure(bg="red")
        else:
            b.configure(bg="blue")
        w.update()

def reaction():
    global a
    a = 1

w = tk.Tk()

b = tk.Button(w, text="OK", command=action)
c = tk.Button(w, text="K0", command=reaction)
b.pack()
c.pack()

w.mainloop()

The danger is to enter in multiple calls to action and worse in recursive calls... you, in these cases, should manage this in your start callback.

1 Comment

Sure. This was an example inserting a while True loop as asker code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.