You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi,
I'm trying to modify this example in order to make it compatible with multiprocessing.
Mainly I had to rename some global variables:
#!/usr/bin/env python3
import sys
import threading
import jack
from mido import MidiFile
from multiprocessing import Process
midi_file = '../Musica/Mozart/k265/Zwölf-Variationen.midi'
try:
mid = iter(MidiFile(midi_file))
except Exception as e:
sys.exit(type(e).__name__ + ' while loading MIDI: ' + str(e))
client = jack.Client('Luces')
midi_port = client.midi_outports.register('output')
midi_event = threading.Event()
midi_msg = next(mid)
midi_fs = None # sampling rate
midi_offset = 0
@client.set_process_callback
def process(frames):
global midi_offset
global midi_msg
midi_port.clear_buffer()
while True:
if midi_offset >= frames:
midi_offset -= frames
return # We'll take care of this in the next block ...
# Note: This may raise an exception:
midi_port.write_midi_event(midi_offset, midi_msg.bytes())
try:
midi_msg = next(mid)
except StopIteration:
midi_event.set()
raise jack.CallbackExit
midi_offset += round(midi_msg.time * midi_fs)
@client.set_samplerate_callback
def samplerate(samplerate):
global midi_fs
midi_fs = samplerate
@client.set_shutdown_callback
def shutdown(status, reason):
print('JACK shutdown:', reason, status)
midi_event.set()
def run_midi():
with client:
print('Playing', repr(midi_file), '... press Ctrl+C to stop')
try:
midi_event.wait()
except KeyboardInterrupt:
print('\nInterrupted by user')
if __name__ == "__main__":
processes = [Process(target=run_midi)]
for p in processes:
p.start()
for p in processes:
p.join()
Now I get this error at the end of the execution:
Playing '../Musica/Mozart/k265/Zwölf-Variationen.midi' ... press Ctrl+C to stop
Cannot read socket fd = 5 err = Success
CheckRes error
JackSocketClientChannel read fail
JACK shutdown: JACK server has been closed <jack.Status 0x21: failure, server_error>
What OS are you on? (there is some specifics of spawning child processes with multiprocessing that do not work on Windows quite the way they work on Linux or macOS)
Also, I believe you want to use multiprocessing.Event instead of threading.Event in order to be consistent. This is to begin with and most probably not going to solve your problem (yet).
I believe you want to use multiprocessing.Event instead of threading.Event in order to be consistent.
Yes, this makes sense.
Here is my current code:
#!/usr/bin/env python3
import sys
import jack
from mido import MidiFile
from multiprocessing import Process, Event
midi_file = '../Musica/Mozart/k265/Zwölf-Variationen.midi'
try:
mid = iter(MidiFile(midi_file))
except Exception as e:
sys.exit(type(e).__name__ + ' while loading MIDI: ' + str(e))
client = jack.Client('Luces')
midi_port = client.midi_outports.register('output')
midi_event = Event()
midi_msg = next(mid)
midi_fs = None # sampling rate
midi_offset = 0
@client.set_process_callback
def process(frames):
global midi_offset
global midi_msg
midi_port.clear_buffer()
while True:
if midi_offset >= frames:
midi_offset -= frames
return # We'll take care of this in the next block ...
# Note: This may raise an exception:
midi_port.write_midi_event(midi_offset, midi_msg.bytes())
try:
midi_msg = next(mid)
except StopIteration:
midi_event.set()
raise jack.CallbackExit
midi_offset += round(midi_msg.time * midi_fs)
@client.set_samplerate_callback
def samplerate(samplerate):
global midi_fs
midi_fs = samplerate
@client.set_shutdown_callback
def shutdown(status, reason):
print('JACK shutdown:', reason, status)
midi_event.set()
def run_midi():
with client:
print('Playing', repr(midi_file), '... press Ctrl+C to stop')
try:
midi_event.wait()
except KeyboardInterrupt:
print('\nInterrupted by user')
if __name__ == "__main__":
# run_midi()
processes = [Process(target=run_midi)]
for p in processes:
p.start()
for p in processes:
p.join()
When calling run_midi() (by commenting the multiprocessing part) now I get this output at the end of the execution:
Playing '../Musica/Mozart/k265/Zwölf-Variationen.midi' ... press Ctrl+C to stop
Cannot read socket fd = -1 err = Success
Could not read result type = 7
but after that the command line is available. So, something wrong happens with multiprocessing.Event() used as replacement of threading.Event().
When running the code I posted here (by commenting the run_midi() call) I get this output at the end of the execution:
Playing '../Musica/Mozart/k265/Zwölf-Variationen.midi' ... press Ctrl+C to stop
Cannot read socket fd = 5 err = Success
CheckRes error
JackSocketClientChannel read fail
JACK shutdown: JACK server has been closed <jack.Status 0x21: failure, server_error>
and the process doesn't stop: so no differences compared to my previous attempt with multiprocessing+threading.
I'm not sure. I suppose it would be the must solid solution for my purpose (if it works properly). At the moment I'm testing a simpler way (threading) and postponing the migration to multiprocessing.
If you really need multiprocessing, you should try to simplify your reproducible example
Isn't that the only way to realize file playback (either audio or MIDI) as an independent component which can be e.g. invoked or remote controlled by other parts of an application?
If then multiprocessing or threading is used probably doesn't change the method or required effort of the implementation, or does it?
Since quite a while, I was thinking to create a simple reference example for (audio) file playback which utilizes multiprocessing (and/or maybe also one with threading). @mgeier do you think that would be useful, especially with regards of investigating the latter part of:
This is really hard to get right and some libraries might not support it very well. I don't know if the jack module does or not.
Isn't that the only way to realize file playback (either audio or MIDI) as an independent component which can be e.g. invoked or remote controlled by other parts of an application?
It depends on what exactly you mean by "independent component", but I don't think so.
In simple cases, neither threading nor multiprocessing are needed, because the audio callback runs in a separate thread anyway, and whatever else has to be done, can be done in the main thread.
But if multiple things have to be done concurrently in the main thread, a solution has to be found.
I guess the next best solution is to use threading, but probably async/await (with or without asyncio) could be used as well. multiprocessing should only be used if it's really needed.
If then multiprocessing or threading is used probably doesn't change the method or required effort of the implementation, or does it?
In my experience it very much does, because multiprocessing is harder to use than it might seem at first glance.
The resulting code is certainly less intuitive, because you have to think about which parts of the program state will be duplicated in multiple processes, which often isn't very obvious.
Since quite a while, I was thinking to create a simple reference example for (audio) file playback which utilizes multiprocessing (and/or maybe also one with threading). @mgeier do you think that would be useful, especially with regards of investigating the latter part of:
This is really hard to get right and some libraries might not support it very well. I don't know if the jack module does or not.
Yes, having an example to test whether the jack module works with multiprocessing would be great!
But it would be really good if the example would somehow represent a situation where multiprocessing matters.
Of course it should be as simple as possible, but it would be good for illustration if one of the processes would do some CPU-intensive work.
Activity
HaHeho commentedon Nov 7, 2020
What OS are you on? (there is some specifics of spawning child processes with
multiprocessingthat do not work on Windows quite the way they work on Linux or macOS)Also, I believe you want to use
multiprocessing.Eventinstead ofthreading.Eventin order to be consistent. This is to begin with and most probably not going to solve your problem (yet).Stemby commentedon Nov 8, 2020
Hi @HaHeho,
thank you for your reply.
Debian GNU/Linux (testing) with kernel realtime:
Yes, this makes sense.
Here is my current code:
When calling
run_midi()(by commenting the multiprocessing part) now I get this output at the end of the execution:but after that the command line is available. So, something wrong happens with
multiprocessing.Event()used as replacement ofthreading.Event().When running the code I posted here (by commenting the
run_midi()call) I get this output at the end of the execution:and the process doesn't stop: so no differences compared to my previous attempt with multiprocessing+threading.
Thanks!
mgeier commentedon Nov 11, 2020
@Stemby Let's take a step back: do you really need
multiprocessing?This is really hard to get right and some libraries might not support it very well. I don't know if the
jackmodule does or not.If you don't really need
multiprocessing, you should do yourself the favor and not use it.If you are willing to load the whole audio file into memory (the MIDI file is already in memory), you might not even need
threading!If you really need
multiprocessing, you should try to simplify your reproducible example:midodependency. Just send some dummy MIDI messages.Then we can start debugging ...
Stemby commentedon Nov 12, 2020
Thanks @mgeier!
I'm not sure. I suppose it would be the must solid solution for my purpose (if it works properly). At the moment I'm testing a simpler way (threading) and postponing the migration to multiprocessing.
OK, thank you!
HaHeho commentedon Nov 12, 2020
Isn't that the only way to realize file playback (either audio or MIDI) as an independent component which can be e.g. invoked or remote controlled by other parts of an application?
If then
multiprocessingorthreadingis used probably doesn't change the method or required effort of the implementation, or does it?Since quite a while, I was thinking to create a simple reference example for (audio) file playback which utilizes
multiprocessing(and/or maybe also one withthreading). @mgeier do you think that would be useful, especially with regards of investigating the latter part of:mgeier commentedon Nov 12, 2020
It depends on what exactly you mean by "independent component", but I don't think so.
In simple cases, neither
threadingnormultiprocessingare needed, because the audio callback runs in a separate thread anyway, and whatever else has to be done, can be done in the main thread.But if multiple things have to be done concurrently in the main thread, a solution has to be found.
I guess the next best solution is to use
threading, but probablyasync/await(with or withoutasyncio) could be used as well.multiprocessingshould only be used if it's really needed.In my experience it very much does, because
multiprocessingis harder to use than it might seem at first glance.The resulting code is certainly less intuitive, because you have to think about which parts of the program state will be duplicated in multiple processes, which often isn't very obvious.
Yes, having an example to test whether the
jackmodule works withmultiprocessingwould be great!But it would be really good if the example would somehow represent a situation where
multiprocessingmatters.Of course it should be as simple as possible, but it would be good for illustration if one of the processes would do some CPU-intensive work.
mgeier commentedon May 25, 2021
@Stemby Any news on this?