Остановите чтение заметок, созданных с помощью FluidSynth, с помощью кнопки в tkinter.

Я на python2-7, я хочу получить кнопку в tkinter, которая останавливает чтение заметок, созданных с помощью FluidSynth.

Я обнаружил, что распространенным решением является использование time.after, как здесь: to-break-an-infinite-loop">Как создать кнопку остановки графического интерфейса Tkinter, чтобы разорвать бесконечный цикл?

Но в моем случае я не могу использовать его, потому что мне нужно время между noteeon и noteoff, чтобы указать продолжительность моих заметок. Более того, я хочу воспроизводить ноты ТОЛЬКО, если я нажимаю «Пуск» (а не в начале, как решение в ссылке).

Итак, я создал этот код, но он не работает, потому что var_start всегда инициализируется как 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()

У меня нет другой идеи изменить мой код... Может ли кто-нибудь мне помочь?

Спасибо


person CaptainCoding7    schedule 02.01.2019    source источник


Ответы (1)


Вы инициировали var_start в int в операторе var_start=int, поэтому блок кода в if var_start==1: никогда не будет выполнен. И ваша функция start() просто меняет var_start на 1 и никогда не начинает играть ноты, поэтому ничего не произойдет.

Никогда не вызывайте time.sleep() в основном потоке, так как это заблокирует основной цикл tkinter. Вы можете использовать .after(...) для имитации цикла воспроизведения, и ниже приведен пример блока кода:

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)

Это просто пример, который вы можете изменить в соответствии с вашими потребностями.

person acw1668    schedule 03.01.2019
comment
Спасибо за помощь acw1668! Теперь он работает отлично! - person CaptainCoding7; 04.01.2019