You are not logged in.
just want to mention that i added a new section to part 9 about using function within functions
this post will eventually be about tables
anyone still reading
Not only am I reading ... I am saving locally!
Keep it coming I need this!
Last edited by Sector11 (2012-01-23 12:57:26)
· ↓ ↓ ↓ ↓ ↓ ↓ ·
BunsenLabs Forums now Open for Registration
· ↑ ↑ ↑ ↑ ↑ ↑ · BL ModSquad
Offline
PART 10 - sending info to functions using tables
Tables in Lua are extremely useful and versatile, so im going to focus on using them to send information.
We have a bar meter drawing function separate to our main function and i've been through a few methods of getting the information the function needs from the main function via the curved brackets () in the function call to the function itself.
i have so far shown how we can do this by sending strings
--call function domsomething in main and send info
dosomething(1,0,0,1,"mono",12)
--dosomething receives info and sets it to strings
function dosomething(red,green,blue,alpha,font,foontsize)
this is a nice straightforward way of passing the information
BUT it has some drawbacks
you have to send EVERYTHING the function needs EVERY time you call the function
if you don't send it everything and miss something out, or put it in the wrong order
then you will get unexpected behaviour from the function as it sets its strings to the wrong values
or, more likely, you will get a nil error.
We can set tables to get around this
this way does requires some extra work initially
but once set up, you have the ability to, for example, specify default values for strings in advance and then only send the function the required information.
Say you wanted 5 bar indicators
you want them all to have grey backgrounds
you want them all to be the same height and width
you want the indicator to be green from 0 to 45, then yellow up to 75 and then red
the only thing that will be different between each bar will be the value it displays and the x,y coordinates so.
possibly we want our bars all to line up in a row, so we may only need to change the x while keeping y the same
so to cut down on typing and save time all we want to send to the function is the value to display and the x coordinate of the meter
when function become complicated, the list of things the function needs to operate can become very large. In addition, the script may allow you to do several different things (eg draw a square or a circle) so you would only want to send the information that the specific part of the script (if you want to draw a circle you dont want to have to specify settings for a square that you wont use!)
USING TABLES
There are different kinds of tables.... indexed tables, "dictionary" tables and mixed tables (which have both))
for this use of sending information we will be using a "dictionary" tables which usually take this general form"
name of table
=
open the table with curly brackets {
enter data separated by commas
close the table with }
table={red=1,green=0,blue=0,alpha=1,font="mono",fontsize=12}
as i mentioned before once you have your table open table={ you can space out and use multiple lines to enter the data on and allow for the use of comments... as long as you use commas in the right place!
table={--set table and open
red=1,
green=0,
blue=0,
alpha=1,--alpha of 0 = full transparent, 1=full opaque
font="mono",
fontsize=12,
}--closes table
NOTE - it isnt a good idea to call a table "table" just as it is a bad idea to call a string "string"
just as with strings, give your tables unique names with the table name giving some information about what that table contains.
now when we want to send info to our "dosomething" function we can do this
i'll be using a better name for the table below
--setup function domsomething in main and call function
dosettings={--set table and open
red=1,
green=0,
blue=0,
alpha=1,--alpha of 0 = full transparent, 1=full opaque
font="mono",
fontsize=12,
}--closes table
dosomething(dosettings)
------------------------------------------------------------------------------
--dosomething receives the table, and puts the info into another table
function dosomething(settings)
NOTE
the name of the table you put your settings into (dosettings in the above) and the table name you set for the function itself to use (settings in the above example) don't have to be the same
function "dosomething" just puts the info inside table "dosettings" and puts it into table "settings" in the same order
NOW WE HAVE TO GET THE INFO OUT
this is where the extra work comes in
when sending the strings, the strings were immediately available to the function
when sending tables we need to get the info out and into strings
this will all happen in the "dosomething" function
in the function we have a table called "settings" that contains the info we need because:
function dosomething(settings)
there are several ways we can get the info out of a dictionary type table
1. using a period
this method takes the form
tablename.stringname
we know our tablename, "settings"
and when we look at what was set in the table, we see that we were setting strings
dosettings={--set table and open
red=1,
green=0,
blue=0,
alpha=1,--alpha of 0 = full transparent, 1=full opaque
font="mono",
fontsize=12,
}--closes table
so red,green,blue,alpha,font and fontsize are the names of the strings within the table
so, we want to get our color values out of the table and into strings... we would do the following:
redvalue=settings.red
greenvalue=settings.green
bluevalue=settings.blue
alphavalue=settings.alpha
NOW:
string "redvalue" has a value of 1
string "greenvalue" has a value of 0
string "bluevalue" has a value of 0
string "alphavalue" has a value of 1
and we can use these string in the function like so:
cairo_set_source_rgba (cr,redvalue,greenvalue,bluevalue,alphavalue)
BUT we said earlier tha we didnt want to have to send "dosomething" colorvalues every time we want to use the function.
when we call the function we only want to specify the font and fontsize
--in main function call dosomething
dosettings={--open
fontsize=12,
font="Sans",
}--close
NOTE - with dictionary type tables, the order in which you enter your data doesn't matter
HOWEVER
"dosomething" still needs color and alpha values
if we have the line inside "dosomething"
redvalue=settings.red
redvalue will be "nil"
and we will get an error when we try and use it to set the color
Conky: llua_do_call: function conky_test execution failed: /home/benjamin/lua/codetest.lua:11: error in function 'cairo_set_source_rgba'.
argument #2 is 'nil'; 'number' expected.
this error message pops up in the terminal
ALWAYS RUN CONKY FROM TERMINAL WHEN TESTING!
its quite helpful... it tells us the name of the file that is causing the problem, it tells us the line number in that file where the error occurs and it tells us where in that line the error is
here is my code, lines 10 and 11
red=nil
cairo_set_source_rgba (cr,red,1,1,1)
and we can see the error on line 11, the second data position within the set source brackets ()
WE NEED TO CATCH THE NIL BEFORE ITS USED
the error occurred on line 11 (when we tried to use the string) not on line 10 (where the string was set to nill)
we can catch nil values using IF statements
redvalue=settings.red
if redvalue==nil then
redvalue=1
end
you will usually find these short statements written on a single like like so
redvalue=settings.red
if redvalue==nil then redvalue=1 end
so the above is where our default settings come into play
if, when calling "dosomething" you don't want to specify color values instead you want to default to white
if you dont set "red" in the function call in the main function then in "dosomething" settings.red will be nill and so redvalue will be nil. If redvalue is nil then the IF evaluation "if redvalue==nil then" is passed and the code inside the If is executed, setting redvalue to 1.
To expand that idea a bit we could set up defualt settings in the main script then use them in the function
function conky_main
--setup lines
--set default values for color, alpha, font and fontsize
default_red=1
default_green=1
default_blue=1
default_alpha=1
default_font="mono"
default_fontsize=12
--setup and call dosomething function
dosettings={
fontsize=14
}
domseomthing(dosettings)
--closeout lines
end-- of main function
-------------------------------------------------------------------------
function dosomething(settings)
redvalue=settings.red
if redvalue==nil then redvalue=default_red end
greenvalue=settings.green
if greenvalue==nil then greenvalue=default_green end
bluevalue=settings.blue
if bluevalue==nil then bluevalue=default_blue end
alphavalue=settings.alpha
if alphavalue==nil then alphavalue=defualt_alpha end
fontvalue=settings.font
if fontvalue==nil then fontvalue=default_font end
fontsizevalue=settings.fontsize
if fontsizevalue==nil then fontsizevalue=default_fontsize end
--use strings to do something
end--of dosomething function
if we want the default we simply dont send the value in the function call
if we want something other than the default then we need to set it in the call,
if we set "fontsize=14" then when we look at the relevant lines in dosomething:
fontsizevalue=settings.fontsize
if fontsizevalue==nil then fontsizevalue=default_fontsize end
settings.fontsize is not equal to nil, it is equal to 14
the IF evaluation is not passed and the code inside the IF is not executed so when we use fontsizevalue in the function it retains its value of 14.
Last edited by mrpeachy (2012-01-30 20:55:06)
Offline
Good another section to add to my .txt file. I'll get this yet!
· ↓ ↓ ↓ ↓ ↓ ↓ ·
BunsenLabs Forums now Open for Registration
· ↑ ↑ ↑ ↑ ↑ ↑ · BL ModSquad
Offline
PART 11a FOR LOOPS and A CPU HISTORY CHART
for loops are extremely useful when you need to do the same thing a number of times
there are many ways you can use the FOR operator, but the way that I use the most is like so:
for example
for i=1,10 do
print (i)
end
the i=1,10 is telling the script to perform the code within the loop (everything from the do to the end) for a certain number of times
when just written as i=1,10, the code will be repeated 10 times for every whole number between 1 and 10, starting at 1 and ending at 10 (you can tell the code to count in different increments or even in reverse but i usually find counting by whole numbers to work)
change the numbers in the line to get different numbers of passes of the loop, different starting points and different ending points
BUT not only is the loop repeated for the designated number of times, the useful part is that for each pass of the loop the value of "i" changes when it is used inside the loop.
so in our loop above:
- the loop starts, "i" is set to a value of 1 inside the loop,
- the code within the loop is executed and we print 1 to the terminal
because i=1 and we are printing i
(i is a just like other strings we have set values to)
the loop repeats, "i" is set to a value of 2 inside the loop, the code is executed, we print 2 to the terminal
loop repeats, i=3, print 3 to terminal
loop repeats, i=4, print 4 to terminal
and so on until i=10 and then the loop is done
so in the terminal we see
1
2
3
4
5
6
7
8
9
10
what makes this useful is that we can then use the changing values for i in calculations.
Say you wanted a horizontal row of 10 filled in white circles with each circle center 20 pixels away from the next with the first circle starting at coordinates 10,10
we would set our colors and set up the cairo_arc function (x,y,radius,start_angle, end_angle) then draw the circle like this
cairo_set_source_rgba (cr,1,1,1,1)
cairo_arc (cr,10,10,10,0,2*math.pi)
cairo_fill (cr)
then we could copy and paste the code a further 9 times and edit the x coordinates for every subsequent circle
or we could use a for loop and have it do the repeats for us
we can set our color outside of the loop as we want all our circles to be white
cairo_set_source_rgba (cr,1,1,1,1)
for i=1,10 do
x=10+((i-1)*20)
cairo_arc (cr,x,10,10,0,2*math.pi)
cairo_fill (cr)
end
in the above code ive separated the calculation for x out of the arc function and set a string called "x" to the value of the equation
x=10+((i-1)*20)
this equation takes the value of i and subtracts 1 from it (so our first circle is drawn at x = 10)
it then multiplies i-1 by 20 which is the gap we want between our circles
then adds 10 which is the staring x for our first circle
so the for loop is activated and "i" is set to 1 so our equation works out so that x=10
and our first circle is drawn at coordinates 10,10 as we wanted
the loop repeats and "i" is set to 2. The equation works out so that x=30
and our next circle is drawn at coordinates 30,10 (ie 20 pixels further on from our first circle)
the loop continues until "i" = 10 and we end up with 10 circles positioned as we wanted
using equations you can do a lot with a simple progression of numbers as you get in this version of the for loop!
Another good use of the for loop is to put data into tables or read the data that is in a table.
Here is another lua display project to work on that uses these techniques:
the cpu history chart
conky has the ability to display a chart showing your cpu usage history with just a short command. It takes a little more to do the same thing in lua, but when you are done you have much more flexibility in how to use it
the first thing we need to be able to do it record out cpu usage over a period of time so that we have something to display. To do this we are going to use a table and we are going to get the data into the table using a for loop.
The type of table we will use is an indexed table, and in this case our table will only contain numbers
Indexed tables
these kinds of tables usually look like this when you write them out (i'll only put numbers into the table for now, but it can hold other things too)
somedata={13,44,25,26,10}
so unlike the "dictionary" takes we used before, this table only has one part to each bit of information.
commas are always used in tables to separate values
in an indexed table, we are concerned about the order in which the data is in the table.
in the table above
position 1 in the table holds the number 13,
position 2 holds the number 44 and so on
to get the data out of the table we have to use a slightly different method
tablename[tableposition]
you have to use the square brackets for this purpose
so i called the table "somedata", so to get the first entry in the table we put:
somedata[1]
NOTE we can also use the square brackets to get data out of dictionary tables
dosettings={--set table and open
red=1,
green=0,
blue=0,
alpha=1,--alpha of 0 = full transparent, 1=full opaque
font="mono",
fontsize=12,
}--closes table
print (dosettings["font"]) -->prints "mono" in the terminal
getting data into a table
Tables can be constructed by putting data into them via code rather than having to write the consent into the table directly
We can use the square brackets to get information into tables (just thinking about indexed tables for now)
we can set up a blank table like this
datatable={}
then we can use this code to put the number 16 into the first position of the table
datatable[1]=16
and we can continue adding values using the same method
AS LONG AS we don't skip over any positions
datatable[2]=18
datatable[3]=20
datatable[4]=22
if we were able to look at the contents of "datatable" directly it would look like this
datatable={16,18,20,22}
in fact is is quite easy to take a look at what is in a table using a for loop
reading a table with a for loop
the first thing we need to know is how many repeats we need the loop to do in order to see all the values in the table. In the above case we know that we have put 4 values into the table, but sometimes you dont know ahead of time how many things there are in a table.
an easy way to find out is to put # in front of the table name like so
--set blank table
datatable={}
--put data into table
datatable[1]=16
datatable[2]=18
datatable[3]=20
datatable[4]=22
--count entries
entries=#datatable
print (entries) --> 4 is printed to the terminal
then we can do this
for i=1,entries do
print ( datatable[i] )
end
so what happening in the loop?
loop starts, "i"=1 inside the loop
the code in the loop is executed
print ( datatable[i] )
and since i=1, we print the number in the first position of the table "datatable" and we see
16
printed in the terminal.
The loop repeats, "i"=2
18 is printed in the terminal
The loop repeats, "i"=3
20 is printed to the terminal
The loop repeats, "i"=4 (the upper limit of the loop since entries=4)
22 is printed to the terminal
end of loop.
NOTE the loop is activated and repeats until done before any subsequent code in the script is executed
So lets think about what is required to get our cpu history chart
The first thing to consider is that we want to information in our cpu table to be persistent from one execution of the lua script to the next and that leads us to think a bit more about how the whole lua script within conky works!
EXECUTING THE LUA SCRIPT
every conky cycle the entire lua script is executed BUT we can write code in the lua script with conditions, using if statements for example, to control the operation of different bits of code. We already saw this in the setup lines required by the conky main function.
we used the line
if updates>5 then
--all the code stuff
end--if updates>5
the point of this condition is so that you don't get a segmentation fault if you try and access cpu values via the lua script
conky updates are quite useful for controlling other things too.
now if we had a setup like this:
function conky_main()
--main conky function setup lines
if updates>5 then
--##############################
--set blank table
cputable={}
--put data into table
cputable[1]=conky_parse("${cpu}")
--##############################
end-- if updates>5
--main function close out lines
end-- end main function
then every cycle of conky, as long as the update number is above 5 the script is executed
beginning "updates=6" (since updates>5) the table called "cputable" is set blank and then subsequently the cpu usage value is put into it
the next conky cycle "updates=7" (since updates is still > than 5 and will be for every additional cycle)
the lua script is executed from the beginning and "cputable" is set blank again and again the current cpu% is put into it
clearly this isnt going to get us anywhere because we are blanking our table each cycle
we want the script to "remember" the values for cpu from previous conky cycles
SO
we have to come up with a situation where the table "cputable" is set up blank only once and not blanked each time the lua script is executed
something like this will do it
function conky_main()
--main conky function setup lines
--setup cpu table
if updates=4 then
cputable={}
end
if updates>5 then
--##############################
cputable[1]=conky_parse("${cpu}")
--##############################
end-- if updates>5
--main function close out lines
end-- end main function
there will be only one time when "updates=4" so only one occasion for the table to be created
every subsequent conky cycle "updates" will not equal 4 so the table isnt blanked and will be persistent from
but the next problem is that we are writing (and then overwriting) the current cpu% to position1 in the table each cycle!
to be continued
OOOOPS i tried making my text within code brackets bold, but it didnt work, just put and into the code!
ive removed these now
also saw that i had missed a bracket on my equations, also fixed
Last edited by mrpeachy (2012-01-31 03:02:08)
Offline
PART 11b - CPU HISTORY CHART CONTINUED
so we have a persistent table in which we can store our cpu values so that we will have them available to the script so we can display them.
Now we have to get the information into the table in a useful way.
Say we wanted to record 10 readings of cpu data, the value now plus the previous 9 values...
it may have been:
5 -- 9 seconds ago
6
8
6
12
10
8
7
4
3 -- now
the table we want would look like this:
cputable={5,6,8,6,12,10,8,7,4,3}
we want to limit the number of values we are storing.
You could just keep recording values into the table and have the table grow bigger and bigger, but leave conky on for a few hours and you will have thousands of entries in the table. Big tables like that are inefficient and would almost certainly increase processor drain as the script has to read through those entries every conky cycle.
We want to specify the number of entires to store and have the script update the table, overwriting the older values with the new ones
so a second later (and our current cpu% is 13) our table would still contain 10 entries, but they would have shifted in order:
cputable={,6,8,6,12,10,8,7,4,3,13}
and so on and so on until our 3 has moved all the way to the left and is eventually lost being replaced with more recent values
So we need to specify how many entries we want and set a string
table_length=10
As ever, there are many ways you could go about getting this result...
when i first wrote a script to give moving bars I wasnt aware of the use of for loops
you can see what i did here: http://thepeachyblog.blogspot.com/2010/ … raphs.html
wlourf then came up with the following code:
for i = 1, tonumber(table_length) do
if cpu_table[i+1]==nil then cpu_table[i+1]=0 end
cpu_table[i]=cpu_table[i+1]
if i==table_length then
cpu_table[table_length]=tonumber(conky_parse('${cpu}'))
end
end--of for loop
this cutting the number of code lines by many hundreds
NOTE - code indenting
code indenting can help you keep track of whats going on in your code (when you have compound if statements and or loops). Since it is important that whenever you open an if or a loop you end it with end
but whether I do it or not is hit or miss.
so lets look at what the code is doing bit by bit
for i = 1, tonumber(table_length) do
here we are opening the for loop,
- setting the number of repeats for the loop
- setting where the loop starts and ends
im using tonumber(table_length) to make sure that there is no error given
more often than not i use a "wait and see" approach with tonumber
ie I tend not to put them in unless it turns out that i need them (or unless i can anticipate a potential problem for example when getting a value using conky_parse its usually a good idea to use tonumber)
this loop will run 10 times, and "i" will take the value of every whole number between 1 and 10 within the loop in order.
if cpu_table[i+1]==nil then cpu_table[i+1]=0 end
this is one of those nil catcher lines because in the next line we will be trying to read the value that our table "cpu_table" has at position [i+1]
we need this because if you try and read a table position that doesn't exist you are going to get a nil value, and then when you try and do something with a string that is nil you get an error and the script wont work until it is fixed
cpu_table[i]=cpu_table[i+1]
this is how we are going to get our number cycling.
This line will give us nil values because initially the table is empty
so if we try and read from table position cpu_table[i+1],
when we start our loop, i=1,
so essentially we are trying to read position 2 in the table which is empty and therefore nil
the line above has anticipated this so when we read position 2 in "cpu_table" it is no longer nil, it has a bvalue of 0 instead
so our loop starts, i=1
we read position 2 of cpu_table and check to see if it is nil (if cpu_table[i+1]==nil)
if it is nil (which it will be at the start) then we set it to a value of 0 (then cpu_table[i+1]=0 end)
we set position 1 of cpu_table (cpu_table[ i ]) to the same value found at position 2 (=cpu_table[i+1])
position 1 in the table=0
our loop continues, i=2
we read position 3 of cpu_table and check to see if it is nil (if cpu_table[i+1]==nil)
it will be nil to start so we set it to a value of 0 (then cpu_table[i+1]=0 end)
we set position 2 of cpu_table (cpu_table[ i ]) to the same value found at position 3 (=cpu_table[i+1])
position 2 in the table=0
the loop continues in the same fashion, setting up our table on the first run of the script, so that position 1 to 9 are 0.
BUT when we get to the last repeat of the loop we activate the next part of the script:
if i==table_length then
cpu_table[table_length]=tonumber(conky_parse('${cpu}'))
end
when i=table_length (which we set to 10) then position 10 in the table "cpu_table" is set to the current cpu% value as read through the conky_parse command
SO the very first cycle of the lua script, conky reads a cpu% value of 8 for example...
so once our for loop is all done what would cpu_table look like?
cpu_table={0,0,0,0,0,0,0,0,0,8,0}
we will in fact have 11 entries in our table because when i=10 we still executed the first lines within the for loop, creating an entry [i+1] with a value of 0
next we end our for loop
end--of for loop
the next conky cycle the script is run again and our for loop runs
this line
cpu_table[i]=cpu_table[i+1]
shifts all the values in our table 1 position to the left
and these lines
if i==table_length then
cpu_table[table_length]=tonumber(conky_parse('${cpu}'))
end
capture the new reading into the table at position 10
if the next cpu value is 5 our table will now look like this
cpu_table={0,0,0,0,0,0,0,0,8,5,0}
next cycle cpu%=6
cpu_table={0,0,0,0,0,0,0,8,5,6,0}
and so on: shift existing values one place to the left, put latest value into position 10
We now have our record of CPU, now we have to work to display the values!
Last edited by mrpeachy (2012-02-01 03:56:41)
Offline
PART 11c - DRAWING THE CPU HISTORY DATA
here is what we have so far, with a couple of additions and ive added a comment here and there
--this script draws history graphs
require 'cairo'
function conky_main()
if conky_window == nil then return end
local cs = cairo_xlib_surface_create(conky_window.display, conky_window.drawable, conky_window.visual, conky_window.width, conky_window.height)
cr = cairo_create(cs)
local updates=tonumber(conky_parse('${updates}'))
--setup tables, need one table for each graph to be drawn
if updates==4 then
cpu_table={}
end
--end of table setup
if updates>5 then
--#########################################################################################################
--you will need to copy and paste this section for each different graph you want to draw
--set table length, ie how many values you want recorded
table_length=10
for i = 1, tonumber(table_length) do
if cpu_table[i+1]==nil then cpu_table[i+1]=0 end
cpu_table[i]=cpu_table[i+1]
if i==table_length then
cpu_table[table_length]=tonumber(conky_parse('${cpu}'))
end
end--of for loop
--call graph drawing function
draw_graph(cpu_table,table_length)
--end of graph setup
--#########################################################################################################
end-- if updates>5
cairo_destroy(cr)
cairo_surface_destroy(cs)
cr=nil
end-- end main function
function draw_graph(data,table_length)
for i=1,table_length do
print (data[i])
end
end--of function draw_graph
i have started to think about writing a separate function to do the drawing part of the script...
so far i have the function call in the main function:
draw_graph(cpu_table,table_length)
and i have the function itself started below the main function
function draw_graph(data,table_length)
for i=1,table_length do
print (data[i])
end
end--of function draw_graph
right now all i am doing is sending the contents of "cpu_table" and "table_length" from the main function to the drawing function
in the drawing function, the contents of "cpu_table" are received and put into a table called "data".
I expect to be sending this function more than one table, for example once i have my cpu graph set up, i can use the same method for a memory usage graph, or a graph for each one of my cpu cores...or whatever else i want to see displayed
so im using a more generic term for my table, and "data" seemed appropriate
at this stage i just have a for loop in the drawing function that will print out in the terminal the contents of "data", using the value of "table_length" as the upper limit of our loop repeats and "i" value
so im going to run the script and make sure that my data is being collected correctly and being sent to my drawing function correctly. I'll have cpu values showing in conky via ${cpu} so i can watch conky and the terminal and makes sure the numbers are correct.
and everything seems to be working...so we can move on and do something with that data
so we have to think about what we want to see at the end... and what we want to make configurable
settings
i want to be able to position my graph, and in this case everything will be relative to the bottom left corner
i want each cpu value to be represented by a vertical bar
i want the color, width and maximum height of the bar to be configurable
0% will be at the bottom of the bar, 100% at the top
i want my graph to move from right to left
so that current cpu value is on the right, getting older to the left
that should do for now...
the first thing i would do is to write in a settings section into the main function, and add those settings to the function call as well as editing the drawing function to receive the settings. For now I'll just be sending strings
im also going to make a string to hold the value to be displayed instead of using conky_parse directly in the code
and im going to make a setting to specify max_value in case we want to use something other than % outputs
in the main function
--you will need to copy and paste this section for each different graph you want to draw
--SETTINGS ##############################################
--set coordinates of bottom left corner of graph
blx,bly=100,200
--set value to display
gvalue=conky_parse('${cpu}')
--set max value for the above value
max_value=100
--set color, red green blue alpha , values 0 to 1
red,green,blue,alpha=1,1,1,1--fully opaque white
--set bar width
width=2
--set height of chart
cheight=150
--set table length, ie how many values you want recorded
table_length=10
--END OF SETTINGS #########################################
for i = 1, tonumber(table_length) do
if cpu_table[i+1]==nil then cpu_table[i+1]=0 end
cpu_table[i]=cpu_table[i+1]
if i==table_length then
cpu_table[table_length]=tonumber(gvalue)
end
end--of for loop
--call graph drawing function
draw_graph(cpu_table,max_value,table_length,blx,bly,red,green,blue,alpha,width,cheight)
--end of graph setup
and in the drawing function
function draw_graph(data,max_value,table_length,blx,bly,red,green,blue,alpha,width,cheight)
for i=1,#data do
print (data[i])
end
end--of function draw_graph
remember - when sending strings you have to make sure the numbers of strings you send in the main function is the same number you set (AND IN THE RIGHT ORDER) in the function that is receiving the strings
NOTE in the above case i have asked for bar width...so the total width of the graph will be determined by the number of bars (which is 10 in our example multiplied by width)
I could have decided to set total graph width in which case i would have to calculate the width of the individual bars...
as always there are plenty of different ways to go!
THE BARS
there are a few ways we could draw our bars, we could use rectangles
in which case our setting for width would be the width of the rectangle
or we could draw line
in which case width would affect line width
also depending on which way you go, you will have to think about positioning.
with the rectangle you set a corner and draw the rectangle relative to that corner
with the line you would set coordinates of the midpoint, in this case the midpoint at the bottom
because of the way the setting of line width is applied
im going to go with drawing lines for this graph.
we can go ahead and set up out colors and line width commands
we have our loop set up, and we can start to think about how we will get the lines drawn...
function draw_graph(data,max_value,table_length,blx,bly,red,green,blue,alpha,width,cheight)
cairo_set_source_rgba (cr,red,green,blue,alpha)
cairo_set_line_width (cr,width)
for i=1,table_length do
print (data[i])
end
end--of function draw_graph
when writing the code within the for loop, its a good idea to just think about one instance of code,
for example, our loop starts and the first value of "i" will be 1... so what do we want to happen when "i"=1...
well... if we were to write
print (data[1])
we would see the first entry in the "data" which is (in the code so far) the first value in "cpu_table"
it is the oldest cpu value that our table contains
we want our oldest value on the left, and we want the graph relative to the bottom left corner coordinates, so this all works out nicely
BUT we do have the hiccup of line width to think about
say we did this to draw a vertical line 100 pixels long:
cairo_set_line_width (cr,10)
cairo_move_to (cr,100,200)
cairo_line_to (cr,100,100)
cairo_stroke (cr)
our "move to" coordinates would be the bottom MIDDLE of the line. The line would extend for 1/2 line width to the left and1/2 line width to the right.
So the actual coordinates of the bottom left corner of the line would be 95,200
to put that as a calculation
--set value of blx
blx=100
--calculate actual coordinate to use with line so that bottom left x is actually at 100
blx=blx+(width/2)
NOTE we are adding (width/2) to blx because we want to shift the line to the right a little (increasing x means moving right)
the second instance of blx= uses the original blx in the calculation but then overwrites the contents of the blx string with the new value
bly will stay the same for each line we draw so we can construct an initial "cairo_move_to" line
replacing out "print (data[ i ])" test line like so:
cairo_move_to (cr,blx+(width/2),bly)
this would be the start position for the leftmost bar...
now we have to think about how we can apply the changing values of "i" inside the for loop to set the starting positions for all the bars
from the bottom left corner of the first line to the bottom left corner of the next line will be equal to our line width and this will be true for each subsequent bar
so we will be multiplying "width" by the value of "i"
BUT
cairo_move_to (cr,blx+(width/2),bly) is what we want for the first bar
and since we are using "i=1,table_length"... the first number "i" will be is 1
so to keep out first start point as it is we would do something like this:
cairo_move_to (cr,blx+(width/2)+((i-1)*width),bly)
why not just use "for i=0,9" ? you ask
so that we can just put
cairo_move_to (cr,blx+(width/2)+(i*width),bly)
no particular reason... but then you would have to go and make our other for loops "for i=0,9" because right now if we were to try and read "data[ i ]" and i=0, we would get a nil value
i almost always start my for loops at 1 and calculate relative to that
of course there are times when you want to start at 0 or a different number
so in our code so far we can put
function draw_graph(data,max_value,table_length,blx,bly,red,green,blue,alpha,width,cheight)
cairo_set_source_rgba (cr,red,green,blue,alpha)
cairo_set_line_width (cr,width)
for i=1,table_length do
cairo_move_to (cr,blx+(width/2)+((i-1)*width),bly)
end
end--of function draw_graph
the next thing to do, just in the cpu indicator bar example, we need to calculate bar height based on the value of cpu and the setting for total graph height (which i called "cheight") and max value
in this case,however, the values are in the table "data" so we need to get then out using the square brackets like this inside the for loop
bar_height=(cheight/max_value)*data[i]
- we have a start position for each bar
- we know how tall to draw each bar
we just need to actually draw the lines, and in this case im going to use cairo_rel_line_to
cairo_rel_line_to draws a line relative to the coordinates we set in cairo_move_to
in this case we want the x value of each line to be the same (as we are drawing vertical lines)
and we want the y value to change and represent our cpu value
- for the rel_line, to draw UP we have to specify NEGATIVE values
so put all that together our drawing function looks like this
function draw_graph(data,max_value,table_length,blx,bly,red,green,blue,alpha,width,cheight)
cairo_set_source_rgba (cr,red,green,blue,alpha)
cairo_set_line_width (cr,width)
for i=1,table_length do
--calculate bar height
bar_height=(cheight/max_value)*data[i]
--set start position for each bar, and modify with the value of "i"
cairo_move_to (cr,blx+(width/2)+((i-1)*width),bly)
--draw relative line, y becomes equal to bar height and must be negative to draw up
cairo_rel_line_to (cr,0,bar_height*-1)
--draw the line
cairo_stroke (cr)
end
end--of function draw_graph
and watch your cpu chart in action!
Last edited by mrpeachy (2012-02-02 23:00:29)
Offline
so the question is... where to go from here?!
any ideas or suggestions would be gladly received
i was perhaps going to look at things like gradients
some other uses of tables and other ways to use them and editing functions i use in lua
also text extents i use quite frequently,,, how to run commands from lua
so may directions to head!
Offline
so may directions to head!
Go in all the directions!
Seriously though, this looks amazing. Planning to spend some serious time with this over the weekend. Thanks so much for putting this together!
Offline
^ if there is anything that doesn't make sense please let me know!
Offline
^ if there is anything that doesn't make sense please let me know!
mrpeachy - shame on you for saying that. You know I'm reading all this (and making a text file) and yet you still ask: if there is anything that doesn't make sense please let me know!
Back on post #1 I see that ...
However sinceyou're here and LUA does loops and
datay and datax with datayy and dataxx values with stuff like this:
topy=15
topyy=135 -- topy+(topyy*1)
topx=285
topxx=130
--set coordinates for top lef corners for each repeat
top_left_x_coordinate[1],top_left_y_coordinate[1] =topx ,topy
top_left_x_coordinate[2],top_left_y_coordinate[2] =topx+(topxx*1) ,topy
top_left_x_coordinate[3],top_left_y_coordinate[3] =topx+(topxx*2) ,topy
top_left_x_coordinate[4],top_left_y_coordinate[4] =topx+(topxx*3) ,topy
top_left_x_coordinate[5],top_left_y_coordinate[5] =topx+(topxx*4) ,topy
top_left_x_coordinate[6],top_left_y_coordinate[6] =topx ,topy+(topyy*1)
top_left_x_coordinate[7],top_left_y_coordinate[7] =topx+(topxx*1) ,topy+(topyy*1)
top_left_x_coordinate[8],top_left_y_coordinate[8] =topx+(topxx*2) ,topy+(topyy*1)
top_left_x_coordinate[9],top_left_y_coordinate[9] =topx+(topxx*3) ,topy+(topyy*1)
top_left_x_coordinate[10],top_left_y_coordinate[10] =topx+(topxx*4) ,topy+(topyy*1)
Is there a way to make a "marquee" in LUA that would outperform the ${scroll} function that is tied into the conky refresh rate? Someone in the main conky thread is asking about the ${scroll} function. Look for the PIGS.
· ↓ ↓ ↓ ↓ ↓ ↓ ·
BunsenLabs Forums now Open for Registration
· ↑ ↑ ↑ ↑ ↑ ↑ · BL ModSquad
Offline
Just a quick question about the last three posts of the HowTo:
Part 11 FOR LOOPS and A CPU HISTORY CHART
CPU HISTORY CHART CONTINUED
DRAWING THE CPU HISTORY DATA
Do you consider them all a part of:
Part 11 FOR LOOPS and A CPU HISTORY CHART?
For my txt file I'm thinking of making them:
Part 11 - For Loops And A CPU History Chart
http://crunchbanglinux.org/forums/post/184830/#p184830
Part 11a - CPU History Chart Continued
http://crunchbanglinux.org/forums/post/185253/#p185253
Part 11b - Drawing The CPU History Data
http://crunchbanglinux.org/forums/post/185753/#p185753
The "Beginning" looks like this: (image links intact throughout)
HowTo: Using Lua scripts in conky Search for-->> thetop
From mrprachy:
This how to is based on what I know... not what is known :D
INDEX (lines are searchable)
Part 01 How does a lua script work?
http://crunchbanglinux.org/forums/post/180225/#p180225
Part 02 - Displaying text and working with colors
http://crunchbanglinux.org/forums/post/180248/#p180248
Part 03 - Drawing Lines
http://crunchbanglinux.org/forums/post/180359/#p180359
Part 04 - Drawing Rectangles, Cirlces And Arcs
http://crunchbanglinux.org/forums/post/180388/#p180388
Part 05 - Making A Bar Meter And A Circle Meter
http://crunchbanglinux.org/forums/post/180661/#p180661
Part 06 - Some More Drawing Calculations And Introduction To "if"
http://crunchbanglinux.org/forums/post/180798/#p180798
Part 07 - Adding Our Alarm Color Change Feature And Looking At More Complex If Statements
http://crunchbanglinux.org/forums/post/181076/#p181076
Part 08 - Turn Our Code Into A Function
http://crunchbanglinux.org/forums/post/181338/#p181338
Part 09 - Sending Information To Functions
http://crunchbanglinux.org/forums/post/181629/#p181629
Part 10 - Sending Info To Functions Using Tables
http://crunchbanglinux.org/forums/post/183756/#p183756
Part 11 - For Loops And A CPU History Chart
http://crunchbanglinux.org/forums/post/184830/#p184830
Part 11a - CPU History Chart Continued
http://crunchbanglinux.org/forums/post/185253/#p185253
Part 11b - Drawing The CPU History Data
http://crunchbanglinux.org/forums/post/185753/#p185753
================================================================================
Part 01 - How Does A Lua Script Work?
Only 3193 lines to date!
Last edited by Sector11 (2012-02-03 00:59:23)
· ↓ ↓ ↓ ↓ ↓ ↓ ·
BunsenLabs Forums now Open for Registration
· ↑ ↑ ↑ ↑ ↑ ↑ · BL ModSquad
Offline
ive thought about scroll using lua a few times and wrote a couple of scripts, but haven't tackled it in a while
but no matter how fancy i get with the coding... lua scripts, when run in conky with lua_load etc, are set to the same cycle time as the conkyrc itself
if conky updates once per second the lua scripts it runs will also update once per second
and yes, i would say that the last 3 points are all part of the same continuum
so 11a, 11b 11c would be appropriate - ill use this on the first page
or 11, 11a, 11b
EDIT i knew i should have added an addendum like this:
^ if there is anything that doesn't make sense please let me know! **
** you are not allowed to answer "all of it!"
Last edited by mrpeachy (2012-02-03 01:19:37)
Offline
@ mrpeachy
RE: Scroll - oh well, can't win them all
I like the 11a, 11b, 11c tells ya right up front a BIG portion is on it's way.
See that's why they pay you the big bucks in 'Luaville'
^ if there is anything that doesn't make sense please let me know! **
** you are not allowed to answer "all of it!"
I would have known immediately it was directed at me too!
· ↓ ↓ ↓ ↓ ↓ ↓ ·
BunsenLabs Forums now Open for Registration
· ↑ ↑ ↑ ↑ ↑ ↑ · BL ModSquad
Offline
Now as I said:
Back on post #1 I see that ...
We come to:
then we have lines about conky updates
local updates=tonumber(conky_parse('${updates}')) if updates>5 then
these lines are only important if you plan on reading cpu% in the lua script, but its generally a good idea to have these lines anyway (one less thing to cause an error)
the first of these lines has a few things to note about it
1. the term "local" at the beginning (cover that later)
2. the use of strings the = sign
in lua you hold information in strings by saying:
string = information
information can be other strings, plain text, numbers etc (more about that later)
I can't find where you ever explained the term "local".
ALSO: if cpu% is not used and those lines are commented out (I would not remove them) how does it make running the LUA script different?
I'm thinking:
draw_bg.lua
draw_bg_cpu.lua
For example, correct me if I'm wrong, if
local updates=tonumber(conky_parse('${updates}'))
if updates>5 then
is 'live' and conky update interval is set to:
update_interval 3600
that background and conky will not show for 5*1800 = 18,000 seconds or 5 hours.
I have a few conkys that use "draw_bg.lua" they do NOT have cpu% in them and by nature do not need to be run more than:
update_interval 86400
once a day.
5*86400 = 5 days!! One heck of a long to to wait for conky to start!
If conky doesn't update - less requests for CPU resources.
THINK: single core 800mHz CPU
Last edited by Sector11 (2012-02-03 03:08:56)
· ↓ ↓ ↓ ↓ ↓ ↓ ·
BunsenLabs Forums now Open for Registration
· ↑ ↑ ↑ ↑ ↑ ↑ · BL ModSquad
Offline
For example, correct me if I'm wrong, if
local updates=tonumber(conky_parse('${updates}')) if updates>5 then
is 'live' and conky update interval is set to:
update_interval 3600
that background and conky will not show for 5*1800 = 18,000 seconds or 5 hours.
I have a few conkys that use "draw_bg.lua" they do NOT have cpu% in them and by nature do not need to be run more than:
update_interval 86400
once a day.
5*86400 = 5 days!! One heck of a long to to wait for conky to start!
If conky doesn't update - less requests for CPU resources.
THINK: single core 800mHz CPU
thats an interesting point
if you know you arent going to use cpu then you can just remove that line (make sure you remove the matching end also!). the only difference is that the lua will be seen as soon as conky starts instead of waiting
in fact the background lua script doesnt have that setup line in it because there was no need to be putting a cpu call in there
that part about "if updates>5"does need some further explanation (and i'll update that post soon)
see, i just assume everyone does the same thing i do, set conky to 1 second updates!
and in that case there's no inconvenience to waiting a few seconds for the lua to load up
but increase the inerval for conky updates and you would indeed be waiting a long time
as for what local means... well thats a whole new kettle of fish... and i do promise to go into it "later"
Offline
Sector11 wrote:5*86400 = 5 days!! One heck of a long to to wait for conky to start!
If conky doesn't update - less requests for CPU resources.
THINK: single core 800mHz CPUthats an interesting point
if you know you arent going to use cpu then you can just remove that line (make sure you remove the matching end also!). the only difference is that the lua will be seen as soon as conky starts instead of waitingin fact the background lua script doesnt have that setup line in it because there was no need to be putting a cpu call in there
that part about "if updates>5"does need some further explanation (and i'll update that post soon)
see, i just assume everyone does the same thing i do, set conky to 1 second updates!
and in that case there's no inconvenience to waiting a few seconds for the lua to load up
but increase the inerval for conky updates and you would indeed be waiting a long timeas for what local means... well thats a whole new kettle of fish... and i do promise to go into it "later"
I'm leaving that entire quote as reference because you just pointed out a slight twist to what I "thought"....
I thought you were talking in 'conky' if you used:
${cpu cpu1}%
they needed to be there...
But you are talking about:
conky_parse('${cpu}')
aren't you.
This is good news.
Like I said I won't remove I'll comment them out with this:
[[-- if you use CPU in LUA like this:
conky_parse('${cpu}')
you NEED the following tow lines:
local updates=tonumber(conky_parse('${updates}'))
if updates>5 then
otherwise comment them out ]]
· ↓ ↓ ↓ ↓ ↓ ↓ ·
BunsenLabs Forums now Open for Registration
· ↑ ↑ ↑ ↑ ↑ ↑ · BL ModSquad
Offline
I thought you were talking in 'conky' if you used:
${cpu cpu1}%
they needed to be there...
But you are talking about:
conky_parse('${cpu}')
aren't you.
that's is correct
Offline
PART 12a - DRAWING A CLOCK and circular things
in this section im going to go through the code to get an analogue style clock in conky
and as always to start with you need to think about what you want it to look like...
lets keep it simple and have a thin white circle on the outside,
marks for the positions of the hours around the face just on the inside of the circle
marks will be short white lines
3 hands, hours and minutes in white
keeping with convention in terms of hand sizes
second hand in red
also keeping with convention in the order in which you see the hands
lets thing about some of the specifics
we want to be able to configure clock total diameter
and set the line width for the outline
we want to be able to configure the shape and size of the hands
set length for all hands
we will be using lines to draw the hands so we want to be able to set the end cap type
see here http://cairographics.org/samples/set_line_cap/
we want to be able to configure the size of the hour marks and their caps
we can draw a circle easy enough
and we will start that in the main function
and we can start to separate our settings from our drawing code
function conky_main
--main function setup lines ##########
##########################
--CLOCK SETTINGS
clock_radius=60
clock_centerx=100
clock_centery=100
--set border options
clock_border_width=2
--set color and alpha for clock border
cbr,cbg,cbb,cba=1,1,1,1--full opaque white
--DRAWING CODE
cairo_set_source_rgba (cr,cbr,cbg,cbb,cba)
cairo_set_line_width (cr,clock_border_width)
cairo_arc (clock_centerx,clock_centery,clock_radius,0,2*math,pi)
cairo_stroke (cr)
##########################
--main function close out lines
end--of main function
OOPS
try the above code and you get this error
usually best to killall conky before you go hunting the error down
Conky: llua_do_call: function conky_main execution failed: /home/benjamin/lua/codetest.lua:24: attempt to perform arithmetic on global 'math' (a table value)
look at line 24 which in my script is this
cairo_arc (clock_centerx,clock_centery,clock_radius,0,2*math,pi)
and the error tells me it has something to do with the "math" part
i put in a comma math,pi when it should have been a period math.pi
ok...fixed, fire it up again! ....
Conky: llua_do_call: function conky_main execution failed: /home/benjamin/lua/codetest.lua:24: error in function 'cairo_arc'.
argument #1 is 'number'; '_cairo' expected.
doh! KFC (killall conky and restart)
look at line 24 again...
cairo_arc (clock_centerx,clock_centery,clock_radius,0,2*math.pi)
yes, as the error said i had not put in the "cr" as the first entry in the curved brackets
should be like this
cairo_arc (cr,clock_centerx,clock_centery,clock_radius,0,2*math.pi)
fixed... fire it up! success! i have a white circle
the amended code...
function conky_main
--main function setup lines ##########
##########################
--CLOCK SETTINGS
clock_radius=60
clock_centerx=100
clock_centery=100
--set border options
clock_border_width=2
--set color and alpha for clock border
cbr,cbg,cbb,cba=1,1,1,1--full opaque white
--DRAWING CODE
cairo_set_source_rgba (cr,cbr,cbg,cbb,cba)
cairo_set_line_width (cr,clock_border_width)
cairo_arc (cr,clock_centerx,clock_centery,clock_radius,0,2*math.pi)
cairo_stroke (cr)
##########################
--main function close out lines
end--of main function
NEXT lets get our hour marks in there
i think its easiest to get the static things done first
we want our marks to look like the kind of marks you would see on a real analogue clock
as if they were radiating out from the middle of the circle to the edges like this
http://www.clker.com/clipart-clock-face-no-hands-.html
THIS is how we are going to do it
i use this bit of code A LOT what it does is allow you to specify a center point and a radius and then calculates for you the coordinates of any point, defined by degrees, around that circle
i like to use the the code like this
point=(math.pi/180)*degree
x=0+radius*(math.sin(point))
y=0-radius*(math.cos(point))
in which case you then have to add on the x and y values it calculates to your existing centre coordinates.
we are going to use the line drawing command for our marks so we need a start point and an end point
and to get those points we need to think about a few things...
we have an outer radius for our clock of 60
how close to the outside circle do we want out marks to come?
how long do we want our marks to be in total?
how thick do we want our marks to be?
how do we want the ends of our marks to look?
we need to add to our settings...
--gap from clock border to hour marks
b_to_m=5
--set mark length
m_length=10
--set mark line width
m_width=3
--set mark line cap type
m_cap=CAIRO_LINE_CAP_ROUND
--set mark color and alpha,red blue green alpha
mr,mg,mb,ma=1,1,1,1--opaque white
then lets think about how to draw these marks.
since we want our marks to end 5 pixels before the border we can imagine a circle that encompasses the outer points of all our marks
in our drawing code section we can start doing some calculations
--calculate mark outer radius
m_end_rad=clock_radius-b_to_m
m_end_rad=60-5 = 55 and that is the radius of where all our marks will end
to calculate the radius of the circle from which the lines will start we can do this
--calculate mark start radius
m_start_rad=m_end_rad-m_length
m_start_rad=55-10 = 45
SO lets just think about th 12'o clock mark
it will start 45 pixels straight up from the center point of our circle, be drawn vertically for 10 pixels and end at a point 55 pixels straight up from the clock center
it would be pretty straightforward to just punch in these numbers to cairo_move_to and cairo_line_to
but try punching in the numbers for the 1 or 2 o'clock mark and things get a little more tricky
we are going to use our point finding code to do the hard math for us!
again, just for the 12 o'clock mark, which occurs at 360 or 0 degrees whichever you want to use
--calculate end and start radius for marks
m_end_rad=clock_radius-b_to_m
m_start_rad=m_end_rad-m_length
--calculate start point for 12 oclock mark
radius=m_start_rad
point=(math.pi/180)*0
x=0+radius*(math.sin(point))
y=0-radius*(math.cos(point))
--set start point for line
cairo_move_to (cr,clock_centerx+x,clock_centery+y)
--calculate end point for 12 oclock mark
radius=m_end_rad
point=(math.pi/180)*0
x=0+radius*(math.sin(point))
y=0-radius*(math.cos(point))
--set path for line
cairo_line_to (cr,clock_centerx+x,clock_centery+y)
--set line cap type
cairo_set_line_cap (cr, m_cap)
--set line width
cairo_set_line_width (cr,m_width)
--set color and alpha for marks
cairo_set_source_rgba (cr,mr,mg,mb,ma)
--draw the line
cairo_stroke (cr)
seems like a lot of code to draw a little line and we still need 11 more marks!
we could just copy and paste the code 11 more times, editing the degrees values to get each mark...
BUT whenever you have a situation where your thinking about repeating code a number of times think FOR LOOP
we need 12 marks, and that tells us that we will start our for loop like this
for i=1,12 do
I'm a stickler for making my code as efficient as i can, so before i go ahead and stick everything inside my for loop, im going to look through the code an see what i can put outside of the loop..
in this case i can put all the setup lines: width,cap,color before the loop begins
no point in calling each one of those commands 12 times
also we only need to calculate our end and start radius once
the next thing is to think about how the changing value of "i" within the loop will be used
and in this case the value of "i" will be used in a calculation to get the degrees for each mark
we have these lines dealing with degrees,
point=(math.pi/180)*0
we know that there are 360 degrees in a cirlcle, we want 12 equally spaced marks so each mark will be 360/12 = 30 ... so that each mark will be 30 degrees around the circle from the previous mark
inside out for loop we will apply "i" like this
point=(math.pi/180)*((i-1)*30)
so when i=1, degrees will be 0*30=0 and thats out 12 oclock
when i=2, degrees will be 1*30=30 and thats our 1 oclock mark
when i=3, degrees will be 2*30=60 and that is out 2 oclock mark
and so on...
remember that we need to apply this code in 2 positions, one to set degrees to get the start points, one to set degrees to set the end points
SO
--stuff that can be moved outside of the loop, needs only be set once
--calculate end and start radius for marks
m_end_rad=clock_radius-b_to_m
m_start_rad=m_end_rad-m_length
--set line cap type
cairo_set_line_cap (cr, m_cap)
--set line width
cairo_set_line_width (cr,m_width)
--set color and alpha for marks
cairo_set_source_rgba (cr,mr,mg,mb,ma)
--start for loop
for i=1,12 do
--drawing code uisng the value of i to calculate degrees
--calculate start point for 12 oclock mark
radius=m_start_rad
point=(math.pi/180)*((i-1)*30)
x=0+radius*(math.sin(point))
y=0-radius*(math.cos(point))
--set start point for line
cairo_move_to (cr,clock_centerx+x,clock_centery+y)
--calculate end point for 12 oclock mark
radius=m_end_rad
point=(math.pi/180)*((i-1)*30)
x=0+radius*(math.sin(point))
y=0-radius*(math.cos(point))
--set path for line
cairo_line_to (cr,clock_centerx+x,clock_centery+y)
--draw the line
cairo_stroke (cr)
end--of for loop
and there we have our marks... now you can play around with the settings till you get them the way you want them.
ill continue in part 12b with how to get the hands on the clock!
Offline
Sector11 wrote:I thought you were talking in 'conky' if you used:
${cpu cpu1}%
they needed to be there...
But you are talking about:
conky_parse('${cpu}')
aren't you.
that's is correct
I just tried, in the v9000.lua
lua script lines
lua script lines
conky_window.height)
cr = cairo_create(cs)
-- local updates=tonumber(conky_parse('${updates}'))
-- if updates>5 then
--#########################################################################################################
local display_script=1 -- set 1 for seperate display script, 0 to enter at bottom, default = 1
settings_table=weather_settings()
local secs=settings_table[1]
more lua script lines
more lua script lines
of course it didn't work --- I forgot about the matching "end" that I have no idea where to find. Do you realize how many "end" statements that are?
The only end I am 100% certain about:
--END OF SCRIPT
· ↓ ↓ ↓ ↓ ↓ ↓ ·
BunsenLabs Forums now Open for Registration
· ↑ ↑ ↑ ↑ ↑ ↑ · BL ModSquad
Offline
@ sector11 ...that particular end is on line 758 (or thereabouts) of the current v9000 as found in post 1 of my weather on conky thread
but there is more dependant on conky updates than the "if updates>5" line
ive been thinking about how to get the script to activate and update if you were to set a long update interval in your conkyrc... the updating part would be fine... if you set conkyrc to an update interval of 1800 you soeuld set the "secs" setting (which i probably need to rename!) to 1
but im not sure about the initial activation of the script
ive been planning to post an update of v9000 with additional options, so ill look into the startup and update methods
but for now i recommend running v9000 at an update interval of 1 second in conkyrc, perhaps a couple or 3 seconds would be fine too but nothing particularly high
Offline
@ sector11 ...that particular end is on line 758 (or thereabouts) of the current v9000 as found in post 1 of my weather on conky thread
but there is more dependant on conky updates than the "if updates>5" line
ive been thinking about how to get the script to activate and update if you were to set a long update interval in your conkyrc... the updating part would be fine... if you set conkyrc to an update interval of 1800 you should set the "secs" setting (which i probably need to rename!) to 1
but im not sure about the initial activation of the script
ive been planning to post an update of v9000 with additional options, so ill look into the startup and update methods
but for now i recommend running v9000 at an update interval of 1 second in conkyrc, perhaps a couple or 3 seconds would be fine too but nothing particularly high
OK, so it's not as easy as I thought. All the conkys I use to have set update_intervals of 1800, 3600 or 86400 are now at 1 because of the LUA background script. BUMMER!!!!!!!!!!!!
I think until I get rid of this crappy 800mHz single core CPU that reaches 100% usage a few times a day and locks up a couple of times a week I should stop xcomp and LUA and put my conkys back as they were with transparent images for backgrounds and of course that will mean no weather either.
· ↓ ↓ ↓ ↓ ↓ ↓ ·
BunsenLabs Forums now Open for Registration
· ↑ ↑ ↑ ↑ ↑ ↑ · BL ModSquad
Offline
Part 12b - CLOCK CONTINUED
we have to get our hands on the clock and get them moving but the first thing we need to know is how to get the time i lua...
we could use conky parse to get the time via the conky commands for time, but there is a more direct way
i like to reference this page when working with time commands
http://php.net/manual/en/function.strftime.php
seconds=tonumber(os.date("%S"))
minutes=tonumber(os.date("%M"))
hours=tonumber(os.date("%I")) -- I is 12 hour clock, H is 24 hour
the seconds hand
this is the most direct hand to get going,
BUT it will also be the hand at the "front" ie it will be drawn in front of the minute and hour hands
so in terms of position in the code we will have to have our seconds hand drawn lowest down in the script
--seconds hand setup
--set length of seconds hand
sh_length=50
--set hand width
sh_width=1
--set hand line cap
sh_cap=CAIRO_LINE_CAP_ROUND
--set seconds hand color
shr,shg,shb,sha=1,0,0,1--fully opaque red
the math...
60 seconds to go all the way around, 360 degrees in a circle, so every second the hand will move 6 degrees
so we need to convert seconds to degrees because we are going to use the same circle point calculating code as before/. We will draw the line of the seconds hand from the center point of the circle to the point corresponding to seconds which will be at a radius equal to the length we set the hand to be
in our drawing section we can do the math
--draw seconds hand
seconds=tonumber(os.date("%S"))--i'm using tonumber to make sure that the output is read as a number
sec_degs=seconds*6
--set radius we will use to calculate hand points
radius=sh_length
--set our starting line coordinates, the center of the circle
cairo_move_to (cr,clock_centerx,clock_centery)
--calculate coordinates for end of seconds hand
point=(math.pi/180)*sec_degs
x=0+radius*(math.sin(point))
y=0-radius*(math.cos(point))
--describe the line we will draw
cairo_line_to (cr,clock_centerx+x,clock_centery+y)
--set up line attributes
cairo_set_line_width (cr,sh_width)
cairo_set_source_rgba (cr,shr,shg,shb,sha)
cairo_set_line_cap (cr, sh_cap)
cairo_stroke (cr)
drawing the other hands is essentially the same
--minues hand setup
--set length of minutes hand
mh_length=50
--set hand width
mh_width=1
--set hand line cap
mh_cap=CAIRO_LINE_CAP_ROUND
--set minute hand color
mhr,mhg,mhb,mha=1,1,1,1--fully opaque white
there is a little bit of additional math involved however
we want the minute hand to move every second so it moves smoothly around the clock instead of jumping from one minute to the next
so instead of dividing the 360 degrees into 60 increments of 6 degrees, will will be dividing 360 by (60*60)
360/3600=0.1... so our minute hand will move 0.1 degrees every second
we need to convert our minutes to seconds and then add on the current seconds to achieve our smooth minute hand movement
minutes=tonumber(os.date("%M"))
--convert minutes to seconds
m_to_s=minutes*60
--get current seconds
seconds=tonumber(os.date("%S"))
--add them together
msecs=m_to_s+seconds
--calculate degrees for the hand each second
msec_degs=msecs*0.1
--set radius we will use to calculate hand points
radius=mh_length
--set our starting line coordinates, the center of the circle
cairo_move_to (cr,clock_centerx,clock_centery)
--calculate coordinates for end of minutes hand
point=(math.pi/180)*msec_degs
x=0+radius*(math.sin(point))
y=0-radius*(math.cos(point))
--describe the line we will draw
cairo_line_to (cr,clock_centerx+x,clock_centery+y)
--set up line attributes and draw line
cairo_set_line_width (cr,mh_width)
cairo_set_source_rgba (cr,mhr,mhg,mhb,mha)
cairo_set_line_cap (cr, mh_cap)
cairo_stroke (cr)
REMEMBER
this chink of drawing code must come BEFORE the code used to draw the seconds hand if you want the minutes hand to be drawn BEHIND the seconds hand.
Things further down in the script are drawn ontop of things higher up
so now we have 2 hands, and again you can go up to your settings and adjust till it looks how you want it
FINALLY
the hours hand!
settings
--hour hand setup
--set length of hour hand
hh_length=30
--set hand width
hh_width=5
--set hand line cap
hh_cap=CAIRO_LINE_CAP_ROUND
--set hour hand color
hhr,hhg,hhb,hha=1,1,1,1--fully opaque white
we want our hour hand to transition nice and smoothly, moving every second
math
60*60*12=number of seconds in 12 hours = 43 200
360/43200= 0.00833333333 and this is how many degrees out hour hand will move every second!
we will have to add onto that the value of minutes as seconds, and the current seconds to get our smooth motion
hours=tonumber(os.date("%I"))--12 hour clock
--convert hours to seconds
h_to_s=hours*60*60
minutes=tonumber(os.date("%M"))
--convert minutes to seconds
m_to_s=minutes*60
--get current seconds
seconds=tonumber(os.date("%S"))
--add them all together
hsecs=h_to_s+m_to_s+seconds
--calculate degrees for the hand each second
hsec_degs=hsecs*(360/43200)--im using an equation instead of typing the calculation straight in because the result of 360/43200 gave us decimal places
--set radius we will use to calculate hand points
radius=hh_length
--set our starting line coordinates, the center of the circle
cairo_move_to (cr,clock_centerx,clock_centery)
--calculate coordinates for end of minutes hand
point=(math.pi/180)*hsec_degs
x=0+radius*(math.sin(point))
y=0-radius*(math.cos(point))
--describe the line we will draw
cairo_line_to (cr,clock_centerx+x,clock_centery+y)
--set up line attributes and draw line
cairo_set_line_width (cr,hh_width)
cairo_set_source_rgba (cr,hhr,hhg,hhb,hha)
cairo_set_line_cap (cr, hh_cap)
cairo_stroke (cr)
placement of this code will determine the order in which the hands are drawn, just as with the minutes hand
here is the code all together in a functional script
--[[drawing a clock
in conkyrc
lua_load /path/clock.lua
lua_draw_hook_pre main
TEXT
]]
require 'cairo'
function conky_main()
if conky_window == nil then return end
local cs = cairo_xlib_surface_create(conky_window.display, conky_window.drawable, conky_window.visual, conky_window.width, conky_window.height)
cr = cairo_create(cs)
--#########################################################################################################
--CLOCK SETTINGS
clock_radius=60
clock_centerx=100
clock_centery=100
--set border options
clock_border_width=2
--set color and alpha for clock border
cbr,cbg,cbb,cba=1,1,1,1--full opaque white
--gap from clock border to hour marks
b_to_m=5
--set mark length
m_length=10
--set mark line width
m_width=3
--set mark line cap type
m_cap=CAIRO_LINE_CAP_ROUND
--set mark color and alpha,red blue green alpha
mr,mg,mb,ma=1,1,1,1--opaque white
--seconds hand setup
--set length of seconds hand
sh_length=50
--set hand width
sh_width=1
--set hand line cap
sh_cap=CAIRO_LINE_CAP_ROUND
--set seconds hand color
shr,shg,shb,sha=1,0,0,1--fully opaque red
--minues hand setup
--set length of minutes hand
mh_length=50
--set hand width
mh_width=3
--set hand line cap
mh_cap=CAIRO_LINE_CAP_ROUND
--set minute hand color
mhr,mhg,mhb,mha=1,1,1,1--fully opaque white
--hour hand setup
--set length of hour hand
hh_length=30
--set hand width
hh_width=5
--set hand line cap
hh_cap=CAIRO_LINE_CAP_ROUND
--set hour hand color
hhr,hhg,hhb,hha=1,1,1,1--fully opaque white
--DRAWING CODE
--draw border
cairo_set_source_rgba (cr,cbr,cbg,cbb,cba)
cairo_set_line_width (cr,clock_border_width)
cairo_arc (cr,clock_centerx,clock_centery,clock_radius,0,2*math.pi)
cairo_stroke (cr)
--draw marks
--stuff that can be moved outside of the loop, needs only be set once
--calculate end and start radius for marks
m_end_rad=clock_radius-b_to_m
m_start_rad=m_end_rad-m_length
--set line cap type
cairo_set_line_cap (cr, m_cap)
--set line width
cairo_set_line_width (cr,m_width)
--set color and alpha for marks
cairo_set_source_rgba (cr,mr,mg,mb,ma)
--start for loop
for i=1,12 do
--drawing code uisng the value of i to calculate degrees
--calculate start point for 12 oclock mark
radius=m_start_rad
point=(math.pi/180)*((i-1)*30)
x=0+radius*(math.sin(point))
y=0-radius*(math.cos(point))
--set start point for line
cairo_move_to (cr,clock_centerx+x,clock_centery+y)
--calculate end point for 12 oclock mark
radius=m_end_rad
point=(math.pi/180)*((i-1)*30)
x=0+radius*(math.sin(point))
y=0-radius*(math.cos(point))
--set path for line
cairo_line_to (cr,clock_centerx+x,clock_centery+y)
--draw the line
cairo_stroke (cr)
end--of for loop
--time calculations###########################
hours=tonumber(os.date("%I"))--12 hour clock
--convert hours to seconds
h_to_s=hours*60*60
minutes=tonumber(os.date("%M"))
--convert minutes to seconds
m_to_s=minutes*60
--get current seconds
seconds=tonumber(os.date("%S"))
--draw hours hand ############################
--get hours minutes seconds as just seconds
hsecs=h_to_s+m_to_s+seconds
--calculate degrees for the hand each second
hsec_degs=hsecs*(360/(60*60*12))--im using an equation instead of typing the calculation straight in because the result of 360/43200 gave us decimal places
--set radius we will use to calculate hand points
radius=hh_length
--set our starting line coordinates, the center of the circle
cairo_move_to (cr,clock_centerx,clock_centery)
--calculate coordinates for end of minutes hand
point=(math.pi/180)*hsec_degs
x=0+radius*(math.sin(point))
y=0-radius*(math.cos(point))
--describe the line we will draw
cairo_line_to (cr,clock_centerx+x,clock_centery+y)
--set up line attributes and draw line
cairo_set_line_width (cr,hh_width)
cairo_set_source_rgba (cr,hhr,hhg,hhb,hha)
cairo_set_line_cap (cr, hh_cap)
cairo_stroke (cr)
--draw minutes hand
--get minutes and seconds just as seconds
msecs=m_to_s+seconds
--calculate degrees for the hand each second
msec_degs=msecs*0.1
--set radius we will use to calculate hand points
radius=mh_length
--set our starting line coordinates, the center of the circle
cairo_move_to (cr,clock_centerx,clock_centery)
--calculate coordinates for end of minutes hand
point=(math.pi/180)*msec_degs
x=0+radius*(math.sin(point))
y=0-radius*(math.cos(point))
--describe the line we will draw
cairo_line_to (cr,clock_centerx+x,clock_centery+y)
--set up line attributes and draw line
cairo_set_line_width (cr,mh_width)
cairo_set_source_rgba (cr,mhr,mhg,mhb,mha)
cairo_set_line_cap (cr, mh_cap)
cairo_stroke (cr)
--draw seconds hand #############################
--calculate degrees for the hand each second
sec_degs=seconds*6
--set radius we will use to calculate hand points
radius=sh_length
--set our starting line coordinates, the center of the circle
cairo_move_to (cr,clock_centerx,clock_centery)
--calculate coordinates for end of seconds hand
point=(math.pi/180)*sec_degs
x=0+radius*(math.sin(point))
y=0-radius*(math.cos(point))
--describe the line we will draw
cairo_line_to (cr,clock_centerx+x,clock_centery+y)
--set up line attributes
cairo_set_line_width (cr,sh_width)
cairo_set_source_rgba (cr,shr,shg,shb,sha)
cairo_set_line_cap (cr, sh_cap)
cairo_stroke (cr)
--#########################################################################################################
cairo_destroy(cr)
cairo_surface_destroy(cs)
cr=nil
end-- end main function
a couple of things to note
im noy using the "if updates>5" check as im not anticipating using conky_parse("${cpu}") in this script so when you run the script the clock will pop up immediately as conky starts
also
ive changed the code around a little bit
instead of having multiple lines getting the data for minutes and seconds, i pulled those lines from the tops of each hand drawing code and put them together in one place ahead of the hand drawing code
--time calculations###########################
hours=tonumber(os.date("%I"))--12 hour clock
--convert hours to seconds
h_to_s=hours*60*60
minutes=tonumber(os.date("%M"))
--convert minutes to seconds
m_to_s=minutes*60
--get current seconds
seconds=tonumber(os.date("%S"))
Offline
OK, so it's not as easy as I thought. All the conkys I use to have set update_intervals of 1800, 3600 or 86400 are now at 1 because of the LUA background script. BUMMER!!!!!!!!!!!!
I think until I get rid of this crappy 800mHz single core CPU that reaches 100% usage a few times a day and locks up a couple of times a week I should stop xcomp and LUA and put my conkys back as they were with transparent images for backgrounds and of course that will mean no weather either.
the lua background script doesnt depend on any readings from conky regarding update interval
so no need to alter those conkyrcs!
if its working then its working
but for script using v9000 for weather you'll want an update interval of 1 second until i get to testing an alternative method
Offline
Sector11 wrote:OK, so it's not as easy as I thought. All the conkys I use to have set update_intervals of 1800, 3600 or 86400 are now at 1 because of the LUA background script. BUMMER!!!!!!!!!!!!
I think until I get rid of this crappy 800mHz single core CPU that reaches 100% usage a few times a day and locks up a couple of times a week I should stop xcomp and LUA and put my conkys back as they were with transparent images for backgrounds and of course that will mean no weather either.
the lua background script doesnt depend on any readings from conky regarding update interval
so no need to alter those conkyrcs!if its working then its working
but for script using v9000 for weather you'll want an update interval of 1 second until i get to testing an alternative method
Yea, I had turned of xcompmgr (never really did like it but thought it was required for the LUA scripts I use).
I was in the process of changing conkys when I saw I had 2 (with the LUA background) running at 86400 (I thought they were all running at 1 sec) and it dawned on me that you said those "update" lines aren't in the draw_bk.lua. So I used the LUA calls "above TEXT" and they work, no xcompmgr required.
Then I remembered reading something in your HowTo, you have no idea how happy I am for that - none trust me:
the second line
lua_draw_hook (can be lua_draw_hook_pre or lua_draw_hook_post)
tells conky which function to run from the lua script that was loaded.
Looking at the draw_bg.lua I see:
lua_load ~/Conky/LUA/draw_bg.lua
lua_draw_hook_pre draw_bg 10 0 0 0 0 0x000000 0.5
lua_draw_hook_pre
so I set the vertical conky on the right with weather and the background to:
lua_load ~/Conky/LUA/draw_bg.lua
lua_draw_hook_pre draw_bg 10 0 0 0 0 0x000000 0.5
#
## Calling the weather script
#
lua_load ~/v9000/v9000.lua
lua_draw_hook_post weather
## lua_draw_hook_pre weather
lua_load ~/Conky/templates/v9003_V_template.lua
TEXT
No composite manager - 6 conkys running (only one at 1 second) and my CPU right now: 3%
I'm not going to complain about that.
The conkys with the red dots boot to Desktop 3 and only run there.
Don't know where I got the idea that a composite manager was needed for these but it's not.
PS: You're writing the HowTo almost faster than I can copy/paste it to my txt file.
Last edited by Sector11 (2012-02-03 21:40:10)
· ↓ ↓ ↓ ↓ ↓ ↓ ·
BunsenLabs Forums now Open for Registration
· ↑ ↑ ↑ ↑ ↑ ↑ · BL ModSquad
Offline
How do I join multiple lua scripts into one?
For example the scripts have:
require 'cairo'
function conky_draw_text()
--- START PARAMETERS ---
stuff
--- END OF PARAMETERS ---
more LUA text stuff
require 'cairo'
function conky_main_rings()
--- START PARAMETERS ---
stuff
--- END OF PARAMETERS ---
more LUA rings stuff
require 'cairo'
function conky_main_bargraph()
--- START PARAMETERS ---
stuff
--- END OF PARAMETERS ---
more LUA rings stuff
require 'cairo'
function conky_main_box()
--- START PARAMETERS ---
stuff
--- END OF PARAMETERS ---
more LUA rings stuff
Everything after
--- END OF PARAMETERS ---
in each is different obviously.
A multi-finction script. If it's in the manual I've missed it.
===============================
Kind of like joining these:
Part 02 - Displaying text and working with colors
http://crunchbanglinux.org/forums/post/180248/#p180248
Part 04 - Drawing Rectangles, Cirlces And Arcs
http://crunchbanglinux.org/forums/post/180388/#p180388
Part 05 - Making A Bar Meter And A Circle Meter
http://crunchbanglinux.org/forums/post/180661/#p180661
Part 11a - For Loops And A CPU History Chart
http://crunchbanglinux.org/forums/post/184830/#p184830
Part 12A - Drawing A Clock And Circular Things
http://crunchbanglinux.org/forums/post/186112/#p186112
Part 12B - Clock Continued
http://crunchbanglinux.org/forums/post/186159/#p186159
Last edited by Sector11 (2012-03-03 16:18:12)
· ↓ ↓ ↓ ↓ ↓ ↓ ·
BunsenLabs Forums now Open for Registration
· ↑ ↑ ↑ ↑ ↑ ↑ · BL ModSquad
Offline
Copyright © 2012 CrunchBang Linux.
Proudly powered by Debian. Hosted by Linode.
Debian is a registered trademark of Software in the Public Interest, Inc.
Server: acrobat