PDA

View Full Version : Can I only make one script wait when necessary, not all scripts?



Mastiff
September 5th, 2015, 03:54 PM
I'm working on the playback system in the house, and I have gotten it pretty good. Pressing play in any room will check if the amp is on, and turn it on if it's off, and start playback. If the amp is already on the playback starts at once. But I would like not to cut the first seconds of the song if the amp is off, and I tried to do that with win.Sleep, but of course that stops the whole system dead in the water. This is what I tried. First I set a local variable ampoff = 1 when the amp is off. Then I ran this code:


if ampoff == 1
then win.Sleep(4000)
end

Which only makes the script wait for 4 seconds before it turns on the amp and starts playback, instead of giving the amp "ample" (ha-ha-) time to be turned on and then starting playback. Is there a sneaky trick I can use to get this working?

jon1977
September 5th, 2015, 05:12 PM
I use this a lot:
Note, 'Self' needs defining.
e.g.

local Self = Test

Create a function:



function Self.TimeDelay(milliseconds)
local starttime = win.GetTickCount()
local deltatime = 0
while deltatime < milliseconds do
deltatime = win.GetTickCount() - starttime
end
end


and call it with:



Self.TimeDelay(250)


at the point you want to delay, where the delay is in ms.


Alternatively I use this:


-- delay timer
if Self.Mydelaytimer then
Self.Mydelaytimer: Close()
Self.Mydelaytimer = nil
end

Self.Mydelaytimer = Classes.DelayedExecutionDispatcher:New (1200,delayed_function)


where delayed_function can be renamed to anything and the 1200 is ms.

Neither of these seem to effect my other scripts.

Jon

jmonier
September 6th, 2015, 08:14 AM
How about gir.CreateTimer. This is what I use all over the place to do delays of this sort.

Mastiff
September 6th, 2015, 04:12 PM
Thanks,Jon! That would be exactly what I wanted, if I could get it to work. Have I made a mistake in translating the function name to "pause"? Here's that I changed it to:


function pause(milliseconds)
local starttime = win.GetTickCount()
local deltatime = 0
while deltatime < milliseconds do
deltatime = win.GetTickCount() - starttime
end
end

Then I call it with this part of the transport script, which starts playback of JRMC in a zone, but turns on the amp if it's off:


if LydogBilde.Forsterkere [sone] == false --Meaning that the amp is not turned on
then
Forsterker(sone) --Turn on the amp in the zone
--print("Turning on amp in zone "..sone)
pause(4000)
end

The Forsterker in the third line is a call toanother function to turn on and off amps. This functino checks if the amp in the zone is true or false (on or off) and then turns it off if it's on and on if it's off. But this code stops execution of the Forsterker function as well. So what happens is that if the amp is off, everything waits for 4 seconds and then it turns on the amp and starts playback at the same time, which is exactly what I was trying to stop. Can you see what have I done wrong there?

Jmonier, the timers means (as far as I know) that I would need to cut the transport script in two and have the first part call the function to turn on the amp and then use the timer to start the second part of the script 4 seconds later. I wanted to do it as part of a single function.

Mastiff
September 6th, 2015, 04:36 PM
I tried a very dirty method I use in batchfiles, but that didn't work. I have a batch file that contains ping 1.1.1.168 -n 1 -w 5000 >NUL and tries to ping a pc an IP that isn't on the network. The batch file will wait five seconds before it times out, and then the execution continues. But calling that from Girder doesn't stop the script from executing.

jmonier
September 7th, 2015, 09:35 AM
Jmonier, the timers means (as far as I know) that I would need to cut the transport script in two and have the first part call the function to turn on the amp and then use the timer to start the second part of the script 4 seconds later. I wanted to do it as part of a single function.

Yes, that is the way it works. But, it's otherwise simpler and much more reliable in that it's guaranteed not to suspend other processing that may be taking place (which COULD be the cause of your present problems). A cardinal rule of programming in a multi-tasking environment (such as Windows) is to NEVER hang the processing in a long loop. While it will often work ok, you never know what's going to happen and is very dependent on what's happening otherwise. In this case, for instance, it's POSSIBLE that's it's affecting the mechanism behind win.GetTickCount.

jon1977
September 8th, 2015, 03:58 PM
Looking at this again, I agree with jmonier. My method probably holds up other processing, something I've not noticed.
I've forced some time critical stuff into other threads where I know things have to happen simultaneously, but its tricky to keep track of.
Ive had a lot of success with the girder timers. Although I've used these in the girder tree.
Jon.

Mastiff
September 9th, 2015, 05:01 AM
Well, I guess I can do a dirty workaround: If the track is on pause, I can start playback and then do two rewinds. That should mean that it starts about where I was when I left off. :)