I'm on python2-7 I want to get a button in tkinter which stop the reading of the notes created with fluidsynth.
I found that the common solution is to use time.after like here: How do you create a Tkinter GUI stop button to break an infinite loop?
But in my case I can't use it because I need an amount of time between noteon and noteoff to give durations for my notes. Moreover I want to play the notes ONLY if I click on start (and no at the beginning like the solution in the link).
So I created this code but it doesn't work because var_start is always initialized as int:
from tkinter import*
import fluidsynth
import time
fs=fluidsynth.Synth()
fs.start(driver='alsa', midi_driver='alsa_seq')
org_charge = fs.sfload("organ.sf2")
fs.program_select(0,org_charge, 0, 0)
time.sleep(1)
var_start=int
def start():
global var_start
var_start=1
def stop():
global var_start
var_start=0
root=Tk()
if var_start==1:
fs.noteon(0,67,127)
time.sleep(1)
fs.noteoff(0,67)
fs.noteon(0,71,127)
time.sleep(1)
fs.noteoff(0,71)
fs.noteon(0,74,127)
time.sleep(1)
fs.noteoff(0,74)
Button(root, text='start', command= start).pack(padx=10, pady=10)
Button(root, text='stop', command= stop).pack(padx=10, pady=10)
root.mainloop()
I don't have other idea to reshape my code... Can someone help me ?
Thanks
You initiated var_start
to int
in statement var_start=int
and so the code block in if var_start==1:
will never be executed. And your start()
function is just changing the var_start
to 1 and never start playing the notes, therefore nothing will happen.
Never call time.sleep()
in main thread as it will block the tkinter
main loop. You can use .after(...)
to simulate the play loop and below is a sample code block:
playing = False
def play_notes(notes, index, noteoff):
global playing
if noteoff:
fs.noteoff(0, notes[index])
index += 1 # next note
if playing and index < len(notes):
fs.noteon(0, notes[index], 127)
# call noteoff one second later
root.after(1000, play_notes, notes, index, True)
else:
# either stopped or no more note to play
playing = False
print('done playing')
def start_playing():
global playing
if not playing:
print('start playing')
playing = True
notes = [67, 71, 74, 88, 80, 91]
play_notes(notes, 0, False)
else:
print('already playing')
def stop_playing():
global playing
if playing:
playing = False
print('stop playing')
else:
print('nothing playing')
Button(root, text='Start', command=start_playing).pack(padx=10, pady=10)
Button(root, text='Stop', command=stop_playing).pack(padx=10, pady=10)
It is just an example you can modify to suit your need.