Robot Jung
Robot Jung

Reputation: 397

Python: my code works perfectly but there is a GUI freezing problem (using tkinter and sounddevice)

I have a code for handle audio data from a sound device.

My code construct the GUI through tkinter and handles audio data through the sounddevice library when the button is pressed.

When I run the code, it actually works perfectly. However, GUI freezing occurs, making it impossible to click the button.

So I tried to solve this problem through thread, but I failed repeatedly.

Please review my code and give me some advice.

This is my Code:

import sounddevice as sd
import numpy as np
import tkinter as tk
from tkinter import ttk
from threading import Thread


class Stream(Thread):
    def __init__(self):
        super().__init__()
        self.input_device_index = 2
        self.output_device_index = 4
        self.BLOCK_SHIFT = 128
        self.SAMPLING_RATE = 16000
        self.BLOCK_LEN = 512
        self.SOUND_DEVICE_LATENCY = 0.2
        self.start_streaming()

    def start_streaming(self):
        try:
            with sd.Stream(device=(self.input_device_index, self.output_device_index),
                       samplerate=self.SAMPLING_RATE, blocksize=self.BLOCK_SHIFT,
                       dtype=np.float32, latency=self.SOUND_DEVICE_LATENCY,
                       channels=1, callback=self.callback):
            input()

    except Exception as ex:
        print(str(type(ex).__name__ + ': ' + str(ex)))

    @staticmethod
    def callback(indata, outdata, frames, time, status):
        outdata[:] = indata


class App(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title("Please Help Me")
        self.geometry("400x300")
        self.resizable(0, 0)

        start_button = tk.Button(self, overrelief="solid", width=15,
                             command=lambda: Function.start_button_clicked(),
                             text="Start", repeatdelay=1000, repeatinterval=100)
        start_button.grid(column=0, row=5)


class Function:
    @staticmethod
    def start_button_clicked():
        stream = Stream()
        stream.start()


if __name__ == "__main__":
    app = App()
    app.mainloop()

Upvotes: 0

Views: 124

Answers (1)

acw1668
acw1668

Reputation: 46688

You used Thread inheritance in a wrong way. You should override run() method in your class. So change start_streaming() to run() and remove calling start_streaming() inside __init__():

class Stream(Thread):
    def __init__(self):
        ...
        # should not call start_streaming() here
        #self.start_streaming()

    # rename start_streaming() to run()
    def run(self):
        ...

Upvotes: 1

Related Questions