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.
It is currently October 9th, 2024, 3:55 pm
Next and Previous Track's Names
-
- Rainmeter Sage
- Posts: 8395
- Joined: February 27th, 2015, 2:38 pm
- Location: Terra Yincognita
Re: Next and Previous Track's Names
-
- Posts: 41
- Joined: December 20th, 2023, 9:18 am
Re: Next and Previous Track's Names
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>
Edit: Wrong Code at end. [!CommandMeasure Player "Next"][!UpdateMeasure *]
-
- Rainmeter Sage
- Posts: 8395
- Joined: February 27th, 2015, 2:38 pm
- Location: Terra Yincognita
Re: Next and Previous Track's Names
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.Aryx wrote: ↑January 8th, 2024, 5:40 pmI 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?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>
Edit: Wrong Code at end. [!CommandMeasure Player "Next"][!UpdateMeasure *]
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
-
- Posts: 41
- Joined: December 20th, 2023, 9:18 am
Re: Next and Previous Track's Names
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...
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 ), 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.
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 ), 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.
-
- Posts: 41
- Joined: December 20th, 2023, 9:18 am
Re: Next and Previous Track's Names
Newer file - empty track substitutes to filename, removed refresh and uses setvariable instead of writekeyvalue.
You do not have the required permissions to view the files attached to this post.
-
- Rainmeter Sage
- Posts: 8395
- Joined: February 27th, 2015, 2:38 pm
- Location: Terra Yincognita
Re: Next and Previous Track's Names
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.
-
- Posts: 41
- Joined: December 20th, 2023, 9:18 am
Re: Next and Previous Track's Names
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 )
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):
That said, I am in no rush. I have another idea - that uses your bang way (what a banger )
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>
Weird bug (Unrelated to the post):
-
- Posts: 41
- Joined: December 20th, 2023, 9:18 am
Re: Next and Previous Track's Names
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]
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.
-
- Rainmeter Sage
- Posts: 8395
- Joined: February 27th, 2015, 2:38 pm
- Location: Terra Yincognita
Re: Next and Previous Track's Names
There is ALWAYS room for improvement if the fans go brrr and usage is up to 75%... 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.
-
- Rainmeter Sage
- Posts: 8395
- Joined: February 27th, 2015, 2:38 pm
- Location: Terra Yincognita
Re: Next and Previous Track's Names
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 )
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)
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
- 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.