I really need to ask a really curious question about the timeout_add()
function in GLib (which is known as GLib.Functions.TimeoutAdd()
in the C# bindings).
How does the source function inside of the TimeoutAdd not get called at all? And how does it get prevented from the source function inside of it being called?
The reason I ask, is because the project I’m currently working on needs a timer, but when I try to implement the TimeoutAdd(), it doesn’t work at all.
It lands on the break point when I set it, but it’s source function that I add in there, which in this case is PosTimerTick
, doesn’t get called at all, not even once, I’ve even set break points in that method and it doesn’t even land on any of the break points, meaning that it doesn’t even enter into the function.
So I’m really curious, if there’s anything that completely blocks TimeoutAdd from being called? Is there anything?
I know that it’s only the project I’m working on that’s affected, and I’ve checked with other projects that have it implemented, and it has no problems, and I’ve even tried implementing the same function in the same way as those projects, but it doesn’t work.
So it’s really not making any sense as to why it’s not working.
And just to verify that it’s running in the same thread as the GUI, yes it is, and it’s supposed to anyways.
So is there anything at all that prevents a timeout_add
source func from not even running once? I’m really really curious.
Here’s the code in VG Music Studio:
public void LetUIKnowPlayerIsPlaying()
{
// Prevents method from being used if timer is already active
// if (_timer.Enabled)
// {
// return;
// }
// Ensures a GlobalConfig Instance is created if one doesn't exist
if (GlobalConfig.Instance == null)
{
GlobalConfig.Init(); // A new instance needs to be initialized before it can do anything
}
// Configures the buttons when player is playing a sequenced track
_buttonPause.Sensitive = _buttonStop.Sensitive = true; // Setting the 'Sensitive' property to 'true' enables the buttons, allowing you to click on them
_buttonPause.Label = Strings.PlayerPause;
//GLib.Functions.TimeoutSourceNew((uint)(1_000.0 / GlobalConfig.Instance!.RefreshRate));
GLib.Functions.TimeoutAdd(0, (uint)(1_000.0 / GlobalConfig.Instance!.RefreshRate), new GLib.SourceFunc(PosTimerTick));
//GLib.Functions.TestTimerStart();
// _timer.Interval = (int)(1_000.0 / GlobalConfig.Instance!.RefreshRate);
// _timer.Start();
Show();
}
private bool PosTimerTick()
{
if (Engine.Instance is not null)
{
if (_positionBarFree)
{
UpdatePositionIndicators(Engine.Instance!.Player.ElapsedTicks);
return true;
}
}
return false;
}
And here’s the one from some other project that works:
private void OnPlayToggled(object sender, EventArgs args)
{
// play/pause audio
if (Audio != null)
{
string statusText;
// Do we play or pause?
if (PlayButton.Active)
{
Audio.Play();
PlayButton.SetIconName("media-playback-pause-symbolic");
statusText = $"Playing {LoadedFilename}";
GLib.Functions.TimeoutAdd(0, 50, new GLib.SourceFunc(CheckPlayback)); // 20x a second, nice and smooth
}
else
{
Audio.Pause();
PlayButton.SetIconName("media-playback-start-symbolic");
statusText = $"Paused {LoadedFilename}";
}
// Update GUI
StatusLabel.SetText(statusText);
}
}
private bool CheckPlayback()
{
// We need to have an audio file
if (Audio == null)
return false;
if (Audio.IsPlaying)
{
if (!MovingPlaybackSlider)
{
double playbackValue = Map(Audio.Cursor, 0, Audio.Duration.TotalSeconds, PlaybackSlider.Adjustment.Lower, PlaybackSlider.Adjustment.Upper);
PlaybackSlider.Adjustment.Value = playbackValue;
}
return true;
}
// If not, don't do anything
PlayButton.Active = false; // Un-toggle play
return false;
}
Thank you in advance!