Anatomy of a pvserver in Lua script language
A pvserver in Lua can be created without installing the Qt SDK and a C++ compiler. All you need is within our installation package. The structure of a Lua pvserver is very similar to the C/C++ version, Our libraries are used via a language binding that is created with swig. Because of this the reference manual for the pvslib and the rllib can also be used for Lua. There is a main program called pvslua which will read file main.lua and execute the lua script. Within main.lua there is a function luaMain(ptr) where the handling of a pvbrowser client starts. In fact pvslua is a C/C++ program with the same structure as a pvserver in C/C++. But within pvMain() pvslua starts processing main.lua.
You start a pvserver in Lua with the following command:
pvslua main.lua
With a pvserver in Lua it is possible to change the Lua code while the pvserver is running. A newly connected pvbrowser client will immediately see the modified version.
main.lua
Whenever a pvbrowser client connects pvslua creates a new thread for handling that client and executes file main.lua. The function showMask1() will show and handle mask1.
------------------------------------------------------------------------------ -- pvserver in lua : pvslua -port=5050 -cd=/your/directory/with/your/lua/code ------------------------------------------------------------------------------ trace = 1 -- here you may put variables global for all your masks dofile("mask1.lua") -- include your masks here ------------------------------------------------------------------------------ function luaMain(ptr) -- pvserver Lua Main Program p = pv.getParam(ptr) -- get the PARAM structure pv.pvSetCaption(p,string.format("Hello Lua %d",123)) pv.pvResize(p,0,1280,1024) pv.pvGetInitialMask(p) print("Inital mask = ", p.initial_mask) ret = 1 while 1 do -- show your masks if (ret==1) then ret = showMask1(p) else ret = 1 end end pv.pvThreadFatal(p,"Lua calling ThreadFatal") return 0 end
Definition of mask1 in Lua
showMask1() is generated by pvdevelop. You do not have to write it manually. It will show mask1. On the begin of that function the names of the widgets you have designed are listed. Also the toolTip and whatsThis properties of the widgets are listed and the widgetType is available.
Then you see the calls to pv functions that create the widget tree in the pvbrowser client.
Finally the function goes to the event loop where the events send by the pvbrowser client are interpreted and the according slotFunctions are called.
------------------------------------------------------------------------------ -- this file is generated by pvdevelop. DO NOT EDIT !!! ------------------------------------------------------------------------------ function showMask1(p) --- begin variables that are private to this mask -------------------------- iarray = pv.IntegerArray() -- see pv.getIntegers(text,iarray) below farray = pv.FloatArray() -- see pv.getFloats(text,farray) below --- begin construction of our mask ----------------------------------------- ID_MAIN_WIDGET = 0 PushButtonBack = 1 ID_END_OF_WIDGETS = 2 toolTip = {} toolTip[0] = "" toolTip[1] = "" whatsThis = {} whatsThis[0] = "" whatsThis[1] = "" widgetType = {} widgetType[0] = pv.TQWidget widgetType[1] = pv.TQPushButton pv.pvStartDefinition(p,ID_END_OF_WIDGETS) pv.pvQPushButton(p,PushButtonBack,0) pv.pvSetGeometry(p,PushButtonBack,10,10,111,40) pv.pvSetText(p,PushButtonBack,"Lua test") pv.pvEndDefinition(p); --- end construction of our mask ------------------------------------------- --- end variables that are private to this mask ---------------------------- dofile("mask1_slots.lua") -- include our slot functions if trace == 1 then print("show mask1") end pv.pvClearMessageQueue(p) -- clear all pending events ret = slotInit(p) -- intitialize our variables if ret ~= 0 then return ret end -- return number of next mask to call while(1) -- event loop do event = pv.pvGetEvent(p) -- get the next event result = pv.pvParseEventStruct(p,event) -- parse the event id = result.event i = result.i text = result.text -- now call the according slot function if id == pv.NULL_EVENT then ret = slotNullEvent(p) elseif id == pv.BUTTON_EVENT then if trace==1 then print("BUTTON_EVENT id=", i) end ret = slotButtonEvent(p,i) elseif id == pv.BUTTON_PRESSED_EVENT then if trace == 1 then print("BUTTON_PRESSED_EVENT id=",i) end ret=slotButtonPressedEvent(p,i) elseif id == pv.BUTTON_RELEASED_EVENT then if trace == 1 then print("BUTTON_RELEASED_EVENT id=",i) end ret=slotButtonReleasedEvent(p,i) elseif id == pv.TEXT_EVENT then --- snip ...
slotFunctions in Lua
The task of the developer of a visualization is to code the slotFunctions. The framework was generated by pvdevelop when you created the mask.
------------------------------------------------------------------------------ -- mask1_slots.lua Please edit this file in order to define your logic ------------------------------------------------------------------------------ -- here you may define variables local for your mask -- also see the variables in the generated maskX.lua function slotInit(p) -- this function will be called before the event loop print("slotInit called") return 0 end function slotNullEvent(p) print("slotNullEvent called") return 0 end function slotButtonEvent(p,id) if (id == PushButtonBack) then pv.pvSetText(p,PushButtonBack,"I have been clicked") end return 0 end function slotButtonPressedEvent(p,id) return 0 end function slotButtonReleasedEvent(p,id) return 0 end --- snip ...