Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement "Wait for next {bar,beat}" and "Wait until end of loop" actions on macOS #1685

Merged
merged 1 commit into from Jan 16, 2023

Conversation

cfillion
Copy link
Collaborator

@cfillion cfillion commented Oct 12, 2022

This uses a very dodgy hack to prevent deadlocks (due to GetPlayPosition not updating) if the wait actions are ran from within REAPER's misc timer (eg. a script's defer callback). The workaround just posts a WM_TIMER to the main window every 30 ms. This bypasses NSTimer's reentrency check.

The Windows implementation still tests the exit condition every 1 ms (vs 30 ms on macOS). However this is likely more than necessary assuming GetPlayPosition is also updated by the misc timer there.

Take

Fixes #971, fixes #1676.

@cfillion cfillion force-pushed the wait-on-macos branch 2 times, most recently from 0db5fe5 to 6db85e3 Compare October 12, 2022 01:53
@AppVeyorBot

This comment was marked as outdated.

@AppVeyorBot

This comment was marked as outdated.

@cfillion cfillion marked this pull request as ready for review October 18, 2022 22:49
@AppVeyorBot

This comment was marked as outdated.

cfillion added a commit to cfillion/reaimgui that referenced this pull request Oct 19, 2022
Unlikely to happen naturally, but required for reaper-oss/sws#1685
@AppVeyorBot

This comment was marked as outdated.

@cfillion cfillion merged commit b2a2c32 into reaper-oss:master Jan 16, 2023
@LexaProductions
Copy link

Amazing CFillion!
But on Mac we're still at a 30ms precision? So this is not advantage vs a normal deferred callback function

Not too sure I understood the statement:
"However this is likely more than necessary assuming GetPlayPosition is also updated by the misc timer there."

@cfillion
Copy link
Collaborator Author

cfillion commented Jan 19, 2023

That's right. GetPlayPosition is only updated once per 30ms+ so even on Windows the accuracy is not better than a reaper.defer.

@LexaProductions
Copy link

LexaProductions commented Jan 19, 2023

Ok Cool thanks.
Would a precise_timer be more accurate than then "playposition/TimeMap2_" method?

Just asking as I've would've hoped to get the same precision as a "Smooth Seek" action

@cfillion
Copy link
Collaborator Author

cfillion commented Jan 19, 2023

A solution using the wall clock could be more precise (within limits, nothing in the main thread will ever come anywhere close to be sample-accurate or even jitter-free). Wouldn't be comparable to smooth seek.

@LexaProductions
Copy link

I have a "Seek to next tab" function which kinda works pretty good but is not as tight as Reaper's "Smooth Seeking" capacities

I use this:

function NextMeasure(outfunction, timingOffs, padding) -- timingOffs: Offset End of bar triggering point <0 =before the bar, >0 After the bar
	local latency = reaper.GetOutputLatency()+0.05
	local pos = reaper.GetPlayPosition()+padding
	local _, msr = reaper.TimeMap2_timeToBeats(0, pos) -- Add Padding in secs
	local _, _, bar_end_qn = reaper.TimeMap_GetMeasureInfo(0, msr)
	local bar_end = reaper.TimeMap2_QNToTime(0, bar_end_qn)
	local bar_end_precise = bar_end-pos+reaper.time_precise()
-- Polling loop function
	local function Loop()
		if reaper.GetPlayState() == 0 then return end -- if stopped while running abort without doing anything.
		local t = reaper.time_precise()

		if t - bar_end_precise+latency > timingOffs then -- if arrived at Next Bar
			outfunction()
			return
		end
		reaper.defer(function() Loop() end)
	end
-- Call polling loop function
	Loop()
end

@cfillion
Copy link
Collaborator Author

cfillion commented Jan 19, 2023

Nothing can come close to smooth seek but hacking REAPER's misc timer to fire more often might help a little bit: made one set to 60 Hz (approximately, especially on Windows) at https://forum.cockos.com/showthread.php?p=2546458.

@ultraGentle
Copy link

Excited to use this, but it doesn't appear in the action list. Am I missing something, or has it just not been included in a release, yet?

@cfillion
Copy link
Collaborator Author

cfillion commented Feb 8, 2023

It's part of the 2.13.2 release: https://www.sws-extension.org/download/pre-release/.

@ultraGentle
Copy link

Just tested on M1 Mac. Works as described!

However: blocks other actions (spinning beach ball) until the "wait" action completes.

I don't know if it's feasible, but I think an asynchronous implementation would be more useful. In a live performance/looping scenario, you'd want to fire this and then go about setting up for what's going to happen after. Right now, it just hangs.

Hope that helps!

@cfillion
Copy link
Collaborator Author

cfillion commented Feb 9, 2023

These actions are meant to be used in custom actions. They need to be synchronous to work in that context.

See https://forum.cockos.com/showthread.php?p=2089111#post2089111 and LexaProductions's snippet above for an asynchronous script solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Action "Wait until loop end" appears to be missing request: SWS - Wait for next bar/beat for OSX
4 participants