It is currently April 27th, 2024, 9:49 pm

Next and Previous Track's Names

General topics related to Rainmeter.
Aryx
Posts: 34
Joined: December 20th, 2023, 9:18 am

Re: Next and Previous Track's Names

Post by Aryx »

Whoa! It happened! Thank you for guiding - rather doing everything! :D Also, cleaning up the code - much appreciated! :bow:

Still got few questions though....:
1. What does this do? Substitute="^(.*)$":'[!CommandMeasure Player "SetPosition \1"]'
2. (Even though I read this somewhere...) [*Track*] means the variable Track, right?
3. What does this do (returns!)? BangR=[#Bang1][&Progress] (I read: I restore it by "executing" the string value of the Progress measure in the OnRefreshAction, but still, can't understand it.)
4. Order of the measures is important? I don't understand.. Alphabetical order or something like that?

5. For Shuffle - On, can I use something like this:

Code: Select all

IfCondition=1
IfTrueAction=[!SetVariable Prev "Shuffle On"] [!SetVariable Next "Shuffle On"]
6. For Repeat - On, can I use this:

Code: Select all

IfCondition=1
IfTrueAction=[!SetVariable Prev "Repeat On - [*Track*]"] [!SetVariable Next "Repeat On - [*Track*]"]
I took your suggestions, and changed fading in/out - it does the magic.

I hope you don't mind me being greedy... I don't understand some bits and want to clear it up..
User avatar
Yincognito
Rainmeter Sage
Posts: 7178
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Next and Previous Track's Names

Post by Yincognito »

Aryx wrote: January 10th, 2024, 12:33 pm Whoa! It happened! Thank you for guiding - rather doing everything! :D Also, cleaning up the code - much appreciated! :bow:

Still got few questions though....:
1. What does this do? Substitute="^(.*)$":'[!CommandMeasure Player "SetPosition \1"]'
2. (Even though I read this somewhere...) [*Track*] means the variable Track, right?
3. What does this do (returns!)? BangR=[#Bang1][&Progress] (I read: I restore it by "executing" the string value of the Progress measure in the OnRefreshAction, but still, can't understand it.)
4. Order of the measures is important? I don't understand.. Alphabetical order or something like that?

5. For Shuffle - On, can I use something like this:

Code: Select all

IfCondition=1
IfTrueAction=[!SetVariable Prev "Shuffle On"] [!SetVariable Next "Shuffle On"]
6. For Repeat - On, can I use this:

Code: Select all

IfCondition=1
IfTrueAction=[!SetVariable Prev "Repeat On - [*Track*]"] [!SetVariable Next "Repeat On - [*Track*]"]
I took your suggestions, and changed fading in/out - it does the magic.

I hope you don't mind me being greedy... I don't understand some bits and want to clear it up..
Asking questions to understand something is perfectly normal, I don't mind it at all. Generally, I only have a problem if folks expect me to repeat things that are already described the same way in the manual because they can't be bothered to read it themselves, not about clarifying things for which the existing info is insufficient.

1. Because of the preceding RegExpSubstitute=1 option, this Substitute option uses regular expressions (basically, patterns made of literal characters and various symbols used to find and / or replace parts of a string) to transform the string value of that measure into the bang between the ' after the : sign. In regular expressions, ^ means the start of the string, $ means the end of the string, . means every character, * means taken any number of times, ( and ) are capturing a part of the string, and \N where N is a number is referencing the N-th capture in the replacement string. So, in effect, I capture the entire string value of the measure (i.e. ^(.*)$) and replace it (i.e. :) with the bang between apostrophes (i.e. [!CommandMeasure Player "SetPosition \1"]) where \1 will be what was captured in the 1st and only capture. In other words, if the string value of that measure is "27.876" corresponding to the position at 27.876 % of the track, then after the replacement it will become [!CommandMeasure Player "SetPosition 27.876"]. In case you wonder, apostrophes are used in the 2nd part of the Substitute because there are already quotes in the replacement string (which would confuse Rainmeter if we were to enclose the replacement with quotes too).

3. Because of the above, this will make the value of the BangR variable to be the string concatenation of Bang1 and the result from the 1. point. So, it will simply append the bang at 1. (which is setting the position in the track to the last value of the Progress measure) to the contents of the Bang1 variable and return it in the BangR variable. That BangR variable is executed in the OnRefreshAction. Without setting the position like that after Bang1 at refresh time, the song that is playing will be re-played from the start because of all that jumping between tracks in the command bangs. This is an imperfect way to alleviate that positional reset, so to speak.

2. [Track] is not a classic variable, it's the value of a measure used as a variable (aka a "section variable" in Rainmeter's terminology). You probably read what you mentioned when checking the link about escaping variables. What escaping does is to temporarily prevent Rainmeter from replacing a variable or measure reference with the actual value of that variable or measure. For example, if the value of the [Track] measure is at one point "SomeTitle - SomeArtist - SomeAlbum" and you do [!SetVariable Prev "[Track]"], then Prev will be SomeTitle - SomeArtist - SomeAlbum. However, since I only store those bangs literally in Bang1 and may use it for any other value of the Track measure, I don't want the [Track] to be replaced with some momentary value of it, I want it to stay as the literal [Track] for the purpose of Bang1. Escaping does that: while [Track] is parsed as the red text earlier, [*Track*] is temporarily parsed as the green text earlier (and it will be replaced with its actual value at a later point in the execution).

4. My bad, I had this written there, but got lost after rephrasing things. I meant the order in the code. You can't properly base the result of a measure on another measure that isn't updated yet. For example, this:

Code: Select all

[MeasureOne]
Measure=Calc
Formula=5

[MeasureTwo]
Measure=Calc
Formula=MeasureOne
will correctly result in MeasureTwo being 5, but this:

Code: Select all

[MeasureTwo]
Measure=Calc
Formula=MeasureOne

[MeasureOne]
Measure=Calc
Formula=5
will result in MeasureTwo being initially 0 (since MeasureOne didn't get a value yet in the code), and afterwards being one update behind MeasureOne (e.g. if the value of MeasureOne changes, this will only be reflected in MeasureTwo after one skin update).

5. and 6. I have no idea why you'd want to use those (since you already have the values of shuffle and repeat displayed in meters), where you'd want to use them, or what exactly you'd want to accomplish with them (I suspect they're incomplete in that regard since you don't have an IfFalseAction or an IfConditionMode=1) but if you want to use those IfConditions in the [Shuffle] and [Repeat] measures (IfConditions can only be used in measures, not meters or anything else) and have them produce results on the said variables, then they should be (no need to escape [Track] if you're not storing the bangs in a variable):

Code: Select all

IfCondition=(Repeat=1)
IfTrueAction=[!SetVariable Prev "Repeat On - [Track]"] [!SetVariable Next "Repeat On - [Track]"]
IfCondition2=(Shuffle=1)
IfTrueAction2=[!SetVariable Prev "Shuffle On"] [!SetVariable Next "Shuffle On"]
and be attached to a measure at the end of the measure list, say, [Track] (because of the 4. point, i.e. to make sure the values are not overwritten by another measure afterwards). By the way, referencing other changing measures or variables in the ...Action options requires having DynamicVariables=1 on the section where you attach them. Incidentally, [Track] already has that. And yes, the above will only react when toggling shuffle and repeat between on and off, see the documentation on the IfTrueAction / IfFalseAction / IfConditionMode to understand why.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
Aryx
Posts: 34
Joined: December 20th, 2023, 9:18 am

Re: Next and Previous Track's Names

Post by Aryx »

For everything - A huge thanks! Seriously! You explained all that skillfully and made it sure that someone (me - a beginner) could understand this easily! (Also, yeah I forgot that link https://docs.rainmeter.net/manual/variables/#Escape :oops: - But still I remember the explanations in the beginning - The "You escaped reading from it... this time" made sure of that :D )

As for 5 & 6, as you said in: https://forum.rainmeter.net/viewtopic.php?t=43352&start=30#p220647 Note-2, I can't parse the list itself into rainmeter, so, I just wanted to leave the complexities at the doorstep and write - Shuffle - On or Repeat - On <Some Track> in Prev and Next variables when either is on. If they are off, they should display the regular things.
But, now I think, that Repeat doesn't need something like this, so, I'll probably not keep that!

Edit: I did just that and I probably need a IfFalseAction for Shuffle one... You got that part right earlier and said it was incomplete, but, I got that right about now...
I did this:

Code: Select all

IfCondition=(Shuffle=1)
IfTrueAction=[!SetVariable Prev "Shuffle On"] [!SetVariable Next "Shuffle On"]
IfFalseAction=[!SetVariable Prev "Syncing"] [!SetVariable Next "Syncing"]
:twisted:
User avatar
Yincognito
Rainmeter Sage
Posts: 7178
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Next and Previous Track's Names

Post by Yincognito »

Aryx wrote: January 10th, 2024, 6:40 pm For everything - A huge thanks! Seriously! You explained all that skillfully and made it sure that someone (me - a beginner) could understand this easily! (Also, yeah I forgot that link https://docs.rainmeter.net/manual/variables/#Escape :oops: - But still I remember the explanations in the beginning - The "You escaped reading from it... this time" made sure of that :D )

As for 5 & 6, as you said in: https://forum.rainmeter.net/viewtopic.php?t=43352&start=30#p220647 Note-2, I can't parse the list itself into rainmeter, so, I just wanted to leave the complexities at the doorstep and write - Shuffle - On or Repeat - On <Some Track> in Prev and Next variables when either is on. If they are off, they should display the regular things.
But, now I think, that Repeat doesn't need something like this, so, I'll probably not keep that!

Edit: I did just that and I probably need a IfFalseAction for Shuffle one... You got that part right earlier and said it was incomplete, but, I got that right about now...
I did this:

Code: Select all

IfCondition=(Shuffle=1)
IfTrueAction=[!SetVariable Prev "Shuffle On"] [!SetVariable Next "Shuffle On"]
IfFalseAction=[!SetVariable Prev "Syncing"] [!SetVariable Next "Syncing"]
:twisted:
Glad you found the explanations useful - that was the whole point. :great:

Yeah, avoiding complexities is absolutely reasonable, but sooner or later, depending on the objective, things will become gradually more technical in nature, it cannot be avoided. This is why you needed to first understand how and why the basics worked in the first version of the code before progressing further or doing it differently. A good and clear foundation and structure is critical for something to work well and offer a solid base to develop things more, so indeed you can't forever "escape" getting familiar with the basics, lol.

Anyway, you did very well until now so you should be proud about it. Take it easy, step by step, and remember that the question is not so much whether this or that can or cannot be done, but rather how to do it in a satisfactory and feasible manner. Experimenting in a simpler environment is typically helpful, as well as not taking the next step until you fully understood the steps you've already taken.

As for the track list itself (if it's the file we're talking about and not some internal add to list from the player), it can actually be parsed by a Rainmeter skin assuming you know which file it's stored in and you decode that file, if necessary. In the case of Winamp, for example, the .m3u8 files that store playlists are just simple text files that can easily be parsed with WebParser. However, besides having to know which list file(s) is (are) in use and potentially their order, or what track you're currently at if controlling the playback from outside the skin, one problem is that even if you'd have that, you couldn't know the player's internal randomized list. So, such an approach would only work for a no shuffle behavior from the player, and exclusive playback control from the skin (although, technically, you could get the current track or its index in the list once you start playing, even if the playback was controlled externally beforehand; also, Rainmeter can produce random numbers to choose the next track index instead of the player, it's just that it doesn't have the ability to jump to playing that track directly, only through a long list of previouses and nexts). So, you see, like I said before, it's not the can or cannot, but the how question that needs to be answered.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth