Функция создания звука беззвучна, когда она назначена на собственный процесс

Я работаю над приложением kivy, которое предназначено для параметрического производства упражнений для тренировки слуха на месте и их воспроизведения. Музыка описывается с помощью модуля Mingus и воспроизводится с помощью его Fluidsynth реализации. У меня есть функция воспроизведения упражнения, которая работает, как и предполагалось, при обычном вызове, но, поскольку с этим методом все остальное зависает во время выполнения упражнения (в бесконечном цикле while, ожидающем остановки вручную), это не приводит к приемлемому поведению. Я назначил функцию ее собственному процессу, используя Process()и в зависимости от выхода на терминал он зацикливается, как и предполагалось, но звука нет. Еще один момент, заслуживающий внимания, заключается в том, что многократное нажатие на кнопку запуска приводит к тому, что несколько процессов работают параллельно, судя по ритму активности терминала. Вот код Python-интерфейса:

from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.recycleview import RecycleView
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.config import Config
from classes import *
from multiprocessing import Process
import yaml
Config.set('graphics', 'width', '400')
Config.set('graphics', 'height', '700')

class Welcome(Screen):
    pass

class Builtin(Screen):
    pass

class DrillScreen(Screen):
    def __init__(self, **kwargs):
        super(DrillScreen, self).__init__(**kwargs)
        self.options = kwargs['options']
        self.desc = self.options.des
        self.thedrill = drill(self.options)
        desc = Label(
                text=self.options.des,
                size_hint_x=0.9,
                size_hint_y=1)
        button = Button(
                text = 'Start',
                size_hint=[0.4,0.1])
        button.bind(on_release=self.startdrill())
        self.add_widget(desc)
        self.add_widget(button)

    def startdrill(self):
        def starter(*args):
            proc = Process(target=self.thedrill.run)
            proc.start()
        return starter



class BuiltinView(RecycleView):
    def __init__(self, **kwargs):
        super(BuiltinView, self).__init__(**kwargs)
        with open('builtin.yaml', 'r') as builtin:
            self.drills = yaml.load(builtin)
        self.data = [ {'text': self.drills[i]['name'],
            'on_release': self.startermaker(i,self.drills[i])}
            for i in sorted(self.drills.keys()) ]

    def startermaker(self,num,options):
        def startdrill():
            options = drilloptions(self.drills[num])
            drillscreen = DrillScreen(name='drill', options=options)
            app = App.get_running_app()
            app.root.add_widget(drillscreen)
            app.root.current = 'drill'
            #drillscreen.thedrill.run()
        return startdrill


class Manager(ScreenManager):
    pass

class TestingApp(App):
    def build(self):
        return Manager()

TestingApp().run()

drill класс содержит некоторые параметры в своих атрибутах и ​​входит в цикл для бесконечной генерации упражнений в этих параметрах, когда его .run() метод называется. в button.bind() заявление DrillScreen класс, если я непосредственно положил on_release = self.thedrill.run, я получаю функцию, работающую без проблем. Я не знаю, что мне здесь не хватает. Я могу опубликовать код из других компонентов проекта, если это необходимо. Спасибо.

1 ответ

Ну, пытаясь привести небольшой разбитый пример, я наткнулся на исправление. Я не совсем уверен, почему это работает в одну сторону, а не в другую. Ранее Fluidsynth был инициализирован в .__init__() метод drill класс по созданию, я переместил его в .run() метод. Очень грубо в почти псевдокоде:

До:

class drill:
    def __init__(self, opt):
        #Some attribute setting
        self.ex = None #This will instantiate a class describing a single question
        fluidsynth.init(args)

    def run(self):
        while True:
            #Determining randomly the arguments to create Exercise instance

            self.ex = Exercise(args)
            self.ex.play()

После:

class drill:
    def __init__(self, opt):
        #Some attribute setting
        self.ex = None

    def run(self):
        fluidsynth.init(args)
        while True:

            #Determining randomly the arguments to create Exercise instance

            self.ex = Exercise(args)
            self.ex.play()

Когда я звоню .run() непосредственно с button.bind(), обе версии работают. Когда я назначаю его собственному процессу и передаю этот процесс button.bind(), только вторая версия производит звук. Таким образом, кажется, что примерно происходит то, что инициализированная жидкость не доступна из разных процессов.

Я задержу принятие этого ответа в случае, если кто-то поставит не спекулятивное понимание по этому вопросу.

Другие вопросы по тегам