It is currently February 23rd, 2024, 3:43 am

Next and Previous Track's Names

General topics related to Rainmeter.
User avatar
Yincognito
Rainmeter Sage
Posts: 6781
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Next and Previous Track's Names

Post by Yincognito »

Aryx wrote: January 8th, 2024, 3:49 pmNo, I don't have 2 different measures for the same purpose. Its [Title] actually.
Sorry, I don't follow. I never said the measures should have the same purpose, only that you should "aggregate" the desired track data in some measure and perform the OnChangeAction on that, instead of only on a part (e.g. title, artist, etc.) of it, that's all. You do as you wish though. :confused:
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 »

Code: Select all

[Title]
Measure=NowPlaying
PlayerName=[Player]
PlayerType=Title

;OnChangeAction=[!Refresh][!Delay 250][!Refresh][!ShowFade][!Delay 20000][!HideFade]
OnChangeAction=[!Refresh][!Delay 250]

[!CommandMeasure Player "Previous"][!UpdateMeasure *][!WriteKeyValue Variables Prev "[Title] - [Artist] - [Album]"][!UpdateMeasure *]
[!CommandMeasure Player "Next"][!UpdateMeasure *][!WriteKeyValue Variables Curr "[Title] - [Artist] - [Album]"][!UpdateMeasure *]
[!CommandMeasure Player "Next"][!UpdateMeasure *][!WriteKeyValue Variables Next "[Title] - [Artist] - [Album]"][!UpdateMeasure *]
[!CommandMeasure Player "Previous"][!UpdateMeasure *]

[!Refresh]


;<Prev><SavePrev #Prev#>, 
;<Next> <SaveCurr #Curr#>, 
;<Next> <SaveNext #Next#>, 
;<Prev>
I have broken up the pieces for clarity. I don't save it that way. It plays the track till the delay kicks in (I think). What did I do wrong?
Edit: Wrong Code at end. [!CommandMeasure Player "Next"][!UpdateMeasure *]
User avatar
Yincognito
Rainmeter Sage
Posts: 6781
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Next and Previous Track's Names

Post by Yincognito »

Aryx wrote: January 8th, 2024, 5:40 pm

Code: Select all

[Title]
Measure=NowPlaying
PlayerName=[Player]
PlayerType=Title

;OnChangeAction=[!Refresh][!Delay 250][!Refresh][!ShowFade][!Delay 20000][!HideFade]
OnChangeAction=[!Refresh][!Delay 250]

[!CommandMeasure Player "Previous"][!UpdateMeasure *][!WriteKeyValue Variables Prev "[Title] - [Artist] - [Album]"][!UpdateMeasure *]
[!CommandMeasure Player "Next"][!UpdateMeasure *][!WriteKeyValue Variables Curr "[Title] - [Artist] - [Album]"][!UpdateMeasure *]
[!CommandMeasure Player "Next"][!UpdateMeasure *][!WriteKeyValue Variables Next "[Title] - [Artist] - [Album]"][!UpdateMeasure *]
[!CommandMeasure Player "Previous"][!UpdateMeasure *]

[!Refresh]


;<Prev><SavePrev #Prev#>, 
;<Next> <SaveCurr #Curr#>, 
;<Next> <SaveNext #Next#>, 
;<Prev>
I have broken up the pieces for clarity. I don't save it that way. It plays the track till the delay kicks in (I think). What did I do wrong?
Edit: Wrong Code at end. [!CommandMeasure Player "Next"][!UpdateMeasure *]
My bad, I think I missed one key detail in doing these things in the OnChangeAction of such a measure: the said option will react when the value of the measure it is attached to changes, BUT, very important, commanding the player to all these previous and next events itself triggers again the OnChangeAction, so in effect, an endless loop is created. E.g. the first "normal" OnChangeAction leads to commanding bang jumps, the bang jumps lead to another OnChangeAction, this OnChangeAction leads to another series of bang jumps, those bangs lead to another OnChangeAction, and so on forever.

The above issue can be solved by only running these commanding bangs a single time, right after clicking to change the track, and revert to no action otherwise. This is slightly more complex in nature, though easy to understand once you get familiar with the techniques. So, to do that, you can:
- save the bangs as variables whose names end in an "index" number, see the BangsN variables below (to have these bangs stored literally, without Rainmeter attempting to replace whatever contained variables or measures with their values, you'd have to escape such occurrences in the said bangs)
- use another variable storing the current "index", see the BangsIndex variable below (this variable will be used as part of the name of the BangsN variables, via nesting)
- on click, briefly changing the BangsIndex variable so that the proper BangsN (Bangs1 here) run once, followed by reverting it to normal (reset it to 0) in the same BangsN to avoid triggering the commanding bangs again (the OnChangeAction will simply "execute" the proper BangsN variable, so either Bangs1 to get data or Bangs0 to do nothing)

I've applied the above along with a [Track] measure holding the desired track data to my earlier simpleton code, for easier understanding - feel free to change or apply to your skin, after noticing the differences:

Code: Select all

[Variables]
PlayerName=Winamp
Prev=
Curr=
Next=

BangsIndex=0
Bangs0=[]
Bangs1=[!SetVariable BangsIndex 0][!CommandMeasure Player "Previous"][!UpdateMeasure *][!SetVariable Prev "[*Track*]"][!CommandMeasure Player "Next"][!UpdateMeasure *][!SetVariable Curr "[*Track*]"][!CommandMeasure Player "Next"][!UpdateMeasure *][!SetVariable Next "[*Track*]"][!CommandMeasure Player "Previous"][!UpdateMeasure *][!UpdateMeter *][!Redraw]

[Rainmeter]
Update=1000
AccurateText=1
DynamicWindowSize=1
BackgroundMode=2
SolidColor=0,255,0,255

---Measures---

[Player]
Measure=NowPlaying
PlayerName=#PlayerName#
PlayerType=State

[Repeat]
Measure=NowPlaying
PlayerName=[Player]
PlayerType=Repeat

[Shuffle]
Measure=NowPlaying
PlayerName=[Player]
PlayerType=Shuffle

[Artist]
Measure=NowPlaying
PlayerName=[Player]
PlayerType=Artist

[Title]
Measure=NowPlaying
PlayerName=[Player]
PlayerType=Title

[Album]
Measure=NowPlaying
PlayerName=[Player]
PlayerType=Album

[Progress]
Measure=NowPlaying
PlayerName=[Player]
PlayerType=Progress
MinValue=0
MaxValue=100

[File]
Measure=NowPlaying
PlayerName=[Player]
PlayerType=File
RegExpSubstitute=1
Substitute="^(.*)\\(.*)\.(.*)$":"\2"

[Track]
Measure=String
String=[Title] - [Artist] - [Album]
RegExpSubstitute=1
Substitute="(?:^ - .*$|^.* - *- .*$|^.* - $)":"[File]"
OnChangeAction=[#Bangs[#BangsIndex]]
DynamicVariables=1

---Meters---

[Prev]
Meter=String
Y=10R
AntiAlias=1
Text=Prev: #Prev#
LeftMouseUpAction=[!SetVariable BangsIndex 1][!CommandMeasure Player "Previous"]
DynamicVariables=1

[Curr]
Meter=String
Y=10R
AntiAlias=1
Text=Curr: #Curr#
LeftMouseUpAction=[!CommandMeasure Player "PlayPause"][!UpdateMeasure *][!SetVariable Curr "[Track]"][!UpdateMeter *][!Redraw]
MiddleMouseUpAction=[!CommandMeasure Player "Stop"]
DynamicVariables=1

[Next]
Meter=String
Y=10R
AntiAlias=1
Text=Next: #Next#
LeftMouseUpAction=[!SetVariable BangsIndex 1][!CommandMeasure Player "Next"]
DynamicVariables=1
So, the bangs themselves are more or less the same as you tried (I have the feeling you abuse !Refresh though, many times things can be done in the same loading session by setting variables in memory too, updating stuff and redrawing, even if you !WriteKeyValue things). Only the things pertaining to avoiding an endless loop and an aggregated track measure are added, but you can place your OnChangeAction in the Title measure if you really want that (despite the potential inaccuracy).
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 »

First off - I made a huge/tiny (depends on your point of view) mistake when I asked to automatically write the name in next and previous by OnChangeAction - When the action is firstly executed, it leads to execution of second OnChangeAction and so on - yeah an endless loop. Got that before reading your post - came here to say that... :oops:

Second off (does anyone say this) - No, I don't abuse !Refresh - I don't know why you think so. I used WriteKeyValue Variables instead of SetVariables. I had to refresh manually each time, so, I wrote !Refresh when it changed for auto-execution. Do I have to use SetVariable, if yes, then I'll revert back to the old code with the same.

Third off (damn! I never heard this in my entire life) - What is the last piece of code supposed to do? It works the same as the first one, but has shorter pieces of codes in parts with bang0 and bang1. I get what you wrote in the info part, but, it does not change automatically for me.

Fourth off (now, I wish I used the numbers) - I already applied the filename thing in the newer part of the skin (although, I firstly mistook it for a meter and began to clear the errors :rofl: ), still, thank you, I noticed that difference.

In case I wrote something wrong earlier, here's a modified short version -

WHEN TRACK CHANGES - RE-WRITE NEW NEXT AND PREVIOUS TRACKS <Edit:> WITHOUT CLICKING.
Aryx
Posts: 34
Joined: December 20th, 2023, 9:18 am

Re: Next and Previous Track's Names

Post by Aryx »

Newer file - empty track substitutes to filename, removed refresh and uses setvariable instead of writekeyvalue.
b.ini
You do not have the required permissions to view the files attached to this post.
User avatar
Yincognito
Rainmeter Sage
Posts: 6781
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Next and Previous Track's Names

Post by Yincognito »

Aryx wrote: January 9th, 2024, 9:42 amWHEN TRACK CHANGES - RE-WRITE NEW NEXT AND PREVIOUS TRACKS <Edit:> WITHOUT CLICKING.
Ah, I see - you want to do this automatically when the track finishes playing and changes from one to another without user intervantion. I didn't check your posted file yet, but just so I know, did you suceed in making it work correctly or not? I'll answer this later on, got some things to do in the meantime.
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 »

No, I did not succeed in making a skin capable of changing the variables automatically - without human intervention. The newer file only has the updates (comparing with the c.ini file posted earlier) written in the post - none other than that.

That said, I am in no rush. I have another idea - that uses your bang way (what a banger :rolmfao: )

Code: Select all

Bang0=[]
Bang1=<same as changing the track to the next one manually - Next meter>
Bang2=<same as chngging the track to the prev one manually - Prev meter>
Bang3=<same as curr track writing - something that is automatic!>
Bang4=<optional - as the middlemouseupaction in ProgressStatus>
Using the above in same way you used in your latest post. Also, is bang0 correctly written? Is it empty? What is its function?

Weird bug (Unrelated to the post):
Just noticed this one thing - While I use AIMP as PlayerName, the skin displays 2 instances of 1 track

If Next clicked, the current track is displayed in Previous; The track being played earlier is displayed in Now and Next both.
If Prev clicked, the current track is displayed in Next; The track being played earlier is displayed in Now and Prev both.

This however is not a problem when I use Winamp as Playername and use either AIMP or WINAMP.
Aryx
Posts: 34
Joined: December 20th, 2023, 9:18 am

Re: Next and Previous Track's Names

Post by Aryx »

Code: Select all

[Rainmeter] 
OnRefreshAction=[!SetVariable Curr "[Title] - [Artist] - [Album]"][!CommandMeasure Player "Previous"][!UpdateMeasure *][!SetVariable Prev "[Title] - [Artist] - [Album]"][!CommandMeasure Player "Next"][!CommandMeasure Player "Next"][!UpdateMeasure *][!SetVariable Next "[Title] - [Artist] - [Album]"][!CommandMeasure Player "Previous"][!CommandMeasure Player "Previous"][!CommandMeasure Player "Next"][!UpdateMeasure *]

[Title]
OnChangeAction=[!Refresh]
The above should to work, but seems to make the fans go brrrr! No, seriously the rainmeter usage went up to 75% and increased even more... But writes everything as it should... So, is there any room for improvement in this?

I know Next-Prev-Prev-Next is not an ideal thing, but Next-Prev does not work somehow.... also, the middle-click code is flawed - i now know it.
User avatar
Yincognito
Rainmeter Sage
Posts: 6781
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Next and Previous Track's Names

Post by Yincognito »

Aryx wrote: January 9th, 2024, 11:48 amThe above should to work, but seems to make the fans go brrrr! No, seriously the rainmeter usage went up to 75% and increased even more... But writes everything as it should... So, is there any room for improvement in this?
There is ALWAYS room for improvement if the fans go brrr and usage is up to 75%... :o I'll take a look at it soon, but you know already, I prefer to keep the process simple for clarity and debugging, so you'll probably want to adapt things to your case. ;-)
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
Yincognito
Rainmeter Sage
Posts: 6781
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Next and Previous Track's Names

Post by Yincognito »

Aryx wrote: January 9th, 2024, 11:04 am 1) No, I did not succeed in making a skin capable of changing the variables automatically - without human intervention.
2) That said, I am in no rush. I have another idea - that uses your bang way (what a banger :rolmfao: )
3) Using the above in same way you used in your latest post. Also, is bang0 correctly written? Is it empty? What is its function?
4) Weird bug (Unrelated to the post)
Aryx wrote: January 9th, 2024, 11:48 am 5) So, is there any room for improvement in this?
3) Yes, Bang0=[] is the empty bang ([]) and is correctly written. It basically does nothing. Alternatively, I guess you could declare it like Bang0=. I chose the square bracket form to make it clear that it's used as a bang, that's all.

As promised, 1), 2) and 5) led to the below, which I think functions correctly and is as light as it should be on the CPU (for my Winamp at least - not sure what the "bug" at 4) or your other experiments could be about since I don't use AIMP and didn't try them):

Code: Select all

[Variables]
PlayerName=WINAMP
FontName=Consolas
FontSize=11
FontColorN=0,0,0,55
FontColor=255,255,255,255
PreSym=⏪
PreText=Previously
CurrSym=🎵
CurrText=Now Playing
NextSym=⏩
NextText=Coming Up

Track=[Title] - [Artist] - [Album]
BangIndex=1
Bang0=[]
Bang1=[!SetVariable BangIndex 0][!CommandMeasure Player "Previous"][!UpdateMeasure *][!SetVariable Prev "[*Track*]"][!CommandMeasure Player "Next"][!UpdateMeasure *][!SetVariable Curr "[*Track*]"][!CommandMeasure Player "Next"][!UpdateMeasure *][!SetVariable Next "[*Track*]"][!CommandMeasure Player "Previous"][!UpdateMeasure *][!UpdateMeter *][!Redraw][!SetVariable BangIndex 1]
BangR=[#Bang1][&Progress]
Prev=
Curr=
Next=

[Rainmeter]
Update=1000
AccurateText=1
DynamicWindowSize=1
OnRefreshAction=[#BangR]

---Measures---

[Device]
Measure=Plugin
Plugin=Win7AudioPlugin

[Volume]
Measure=Calc
Formula=Device
RegExpSubstitute=1
Substitute="^-1$":"Mute"

[Player]
Measure=NowPlaying
PlayerName=#PlayerName#
PlayerType=State

[Repeat]
Measure=NowPlaying
PlayerName=[Player]
PlayerType=Repeat
Substitute="0":"Off","1":"On"

[Shuffle]
Measure=NowPlaying
PlayerName=[Player]
PlayerType=Shuffle
Substitute="0":"Off","1":"On"

[Progress]
Measure=NowPlaying
PlayerName=[Player]
PlayerType=Progress
MinValue=0
MaxValue=100
RegExpSubstitute=1
Substitute="^(.*)$":'[!CommandMeasure Player "SetPosition \1"]'

[Title]
Measure=NowPlaying
PlayerName=[Player]
PlayerType=Title

[Artist]
Measure=NowPlaying
PlayerName=[Player]
PlayerType=Artist

[Album]
Measure=NowPlaying
PlayerName=[Player]
PlayerType=Album

[File]
Measure=NowPlaying
PlayerName=[Player]
PlayerType=File

[Track]
Measure=String
String=#Track#
RegExpSubstitute=1
Substitute="(?:^ - .*$|^.* - *- .*$|^.* - $)":"[File]","^(.*)\\(.*)\.(.*)$":"\2"
OnChangeAction=[#Bang[#BangIndex]]
DynamicVariables=1

---Meters---

[Container]
Meter=Shape
X=4
Y=4
W=600
H=110
Shape=Rectangle ([Container:X]),([Container:Y]),([Container:W]),([Container:H]),8 | Fill Color 0,0,0,255 | StrokeWidth 0
DynamicVariables=1

[Background]
Meter=Shape
Shape=Rectangle ([Container:X]),([Container:Y]),([Container:W]),([Container:H]),8 | Fill Color #FONTCOLORN# | StrokeWidth 2 | StrokeColor #FONTCOLOR#

[Prev]
Meter=String
Container=Container
X=8
Y=8R
W=[Background:W]
FontFace=#FONTNAME#
FontColor=#FONTCOLOR#
FontSize=#FONTSIZE#
ClipString=1
AntiAlias=1
Text=#PreSym# #PreText#	: #Prev#
LeftMouseUpAction=[!SetVariable BangIndex 1][!CommandMeasure Player "Previous"][!UpdateMeasure *]
MouseScrollUpAction=[!SetVariable BangIndex 1][!CommandMeasure Player "Previous"][!UpdateMeasure *]
MouseScrollDownAction=[!SetVariable BangIndex 1][!CommandMeasure Player "Next"][!UpdateMeasure *]
DynamicVariables=1

[Curr]
Meter=String
Container=Container
X=8
Y=7R
W=[Background:W]
FontFace=#FONTNAME#
FontColor=#FONTCOLOR#
FontSize=#FONTSIZE#
ClipString=1
AntiAlias=1
Text=#CurrSym# #CurrText#	: #Curr#
LeftMouseUpAction=[!CommandMeasure Player "PlayPause"][!UpdateMeasure *]
MouseScrollUpAction=[!SetVariable BangIndex 1][!CommandMeasure Player "Previous"][!UpdateMeasure *]
MouseScrollDownAction=[!SetVariable BangIndex 1][!CommandMeasure Player "Next"][!UpdateMeasure *]
DynamicVariables=1

[Next]
Meter=String
Container=Container
X=8
Y=4R
W=[Background:W]
FontFace=#FONTNAME#
FontColor=#FONTCOLOR#
FontSize=#FONTSIZE#
ClipString=1
AntiAlias=1
Text=#NextSym# #NextText#	: #Next#
LeftMouseUpAction=[!SetVariable BangIndex 1][!CommandMeasure Player "Next"][!UpdateMeasure *]
MouseScrollUpAction=[!SetVariable BangIndex 1][!CommandMeasure Player "Previous"][!UpdateMeasure *]
MouseScrollDownAction=[!SetVariable BangIndex 1][!CommandMeasure Player "Next"][!UpdateMeasure *]
DynamicVariables=1

[ShuffleStatus]
Meter=String
Container=Container
X=20
Y=([Next:Y]+[Next:H]+4)
W=([Background:W]/4)
FontFace=#FONTNAME#
FontColor=#FONTCOLOR#
FontSize=#FONTSIZE#
Text=Shuffle: [Shuffle]
AntiAlias=1
LeftMouseUpAction=[!CommandMeasure Player "SetShuffle -1"][!UpdateMeasure *][!UpdateMeter ShuffleStatus][!Redraw]
DynamicVariables=1

[RepeatStatus]
Meter=String
Container=Container
X=([RepeatStatus:W]+[ShuffleStatus:X])
Y=([Next:Y]+[Next:H]+4)
W=([Background:W]/4)
FontFace=#FONTNAME#
FontColor=#FONTCOLOR#
FontSize=#FONTSIZE#
Text=Repeat: [Repeat]
AntiAlias=1
LeftMouseUpAction=[!CommandMeasure Player "SetRepeat -1"][!UpdateMeasure *][!UpdateMeter RepeatStatus][!Redraw]
DynamicVariables=1

[VolumeStatus]
Meter=String
Container=Container
X=([RepeatStatus:W]+[ShuffleStatus:X]+[ShuffleStatus:W]+12)
Y=([Next:Y]+[Next:H]+4)
W=([Background:W]/4)
FontFace=#FONTNAME#
FontColor=#FONTCOLOR#
FontSize=#FONTSIZE#
Text=Volume: [Volume]
AntiAlias=1
LeftMouseUpAction=[!CommandMeasure Device "ToggleMute"][!UpdateMeasure *][!UpdateMeter VolumeStatus][!Redraw]
MouseScrollUpAction=[!CommandMeasure Device "ChangeVolume +2"][!UpdateMeasure *][!UpdateMeter VolumeStatus][!Redraw]
MouseScrollDownAction=[!CommandMeasure Device "ChangeVolume -2"][!UpdateMeasure *][!UpdateMeter VolumeStatus][!Redraw]
DynamicVariables=1

[ProgressStatus]
Meter=String
Container=Container
X=(([Background:W])-([Background:W]/4)+8)
Y=([Next:Y]+[Next:H]+4)
W=([Background:W]/4-8)
FontFace=#FONTNAME#
FontColor=#FONTCOLOR#
FontSize=#FONTSIZE#
AntiAlias=1
Text=Progress: [Progress:%,1]%
LeftMouseUpAction=[!CommandMeasure Player "Stop"][!CommandMeasure Player "Play"][!UpdateMeasure *]
MouseScrollUpAction=[!CommandMeasure Progress "SetPosition +2"][!UpdateMeasure *][!UpdateMeter ProgressStatus][!Redraw]
MouseScrollDownAction=[!CommandMeasure Progress "SetPosition -2"][!UpdateMeasure *][!UpdateMeter ProgressStatus][!Redraw]
MiddleMouseUpAction=[#Bang1]
DynamicVariables=1
There are multiple changes I made, so I'll just list them:
- added a Track variable where you can set whether you want just the title and artist or the album as well to be returned by the Track measure (this way, you don't have to change in a thousand places when you want a different return)
- continued to use Bang0 and Bang1 (Bang1 is the sole bang for getting track data in advance now, got rid of the rest), but added a little hack in BangR where, because of the commanding bangs in Bang1 reset the track position on jumping, I restore it by "executing" the string value of the Progress measure in the OnRefreshAction (just watch the string value of that measure in the About > Skins tab and you'll understand what I mean; it's not perfect, but it's as good as it gets)
- set Update to 1000, it doesn't make any sense for it to be lower since the NowPlaying data is not retrieved at a frequency of less than 1 second anyway (this will slightly help with lowering the CPU usage too)
- added the ability to display the "Mute" text instead of "-1" on toggling the mute status, in the Volume measure
- aggregated sustitutions in the Track measure (by the way, the order of measures and meters is important, so the Artist measure should have been before the Track measure in your b.ini code in order for the latter to get the current value of the former properly)
- cleaned the code a bit, shuffled the order of some options, made stuff more compact (this one was just cosmetics, no functional purpose at all)

Notes:
- No, you can't workaround the couple of milliseconds when you hear the start of other songs when using the commanding bangs above. Regardless of the value of Update, there will always be a slight delay between the start of the song and Rainmeter getting the NowPlaying data or performing the OnChangeAction. Here, it pays off to have tracks where the music doesn't start right away and doesn't end abruptly - a possible alternative would be to configure the player to use a bit of fading in/out the sound when changing tracks though.
- One other thing neither of us considered when pursuing the OnChangeAction approach is that the skin will take exclusive control of playing when Shuffle in On. This means that if you try to play some track from your player with the skin loaded, it won't work. This is because the commanding bangs are jumping to tracks from the internal randomized list used by the player when getting the previous and next of them in advance. The solution is to temporarily toggle Shuffle to Off, and change the tracks from the player as desired. Of course, if toggling the Shuffle to On afterwards, the previous and next tracks won't be properly set back to the shuffled ones until the track is changed again (either by re-starting play, the track ending, or otherwise). But then, these are the drawbacks of a hack like this is, so it is what it is.

Feel free to ask if you don't understand something from the above, or further adjust the code to your preference. ;-)
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth