Create a multithreaded application ?

43 views
Skip to first unread message

Lucas Sanner

unread,
May 17, 2023, 4:23:45 AM5/17/23
to fltk.general
Hi all,
I want to develop a simple sound player that reads audio files by pushing a "play" button.
For sake of simplicity here's a very basic application that mimics what a real sound player application is supposed to do:


void play_cb(Fl_Widget* w, void* window)
{
    printf("Start playing\n");
    usleep(3000000); // Simulates the audio file reading from start to finish.
    printf("Stop playing:\n");

    return;
}

int main(int argc, char **argv) {
    Fl_Window *window = new Fl_Window(340,180);
    Fl_Button *play = new Fl_Button(90, 65, 200, 55, "Play");
    play->callback(play_cb, window);
    window->end();
    window->show(argc, argv);

    return Fl::run();
}

The problem here is the button stay pushed while the audio file is being played and prevent any interaction with the application (menu etc..) until the the audio file reading is finished.

I guess I'm gonna have to use multithreading, but should I use C++ multithreading (thread, join etc...) or FLTK multithreading or both and how should I set this up ?
I've never worked with threads before so any help or guidance would be appreciated.
Thanks in advance.

Basile Starynkevitch

unread,
May 17, 2023, 7:43:34 AM5/17/23
to fltkg...@googlegroups.com
A useful insight on this approach is called continuation-passing style
programming.

https://en.wikipedia.org/wiki/Continuation-passing_style

On 5/17/23 11:31, Basile Starynkevitch wrote:
> On Linux, both should be equivalent, and using POSIX threads.
>
>
> The point is that your audio file playing should be done incrementally
> (and perhaps in another thread, but that might not be necessary).
>
> You probably want to code a routine which sends a few milliseconds of
> sound to the loud speakers, and conceptually loop on it.
>
> That routine could be called incrementally in FLTK callbacks or
> Fl::awake or inside your own custom FLTK event loop.
>
> Be sure to download the source code of FLTK and study it.
>
> Regards.
>
>
> PS: my pet open source project is the RefPerSys inference engine on
> https://github.com/RefPerSys/RefPerSys and http://refpersys.org
>
--
Basile Starynkevitch <bas...@starynkevitch.net>
(only mine opinions / les opinions sont miennes uniquement)
92340 Bourg-la-Reine, France
web page: starynkevitch.net/Basile/

Immanuel Litzroth

unread,
May 17, 2023, 7:43:35 AM5/17/23
to fltkg...@googlegroups.com
Your questions raises a lot of issues. What you should generally do
is have the audio play on another thread. How this is set up depends
very much on the details of the audio system/libraries involved.

Maybe FLTK is not the best choice for doing audio programming if you're
not really fluent with the techniques involved. If you look at
something like JUCE
https://juce.com/
They have a lot of tutorials and also support cross platform GUI/audio/plugin
development.

If you want more in-depth information
https://www.youtube.com/watch?v=boPEO2auJj4
https://www.youtube.com/watch?v=UvRU25T_XOg
There's an audio programming group on youtube that does regular meetups...
Regards,
Immanuel Litzroth
> --
> You received this message because you are subscribed to the Google Groups "fltk.general" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to fltkgeneral...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/fltkgeneral/8aa56ccb-6b55-453d-a7f5-9213364e7cdcn%40googlegroups.com.



--
-- A man must either resolve to point out nothing new or to become a
slave to defend it. -- Sir Isaac Newton

Basile Starynkevitch

unread,
May 17, 2023, 7:43:35 AM5/17/23
to fltkg...@googlegroups.com

On 5/17/23 10:23, Lucas Sanner wrote:

Immanuel Litzroth

unread,
May 17, 2023, 8:38:27 AM5/17/23
to fltkg...@googlegroups.com
Interesting, can you point to some c++ code that does audio programming
in CPS style?
Immanuel
> --
> You received this message because you are subscribed to the Google Groups "fltk.general" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to fltkgeneral...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/fltkgeneral/e5520f02-9adb-bca9-6f0e-34851b807dda%40starynkevitch.net.

Lucas Sanner

unread,
May 17, 2023, 9:15:26 AM5/17/23
to fltk.general
Thanks Immanuel for your reply. 
I know JUCE and you're right, it's probably a more relevant choice when it comes to audio programming.
However, JUCE requires a lot of resources (projucer etc...) and is pretty complicated whereas I'd like to keep the all thing as light as possible.
I use a very light audio library called MiniAudio and here's a basic example of how to read an audio file:

int main(int argc, char** argv)
{
    ma_result result;
    ma_engine engine;

    if (argc < 2) {
        printf("No input file.");
        return -1;
    }

    result = ma_engine_init(NULL, &engine);
    if (result != MA_SUCCESS) {
        printf("Failed to initialize audio engine.");
        return -1;
    }

    ma_engine_play_sound(&engine, argv[1], NULL);

    printf("Press Enter to quit...");
    getchar();

    ma_engine_uninit(&engine);

    return 0;
}

Do you think it's possible to use this kind of library along with FLTK ?

Ian MacArthur

unread,
May 17, 2023, 11:08:13 AM5/17/23
to fltk.general
FLTK works with most threading approaches - you can use pretty much any thread lib, or C++ threads, or whatever you are used to and make it work.

FLTK doesn't provide any threading primitives of it's own but a minimal implementation is shown in the test/threads sample, that just wraps pthread_create() on most hosts or _beginthread() on WIN32 - the API is "similar enough" that it is trivial to wrap them up to look "the same" to the rest of your code.
If you are doing multi-threading with FLTK, do read and understand the "Advanced FLTK" chapter of the docs. first though.
Also, I'd advise you to only use the simplest thread mechanics - in 40-odd years of coding, I've seen all manner of incredibly clever and sophisticated thread schemes, and they always led to disaster! 
Keep it simple...

Audio-wise, I personally still use portaudio, but again pretty much any portable audio lib should work.
As with threads, FLTK has no specific mechanism for audio - though the test/sudoku sample does implement a simple audio class that variously wraps ALSA (*nix systems) CoreAudio (OSX) or WIN32 audio.
In the sudoku sample it is only used to make beeps and pings, so doesn't need an extra thread to keep the audio stream fed, but the audio code that's there could handle more complex audio streams if needed.
For continuous audio a separate thread would probably make the most sense, it's certainly what I do, though if you can keep the audio output buffer filled from a simple timer callback, without blocking your main thread, that can be sufficient - I have certainly seen this done successfully, though it's not the way I'd do it myself!

Actually... I haven't checked, but I have an idea that might be what the test/blocks demo does - might be worth a look, at any rate!
I think it uses basically "the same" audio wrapper mechanics as the sudoku sample, but ISTR it has more complex audio outputs.

Matthias Melcher

unread,
Jun 3, 2023, 4:24:52 PM6/3/23
to fltk.general
FLTK is multi threading aware. If you use FLTK calls from various threads, you must call Fl::lock() once before calling Fl::run(). Fl::run() must be called from the main (initial) thread.  If you call FLTK functions from a different thread, for example, you want to change the color of a widget, you must enclose them in Fl::lock(); myWidget->color(FL_GREEN); myWidget->redraw(); Fl::unlock(); . If you have another thread that need to tell tell the main thread something (for example, that your audio data is loaded), you can use Fl::awake(); from any thread, either with a message (void*) or calling an awake handler (like a callback). See here and sample code here. ('fl_create_thread' is declared in the header file for all platforms).
Reply all
Reply to author
Forward
0 new messages