It is currently March 28th, 2024, 2:32 pm

Reading from Rainmeter.ini or other .ini

Get help with creating, editing & fixing problems with skins
User avatar
Codger
Posts: 97
Joined: May 29th, 2017, 3:16 pm

Reading from Rainmeter.ini or other .ini

Post by Codger »

I found the WriteKey bang and a ReadKey lua snippet.
But I have no idea how to interface lua code in a rainmeter skin.

What I want to do is find the X, Y and Active values of another skin.
Can someone help, making as few assumptions as possible as I have zero knowledge of lua or making them work together. I just want to get those three values loaded into variables. Thanks.

Currently in the air headed to a layover in Seoul, so don't start the war yet. :jokepoortaste:
Cougar Draven
Posts: 8
Joined: May 28th, 2017, 9:15 pm

Re: Reading from Rainmeter.ini or other .ini

Post by Cougar Draven »

User avatar
Codger
Posts: 97
Joined: May 29th, 2017, 3:16 pm

Re: Reading from Rainmeter.ini or other .ini

Post by Codger »

You'd think that but this ageing brain learns better for one complete example. Then I can extrapolate next time.

So I have the snippet from the manual:

Code: Select all

function ReadIni(inputfile)
	local file = assert(io.open(inputfile, 'r'), 'Unable to open ' .. inputfile)
	local tbl, section = {}
	local num = 0
	for line in file:lines() do
		num = num + 1
		if not line:match('^%s-;') then
			local key, command = line:match('^([^=]+)=(.+)')
			if line:match('^%s-%[.+') then
				section = line:match('^%s-%[([^%]]+)'):lower()
				if not tbl[section] then tbl[section] = {} end
			elseif key and command and section then
				tbl[section][key:lower():match('^s*(%S*)%s*$')] = command:match('^s*(.-)%s*$')
			elseif #line > 0 and section and not key or command then
				print(num .. ': Invalid property or value.')
			end
		end
	end
	if not section then print('No sections found in ' .. inputfile) end
	file:close()
	return tbl
end
Which try as I might (way too many hours on three planes) is largely gibberish to me.

All I want is a Measure that takes a skin name and returns the value for the key Active of that skin from Rainmeter.ini.
Perhaps a -1 if the skin isn't in Rainmeter.ini

Your time is appreciated.
User avatar
balala
Rainmeter Sage
Posts: 16109
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Reading from Rainmeter.ini or other .ini

Post by balala »

Codger wrote:All I want is a Measure that takes a skin name and returns the value for the key Active of that skin from Rainmeter.ini.
Here is a solution: first create a MyScript.lua file, in the @Resource folder. Add the following code:

Code: Select all

function ReadIni(inputfile)
	local file = assert(io.open(inputfile, 'r'), 'Unable to open ' .. inputfile)
	local tbl, section = {}
	local num = 0
	for line in file:lines() do
		num = num + 1
		if not line:match('^%s-;') then
			local key, command = line:match('^([^=]+)=(.+)')
			if line:match('^%s-%[.+') then
				section = line:match('^%s-%[([^%]]+)')
				if not tbl[section] then tbl[section] = {} end
			elseif key and command and section then
				tbl[section][key:match('^s*(%S*)%s*$')] = command:match('^s*(.-)%s*$')
			elseif #line > 0 and section and not key or command then
				print(num .. ': Invalid property or value.')
			end
		end
	end
	if not section then print('No sections found in ' .. inputfile) end
	file:close()
	return tbl
end

function SetVarVal(Section, Variable)
	local iniTable = ReadIni(SKIN:GetVariable('SETTINGSPATH')..'Rainmeter.ini')	
	return iniTable[Section][Variable]
end

function Update()
	Section = SELF:GetOption('ConfigName')
	Parameter = SELF:GetOption('ParameterName')
	return SetVarVal(Section, Parameter)
end
I took the ReadIni file from the Rainmeter Snippets (as I think you also did). I also used this post.
The Script measure of your skin, must have a ConfigName and a ParameterName option. ConfigName is the name of the config (section of Rainmeter.ini) you'd like to read (eg Gmail, if you have a such config name) and ParameterName is the name of the desired parameter (like WindowX, to read the horizontal position of the skin on the screen). If both options are given properly, the following Script measure will return the appropriate value:

Code: Select all

[MeasureLuaScript]
Measure=Script
ScriptFile=#@#MyScript.lua
ConfigName=Gmail
ParameterName=WindowX
Note that you can add a "Default" parameter to both SELF:GetOption commands of the above script. If you do so and if the used ConfigName or ParameterName options are missing, the Script will use this default value:

Code: Select all

	Section = SELF:GetOption('ConfigName', 'MyDefaultConfigName')
	Parameter = SELF:GetOption('ParameterName', 'WindowX')
To use the returned value in your skin, you have to read the value of the script measure:

Code: Select all

[MeterParameter]
Meter=STRING
MeasureName=MeasureLuaScript
X=0
Y=0
Padding=15,5,15,5
FontColor=220,220,220
SolidColor=0,0,0,150
FontSize=8
FontFace=Segoe UI
StringStyle=BOLD
StringAlign=LEFT
AntiAlias=1
Text=Returned parameter: %1
Obviously you can add more different Script measures, each with different ConfigName and ParameterName. In such cases, each of them will return the appropriate read value.
I hope you can handle all this, please let me know if you have any problem.
User avatar
Codger
Posts: 97
Joined: May 29th, 2017, 3:16 pm

Re: Reading from Rainmeter.ini or other .ini

Post by Codger »

Bless you! Not only was that the routines I needed but it was presented in a way that I feel I understand a lot of what is going on. I learn whether that is true or not when I try to adapt it :)

Thank you for your time and excellent presentation.
User avatar
balala
Rainmeter Sage
Posts: 16109
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Reading from Rainmeter.ini or other .ini

Post by balala »

Codger wrote:Bless you! Not only was that the routines I needed but it was presented in a way that I feel I understand a lot of what is going on. I learn whether that is true or not when I try to adapt it :)

Thank you for your time and excellent presentation.
You're welcome. And me also thank you for your kind words. Means a lot.
User avatar
Codger
Posts: 97
Joined: May 29th, 2017, 3:16 pm

Re: Reading from Rainmeter.ini or other .ini

Post by Codger »

balala wrote:You're welcome. And me also thank you for your kind words. Means a lot.
I'm glad. You are doing a fantastic job.
I'm slower than usual today. It's frustrating because I have so little retention. The last three days off from this have cost me dearly in hard fought knowledge. And now I'm stuck. Again :confused: :handtohead:

BTW: This is completely separate from the Thailand project. This is just me seeing what this brain can still do.
My usual plan of attack is to have a launching point, then get a piece working. They get it all working. Then rewrite the whole thing in a more logical orderly fashion. I'm deeply stuck at step 2.

This is a simple little thing (I thought). I have a bunch of little square widgets based on the width and color of the small size Win 10 Widgets skins. What I'm trying to build is a little button (that may become a frame later on) that makes the individual skins drag with the mouse and line up.

To my eye this code should make the top widget follow the button. I don't think even the first action is firing.
I know there are probably a dozen ways to do it better, but that is step 4. Right now I just would love to be unstuck. Shown the ## I forget or the [] I should or should not have used. Etc. Help!! But just debug help.

The .lua is exactly what you gave me early with only the name change.

This is the code: (RackMaster2)

Code: Select all

[Rainmeter]
Update=1000
AccurateText=1
MiddleMouseDownAction=!RainmeterDeactivateConfig
;LeftMouseDownAction=[!Enable StackSkins][!Update StackSkins]
Group=RackMaster

[Metadata]
Name=RackMaster2
Author=Codger
Information=
Version=0.0.1
License=Creative Commons Attribution - Non - Commercial - Share Alike 3.0

[Variables]
@include=#@#Common.inc
CRadius=7
CBorder=4

MasterX = #CURRENTCONFIGX#
MasterY = #CURRENTCONFIGY#
LastX = #CURRENTCONFIGX#
LastY = #CURRENTCONFIGY#

[Background]
Meter=Shape
X=(#CRadius#+2)
Y=(#CRadius#+2)
Shape=Rectangle X,Y,(#CRadius#*3),(#CRadius#*4),10 | Extend MyModifiers1
MyModifiers1=Fill Color #MediumGrey#,160 | StrokeWidth #CBorder# | Stroke Color #MediumGrey#,222
UpdateDivider=-1


[RackSymbol]
Meter=String
X=(#CRadius#+4)
Y=(#CRadius#+5)
FontFace=WingDings
FontColor=#PureYellow#,240
FontSize=(#CRadius#*2+1)
StringStyle = Bold
Text=T
;❄︎
UpdateDivider=-1

[DidRackMove]
Measure=String
IfCondition=(#LastX# = #CURRENTCONFIGX#) && (#LastY# = #CURRENTCONFIGY#)
IfFalseAction=[!UpdateMeasure SetRackTop][!UpdateMeasure MeasureHardDriveUsageBarCActive][!Updategroup RackMaster]
DynamicVariables=1

[SetRackTop]
Measure=String
LastX = #MasterX#
LastY = #MasterY#
MasterX = (#CURRENTCONFIGX#+10)
MasterY = #CURRENTCONFIGY#
DynamicVariables=1
UpdateDivider=-1

[MeasureHardDriveUsageBarCActive]
Measure=Script
ScriptFile=#@#ReadIni.lua
ConfigName=Codger\HardDriveBar\HardDriveUsageBarC
ParameterName=Active

[MeasureSetBottomHardDriveUsageBarCInRack]
Measure=String
#MasterY# = (#MasterY# + 58)
DynamicVariables=1
UpdateDivider=-1

[MeasureSetHardDriveUsageBarCInRack]
Meter=STRING
MeasureName=MeasureHardDriveUsageBarCActive
IfAboveValue=0
IfAboveAction=[!WriteKeyValue  Codger\HardDriveBar\HardDriveUsageBarC WINDOWX #MasterX# "#SETTINGSPATH#Rainmeter.ini"][!WriteKeyValue  Codger\HardDriveBar\HardDriveUsageBarC WINDOWY #MasterY# "#SETTINGSPATH#Rainmeter.ini"][!UpdateMeasure MeasureSetBottomHardDriveUsageBarCInRack][!UpdateMeasure MeasureSetBottomHardDriveUsageBarCInRack]
UpdateDivider=-1

/*

[MeterRack]
Meter=Image

;[Win10 Widgets\WiFi]
;[Codger\CPU]
;;[Codger\HardDriveBar\HardDriveUsageBarC]
;[Codger\HardDriveBar\HardDriveUsageBarD]
;[Codger\HardDriveBar\HardDriveUsageBarJ]
;[Codger\HardDriveBar\HardDriveUsageBarK]
;[Codger\HardDriveBar\HardDriveUsageBarL]
;[Codger\Traffic]
;[Win10 Widgets\Volume]
*/

;!WriteKeyValue Variables MyFontName Arial "#@#Variables.inc"
And this is the referenced Widget: (HardDriveUsageBarC.ini)

Code: Select all

; Change Last Letter in Name (Line 14)
; Change Value of HD to Drive Letter (Line 22)
; Change Value of IgnoreRemovableSetting to 1 if USB drive (Line 23)
; Then save as skin as named in Name=
; Make as many as needed

[Rainmeter]
Update=1000
AccurateText=1
MiddleMouseDownAction=!RainmeterDeactivateConfig
Group=RackMaster

[Metadata]
Name=HardDriveUsageBarC
Author=Codger
Information=Create Multiple Stackable Drives by creating copies of this skin.
Version=1.0.1
License=Creative Commons Attribution - Non - Commercial - Share Alike 3.0

[Variables]
; Change This to Drive Letter
HD="C:"
IgnoreRemovableSetting=0
;set to 1 if removable drive
UpdatePeriod = 300
; Update every 5 minutes

@include=#CURRENTPATH#..\HardDriveBar.inc
Which requires: (HardDriveBar.inc)

Code: Select all

[Variables]
@include=#@#Common.inc
BackHeight=56

[MeasureHardDrive]
Measure=FreeDiskSpace
Drive="#HD#"
IgnoreRemovable=#IgnoreRemovableSetting#
InvertMeasure=1
OnUpdateAction=[!UpdateMeasure MeasureHardDriveLabel][!UpdateMeasure MeasureFreeSpace][!UpdateMeter Background][!UpdateMeter "Bar Background"][!UpdateMeter MeterBar][!UpdateMeter MeterHardDriveLabel][!UpdateMeter MeterHardDrive][!UpdateMeter MeterFreeSpace][!Redraw]
UpdateDivider=#UpdatePeriod#

[MeasureHardDriveLabel]
Measure=FreeDiskSpace
Drive="#HD#"
IgnoreRemovable=#IgnoreRemovableSetting#
Label=1
UpdateDivider=-1

[MeasureFreeSpace]
Measure=FreeDiskSpace
Drive="#HD#"
IgnoreRemovable=#IgnoreRemovableSetting#
UpdateDivider=-1

[Background]
Meter=Shape
Shape=Rectangle 0,0,(#BarWidth# + (#BackPadding#*2) + 1),#BackHeight# | Fill Color #BackColor# | StrokeWidth 1 | Stroke Color #BackBorder#
UpdateDivider=-1

[Bar Background]
Meter=Image
X=#BackPadding#
Y=28
H=5
W=#BarWidth#
SolidColor=#PureWhite#,100
UpdateDivider=-1

[MeterBar]
Meter=BAR
MeasureName=MeasureHardDrive
X=#BackPadding#
Y=28
H=5
W=#BarWidth#
BarColor=#PureWhite#,255
BarOrientation=Horizontal
UpdateDivider=-1

[MeterHardDriveLabel]
MeasureName=MeasureHardDriveLabel
Meter=STRING
X=#BackPadding#
Y=9
FontFace=#FontFace#
FontColor=#FontColor#
FontSize=#FontSize#
AntiAlias=1
StringCase=Upper
LeftMouseUpAction=!execute [#HD#/]
UpdateDivider=-1

[MeterDriveLetter]
Meter=String
X=(#BackPadding#+#BarWidth#)
Y=9
FontFace=#FontFace#
FontColor=#FontColor#
FontSize=#FontSize#
AntiAlias=1
StringCase=Upper
StringAlign = Right
Text = #HD#
LeftMouseUpAction=!execute [#HD#/]
UpdateDivider=-1

[MeterHardDrive]
Meter=String
MeasureName=MeasureHardDrive
FontFace=#FontFace#
FontColor=#FontColor#
FontSize=#FontSize#
AntiAlias=1
MinValue=0
MaxValue=100
Text=%1% Used
X=#BackPadding#
Y=38
Percentual=1
LeftMouseUpAction=!execute [#HD#/]
UpdateDivider=-1

[MeterFreeSpace]
Meter=String
MeasureName=MeasureFreeSpace
X=(#BackPadding#+#BarWidth#)
Y=38
FontFace=#FontFace#
FontColor=#FontColor#
FontSize=#FontSize#
AntiAlias=1
StringAlign = Right
AutoScale=1k
Text = "%1  Free"
LeftMouseUpAction=!execute [#HD#/]
UpdateDivider=-1
Which requires this from @resources (common.inc)

Code: Select all

[Variables]
; Static Variables
BackPadding=15
BarWidth=330
BackColor=25,25,25,200
BackBorder=255,255,0,50

PureBlue=0,0,255
PureRed=255,0,0
PureGreen=0,255,0
PureYellow=255,255,0
PureWhite=255,255,255
BurntOrange=153,76,0
MediumOrange=255,128,0
RedOrange=255,51,51
DarkGreen=0,102,0
MediumGrey=25,25,25
PureWhite=255,255,255

FontFace=Microsoft Sans Serif
FontColor=#PureWhite#,240
FontSize=10

Phew. Probably should have just made a fake mockup for the second widget. The name and the group line is the only thing of importance.

Any help would be greatly appreciated.
User avatar
balala
Rainmeter Sage
Posts: 16109
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Reading from Rainmeter.ini or other .ini

Post by balala »

Codger wrote:BTW: This is completely separate from the Thailand project. This is just me seeing what this brain can still do.
Not very sure what the Thailand project is, but probably it doesn't even have an importance.

It's very hard to follow everything, as you've posted the above codes. So, for first, I'll tell just a few general things about them:
  • What the [SetRackTop] section of the main code, want to be? It's not a measure, it's not a meter, so what you wanted to achieve with it? In Rainmeter, such sections can't be used. The options posted under it, are "orphans".
  • Same is the #MasterY# = (#MasterY# + 58) option of the [MeasureSetBottomHardDriveUsageBarCInRack] measure, which I also can't understand.
  • The IfActions (as well as the IfConditions and IfMatches) can't be applied to meters. They belong to measures. You've used an IfAboveValue and the appropriate IfAboveAction, on the [MeasureSetHardDriveUsageBarCInRack] meter (which despite of its name, is a meter, having a Meter=STRING option). So, the bangs included into the IfAboveAction option won't be executed never.
  • Usually is not a very good idea to use spaces into any section name. Maybe it's not completely prohibited, but definitely neither a good habit isn't. I'm talking about the [Bar Background] meter name, used into the code of the HardDriveBar.inc file.
  • I'm again not very sure what you wanted to achieve with the @include=#CURRENTPATH#..\HardDriveBar.inc option, used into the HardDriveUsageBarC.ini file. You wanted to make a step above and include the HardDriveBar.inc file, which is located into the root folder of the current one? If yes, replace this option with @include=..\HardDriveBar.inc (without the #CURRENTPATH# variable, which is not needed).
Please try to fix all these first, then let's see if any of them help.
User avatar
Codger
Posts: 97
Joined: May 29th, 2017, 3:16 pm

Re: Reading from Rainmeter.ini or other .ini

Post by Codger »

balala wrote:Not very sure what the Thailand project is, but probably it doesn't even have an importance.
Sorry, got my 'mentors' confused. I've been rather addlepated since being back but I am feeling a little sharper today. Unfortunately that means that several things are clamoring for my attention when what I really want to do is dig into this. But with your permission I like to skip a round and jump ahead without doing my due diligence.
balala wrote:It's very hard to follow everything, as you've posted the above codes.
I've simplified that so that you can set the variable SectionName to any widget you have that you'd like to drag around.
You'll need to add Group=RackMaster to that widget. That allows us to focus down on just the script in question. Good points on the other one. It was one of the first ones I wrote and largely it was adapted from bits and parts found on line as I learned what the parts did.

As to the rest.
balala wrote:What the [SetRackTop] section of the main code, want to be? It's not a measure, it's not a meter, so what you wanted to achieve with it? In Rainmeter, such sections can't be used. The options posted under it, are "orphans".
I actually caught this one before bed but you must have grabbed it prior to that.
I would like to use the example though to help get clarity on something I probably previously understood.
A lot of time I just want something to happen. That comes in two forms. I create a Measure of which I don't give a damn about the return value. Usually I make that a String measure. Is that the correct choice? The other is I want a series of Bangs to activate regardless of any condition and in that case I set up the very artificial looking 'always is true' scenario. Is there a 'just do it' command for bangs I am overlooking?
balala wrote:Same is the #MasterY# = (#MasterY# + 58) option of the [MeasureSetBottomHardDriveUsageBarCInRack] measure, which I also can't understand.
Can't believe I was so foggy I missed that.
balala wrote:The IfActions (as well as the IfConditions and IfMatches) can't be applied to meters. They belong to measures. You've used an IfAboveValue and the appropriate IfAboveAction, on the [MeasureSetHardDriveUsageBarCInRack] meter (which despite of its name, is a meter, having a Meter=STRING option). So, the bangs included into the IfAboveAction option won't be executed never.
Meant to type Measure. When I saw that I was so hoping that was the problem. I'm sure that is a big part of it but alas not the whole thing.

The rest of your points apply to the other program (which I really should go back over my early work) that I had included only so you could run it. And in doing so I made things much more confusing instead.
balala wrote:Please try to fix all these first, then let's see if any of them help.
I made the changes and ran it to no obvious change. If you wish to go on to others more deserving of your time until I am able to return to this and get back under the hood I fully understand. Hopefully I can free up some time tomorrow.

And by the way, once again you did exactly what I asked. You just pointed out the glaring errors without rewriting the whole thing. That and your time continue to be greatly appreciated.

[hr][/hr]

Code: Select all

[Rainmeter]
Update=1000
AccurateText=1
MiddleMouseDownAction=!RainmeterDeactivateConfig
;LeftMouseDownAction=[!Enable StackSkins][!Update StackSkins]
Group=RackMaster

[Metadata]
Name=RackMaster2
Author=Codger
Information=
Version=0.0.1
License=Creative Commons Attribution - Non - Commercial - Share Alike 3.0

[Variables]
@include=#@#Common.inc
CRadius=7
CBorder=4

;Section Name in the Rainmeter.ini file
SectionName = Codger\HardDriveBar\HardDriveUsageBarC

MasterX = #CURRENTCONFIGX#
MasterY = #CURRENTCONFIGY#
LastX = #CURRENTCONFIGX#
LastY = #CURRENTCONFIGY#

[Background]
Meter=Shape
X=(#CRadius#+2)
Y=(#CRadius#+2)
Shape=Rectangle X,Y,(#CRadius#*3),(#CRadius#*4),10 | Extend MyModifiers1
MyModifiers1=Fill Color #MediumGrey#,160 | StrokeWidth #CBorder# | Stroke Color #MediumGrey#,222
UpdateDivider=-1


[RackSymbol]
Meter=String
X=(#CRadius#+4)
Y=(#CRadius#+5)
FontFace=WingDings
FontColor=#PureYellow#,240
FontSize=(#CRadius#*2+1)
StringStyle = Bold
Text=T
;❄︎
UpdateDivider=-1

[DidRackMove]
Measure=String
IfCondition=(#LastX# = #CURRENTCONFIGX#) && (#LastY# = #CURRENTCONFIGY#)
IfFalseAction=[!UpdateMeasure SetRackTop][!UpdateMeasure MeasureHardDriveUsageBarCActive][!Updategroup RackMaster]
DynamicVariables=1

[SetRackTop]
Measure=String
LastX = #MasterX#
LastY = #MasterY#
MasterX = (#CURRENTCONFIGX#+10)
MasterY = #CURRENTCONFIGY#
DynamicVariables=1
UpdateDivider=-1

[MeasureHardDriveUsageBarCActive]
Measure=Script
ScriptFile=#@#ReadIni.lua
ConfigName=#SectionName#
ParameterName=Active

[MeasureSetBottomHardDriveUsageBarCInRack]
Measure=String
MasterY = (#MasterY# + 58)
DynamicVariables=1
UpdateDivider=-1

[MeasureSetHardDriveUsageBarCInRack]
Measure=STRING
MeasureName=MeasureHardDriveUsageBarCActive
IfAboveValue=0
IfAboveAction=[!WriteKeyValue  #SectionName# WINDOWX #MasterX# "#SETTINGSPATH#Rainmeter.ini"][!WriteKeyValue  #SectionName# WINDOWY #MasterY# "#SETTINGSPATH#Rainmeter.ini"][!UpdateMeasure MeasureSetBottomHardDriveUsageBarCInRack][!UpdateMeasure MeasureSetBottomHardDriveUsageBarCInRack]
UpdateDivider=-1
User avatar
balala
Rainmeter Sage
Posts: 16109
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Reading from Rainmeter.ini or other .ini

Post by balala »

Ok, please pack your config and upload it. It would be the simplest solution to can check what you have. If you agree, be careful to include all configs, if more then one are needed.
Post Reply