What is the best way to use a timer?

What would be the best way to use a timer (with callback function) in a (C++) Extension?

In GP Script, there is the function On TimerTick, or even a generator can be used.
Is there an alternative inside the extension SDK? Or should I use a Windows/Win32 timer? (I might get into problems with threads possibly).

When you create an extension, you have access to the full power of your operating system. You can create your own threads, timers, GUI components, networking, general file handling and so on.

The GP-SDK is solely intended to access functionality unique to GP such as access to widgets, plugins, some control (switching rackspaces, songs, etc), starting or stopping the play head, etc. But there’s nothing special about timers.

It is not intended to be a library or wrapper that exposes full OS functionality.

If you want an easy way to create timers, threads, OSC or other things that are not specific to gig performer, then use a library like JUCE which exposes those kinds of things and wraps OS functionality in a way that allows it to be cross-platform.

By the way, I was looking at the code to see why we didn’t expose parameter change callbacks to date and the reason is because those changes can happen inside the audio processing block. Exposing that to an extension directly is very dangerous as even the slightest delay in handling them will immediately cause audio glitching. In the short term, I’m considering optionally making them available by pushing the messages into the GUI thread (also not inexpensive) and will slow GUI response time if there are a lot of parameter changes. I may consider using a separately buffered object on another thread but even that will require the SDK developer to be very careful to avoid locking that buffer and basically killing audio.

3 Likes

Thank you for your elaborated answer and comments.

I understand that the SDK is only for GigPerformer, but better asking before than finding out there is a different (better) solution. It’s some time ago I used timers on Windows, so something to dive into (probably enough examples to be found).

I will first try a ‘normal’ WIndows method, maybe later going to check into JUCE. Also, for me being cross platform compatible is not a must.

I requested for the parameter callback functions, as you said in principle all GP script functions are easy to port to the SDK (btw, I meanwhile found some others, but I will make a list or a single thread out of it later, that might be easier). For my use case, MAYBE I can do without parameter callbacks, as I used them for the Insert Piz Here AudioToCc plugin, but it also works via MIDI … on the other hand, this might also cause a performance penalty, but in about two months I hope to have my extension finished in such a way I can do some performance testing.

On the other hand, I think it wouldn’t matter if the extension handles the parameter callback functions, or a GP script … or are they handled differently regarding thread usage?

Also, next week I will reserve a few hours for beta-testing, because npudar is right that I (also) should focus on beta testing… I am just so much in the flow of writing the extension (I probably will reach over 10K lines when all is finished). And happy to share it for everyone (although it will be quite hardware specific), although the framework is generic.

Before you go much further,I would strongly encourage you to take a look at using JUCE (and there’s already an example project to get you started). Beyond the value of being cross-platform, JUCE has a huge collection of classes for building applications and libraries. You’ll save yourself a lot of time.

For example, using a normal Windows method, you have to do stuff like this

whereas in juce with a lambda you can just write

   Timer::callAfterDelay(10000, []()
      {
         //  process a 10-second timer
      }   
   );

…no need to have handles to windows, timer identifiers, and so forth.

Just my two cents

1 Like

I think it might even be more complicated, as there is no default loop to check messages, I cannot make a loop in a callback function from GP, and doing it in another thread might result in other issues (data handling between threads).

I think this is indeed the way to go, I will finish a part I’m busy with next week and then check into JUCE; most of my code will probably still not have to be changed.
Also later, I might want to use OSC messages. Or maybe in time a dedicated UI, although I like the GP builtin widgets a lot.

FYI:

There is a possibility to use null for the windowshandle, but it is not very clean.

This is the windowless/message-less version:

1 Like

Thanks for that solution, however, I think I will try first the JUCE solution, as it has more features I might want to incorporate later when needed (like OSC messages). Or even another (G)UI.

@dhj Thanks for mentioning Juce … it took a bit of timing getting both the extension and the test project compiling, but they compile (testing in GP I will do later). Setting a timer is super easy in Juce :slight_smile:

1 Like

And now your extension can be cross platform! :+1:

2 Likes

True … I will make file I/O implementation somewhere in 1 to 2 weeks from now, using JUCE so that also will be cross platform.

The only disadvantage for most is, that my extension is heavily based on some specific hardware (MIDI oxygen 61, or at least a MIDI keyboard with 9 knobs, 13 buttons), a secondary keyboard, and a MIDI foot pedal with (at least 5) switches and 2 pedals. It will probably be quite some work to make this so flexible any hardare can be used, but in the end, but I will do my best to describe the structure so people can change/adapt it for their own use, if they want.

1 Like