It is currently September 21st, 2021, 5:05 pm

Bell ring clock skin

Help with creating, editing & fixing problems with skins
User avatar
FreeRaider
Posts: 816
Joined: November 20th, 2012, 11:58 pm

Bell ring clock skin

Post by FreeRaider »

Hello all.

I would like to write a clock skin that when it is 11:30 bell 1 rings 11 times and bell 2 rings 2 times or if it is 15:00 bell 1 rings 15 times while bell 2 does not ring.

I'm very rusty in scripting and I can't figure out how to do that.

Some idea?

Thanks
User avatar
death.crafter
Posts: 937
Joined: April 24th, 2021, 8:13 pm

Re: Bell ring clock skin

Post by death.crafter »

FreeRaider wrote: July 17th, 2021, 10:36 pm Hello all.

I would like to write a clock skin that when it is 11:30 bell 1 rings 11 times and bell 2 rings 2 times or if it is 15:00 bell 1 rings 15 times while bell 2 does not ring.

I'm very rusty in scripting and I can't figure out how to do that.

Some idea?

Thanks
Lua:

Code: Select all

function Update()
    local timeMeasure=SKIN:GetMeasure('Time')
    local time=timeMeasure:GetStringValue()
    local hour=time:gsub('^(.*):(.*)$', '%1')
    local minute=time:gsub('^(.*):(.*)$', '%2')
    hour, minute=tonumber(hour), tonumber(minute)
    for i=1, hour, 1 do
        SKIN:Bang('Play', [[path\to\hoursound]])
    end
    for i=1, minute%15 do
        SKIN:Bang('Play', [[path\to\minutesound]])
    end
end
from the Realm of Death
My Current Desktop
User avatar
jsmorley
Developer
Posts: 22288
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Bell ring clock skin

Post by jsmorley »

death.crafter wrote: July 18th, 2021, 12:59 am Lua:

Code: Select all

function Update()
    local timeMeasure=SKIN:GetMeasure('Time')
    local time=timeMeasure:GetStringValue()
    local hour=time:gsub('^(.*):(.*)$', '%1')
    local minute=time:gsub('^(.*):(.*)$', '%2')
    hour, minute=tonumber(hour), tonumber(minute)
    for i=1, hour, 1 do
        SKIN:Bang('Play', [[path\to\hoursound]])
    end
    for i=1, minute%15 do
        SKIN:Bang('Play', [[path\to\minutesound]])
    end
end
In and of itself, I believe that is going to ring on every single update. You will need to put this in a different function, and call it with an IfCondition on the Time measure, where it will only fire once when the hour and / or minute first turns. Some kind of If seconds = 0. Either that, or build the "only fire once when the seconds are zero" test into the Lua.

In addition there is no way in the world you can possibly have a sound short enough to be allowed to even start to play through before that loop will instantly tell it to play again, stopping the first one. You have to keep in mind how the Play command works... I believe you will hear the sound once, no matter the hour or minute.
User avatar
Yincognito
Rainmeter Sage
Posts: 4052
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Bell ring clock skin

Post by Yincognito »

FreeRaider wrote: July 17th, 2021, 10:36 pmI would like to write a clock skin that when it is 11:30 bell 1 rings 11 times and bell 2 rings 2 times or if it is 15:00 bell 1 rings 15 times while bell 2 does not ring.
I will assume that since bell 2 rings 2 times at 30 minutes, you'd like that bell to ring once for a quarter of an hour, i.e. 15 minutes, and that you know how to display a measure value in a meter. If so, what you need to do is:
1) have 2 Time measures, one for Hours and one for Minutes (use the Format option and the time format codes to set them properly)
2) the 2 measures above will be used for both displaying time in associated meters, but also for calculating the number of times the associated bells will ring in another 2 measures, like (for minutes, since for hours it's pretty straight-forward):

Code: Select all

[MinuteRings]
Measure=Calc
Formula=(Trunc(Minutes/15))
3) have 2 short .WAV files with the rings you want to play using the Play bang
3) have an ActionTimer measure somewhere in your skin that will repeat ringing as many times as needed for both hours and minutes using the measure values from step 2), like:

Code: Select all

[Ring]
Measure=Plugin
Plugin=ActionTimer
ActionList1=Repeat HourRing,1000,[HourRings] | Wait 1000
ActionList2=Repeat MinuteRing,1000,[MinuteRings] | Wait 1000
HourRing=[Play "Bell1.wav"]
MinuteRing=[Play "Bell2.wav"]
DynamicVariables=1
4) trigger the ringings when HourRings and MinuteRings from step 2) change, by adding OnChangeAction-s to those measures, like:

Code: Select all

[HourRings]
...
OnChangeAction=[!CommandMeasure Ring "Stop 1"][!CommandMeasure Ring "Execute 1"]

Code: Select all

[MinuteRings]
...
OnChangeAction=[!CommandMeasure Ring "Stop 2"][!CommandMeasure Ring "Execute 2"]
Apart from that, some things should be treated with care here:
- as noted in the manual "only one sound at a time can be managed, Rainmeter-wide. Playing a sound in any skin will stop any other currently playing sounds", so I'm not sure if you can properly play both bell 1 and bell 2 at the same time, even with the 1000 milliseconds interval between rings at step 3); if not, you can try playing them sequentially (say, the hour rings first and the minute rings second), by adding an appropriate delay at the start of the [MinuteRings]' OnChangeAction
- you might need to adjust the 1000 milliseconds intervals between rings at step 3), depending on the length in milliseonds of your bell 1 and/or bell 2 .WAV sounds

That's pretty much it, overall. If you need further help with the code, don't hesitate to ask. I'll be probably busy today/tomorrow, but hopefully others will step in if necessary.

P.S. Huh! I wrote here for like a quarter of an hour, and death.crafter comes up with a 10 lines Lua script... Freaking Lua, LMAO! But he still has a mistake, since the minute FOR should not use modulus / remainder, but the "div" function, i.e. the integer part of the division. :D
User avatar
Yincognito
Rainmeter Sage
Posts: 4052
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Bell ring clock skin

Post by Yincognito »

jsmorley wrote: July 18th, 2021, 1:09 am In and of itself, I believe that is going to ring on every single update. You will need to put this in a different function, and call it with an IfCondition on the Time measure, where it will only fire once when the hour and / or minute first turns. Some kind of If seconds = 0.

In addition there is no way in the world you can possibly have a sound short enough to be allowed to play once before that loop will instantly tell it to play again, stopping the first one.
What if he sets the Lua measure to update once every 15 minutes, taking care to only play the hour if the minutes are 0?

EDIT: That won't be as precise though, from a time perspective...
User avatar
jsmorley
Developer
Posts: 22288
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Bell ring clock skin

Post by jsmorley »

Yincognito wrote: July 18th, 2021, 1:20 am What if he sets the Lua measure to update once every 15 minutes, taking care to only play the hour if the minutes are 0?

EDIT: That won't be as precise though, from a time perspective...
That literally will have nothing to do with the "time". In any case it really must only fire when the hour changes and the seconds are zero.

I don't believe this can be done just in Lua. There is no "sleep" command in Lua, and if there was, it would be horrifically "blocking" on the entire skin. I'm fine with using Lua to evaluate the time and see if the hour has just changed and the seconds are zero. Going to need to set some true/false flag (ala IfCondition) that tells it to skip playing until the condition happens again, the hour changes and the seconds are zero. Then you clear the flag, let the bells ring, and at the end of that process you set the flag again.

The actual calling of Play over and over the number of times in the hour will likely need to be done by having the Lua call an ActionTimer script in the skin. That is the only way that you are going to be able to call Play over and over while leaving enough time between each call for the sound to finish.

I'm not entirely convinced that Lua must, or even should, play a role in this at all. I think this is best as a combination of IfCondition on one or more Time measures, and probably two ActionTimer measures.

To be perfectly honest, I almost always regret it when I post code without actually testing it.
User avatar
Yincognito
Rainmeter Sage
Posts: 4052
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Bell ring clock skin

Post by Yincognito »

jsmorley wrote: July 18th, 2021, 1:23 am That literally will have nothing to do with the "time". In any case it really must only fire when the hour changes and the seconds are zero.
Yep, indeed.
User avatar
Yincognito
Rainmeter Sage
Posts: 4052
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Bell ring clock skin

Post by Yincognito »

jsmorley wrote: July 18th, 2021, 1:23 amI don't believe this can be done just in Lua. There is no "sleep" command in Lua, and if there was, it would be horrifically "blocking" on the entire skin.
Yeah, I was looking at ways to simulate a "sleep" command in Lua, some of them are really hilarious, like os.execute, ping, or socket. Being a scripting language where the parent language is assumed to have most of the tools one needs certainly has its drawbacks, it seems.
User avatar
jsmorley
Developer
Posts: 22288
Joined: April 19th, 2009, 11:02 pm
Location: Fort Hunt, Virginia, USA

Re: Bell ring clock skin

Post by jsmorley »

Yincognito wrote: July 18th, 2021, 1:45 am Yeah, I was looking at ways to simulate a "sleep" command in Lua, some of them are really hilarious, like os.execute, ping, or socket. Being a scripting language where the parent language is assumed to have most of the tools one needs certainly has its drawbacks, it seems.
It never pays to have Lua do things that take a lot of time before control is returned to the skin. I honestly don't think Lua has a real role to play in this solution. The only thing that isn't going to be "blocking" on the skin while the sounds are played is ActionTimer. As I said, you will need to test for the hour just changing and the seconds at zero, and the minutes just changing to one of 0/15/30/45 or whatever effect you are going for. Then you need to have the "hour" ActionTimer fire for some "repeat" number of times, and when and only when that is finished, fire the "minute" ActionTimer to sound the minutes.
User avatar
Yincognito
Rainmeter Sage
Posts: 4052
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Bell ring clock skin

Post by Yincognito »

jsmorley wrote: July 18th, 2021, 1:23 amI'm not entirely convinced that Lua must, or even should, play a role in this at all. I think this is best as a combination of IfCondition on one or more Time measures, and probably two ActionTimer measures.

To be perfectly honest, I almost always regret it when I post code without actually testing it.
Any particular reason to use 2 AT measures since 1 AT can hold both action lists, and doesn't force the user to use both?
Regarding testing, you're probably right, but in this case it would take lots of time changes in the OS to make sure the code is properly working in all more or less fringe scenarios. That is why I opted for an explanation rather than posting a full code as well. I agree on the thinking twice before doing something principle though.
jsmorley wrote: July 18th, 2021, 1:51 amIt never pays to have Lua do things that take a lot of time before control is returned to the skin. I honestly don't think Lua has a real role to play in this solution. The only thing that isn't going to be "blocking" on the skin while the sounds are played is ActionTimer.
Since we're at this, do you see a drawback in using !Delay in my approach? Since in a way, that's also kind of blocking, as far as I recall...