PDA

View Full Version : Advice on programming a new HT setup with Girder



rbh
February 17th, 2006, 05:19 AM
My setup: A plasma TV with split screen. A Denon AVR4306 which has an Ethernet port. A HAI Omni Pro which does lights, security & sprinklers, a Russound 6-zone speaker system with IR collection from room keypads, 2 satellite receivers plus DVD, CD and my home PC which runs Girder, is not too far from the plasma and has second video output & sound. One satellite has a PVR but the software is not good and the TV guide only goes 3 days ahead and is dumb not smart like a TIVO so I might get Sage or Beyond TV or something.

So I am wondering how to pull all or most of this together. I am an experienced programmer having done C, C++, Vbasic, SQL, Java and most recently web pages & JavaScript. I groan at learning Lua, but if I use Girder then I must.

I've done a few short lua scripts and looked thru the forums. My basic hardware all works. I can learn IR codes and power up the plasma, talk to the Denon over IP. I have my own Java program to talk to the HAI over serial, but I am also trying to get the HAI plugin working with help from Proximis team.

Now to the point.

What is a good way of organising software for this lot? I don't think I want to do a true HTPC as I want to switch to HD and I wonder about the quality of PCI TV tuners for HD. My TV Wonder does not give a great picture on my hi-res PC LCD monitor although normal PC display looks good.

My thoughts are to use just the Denon to switch high quality TV and use the split screen capability of the plasma to have OSD with out having to worry about mixing HD signals. The TV also has a XGA input so I could switch to that too.

Back to the software. How to come with a scheme which is modular and allows components to be changed without having to reprogram the whole thing?

On the inputs side, the "Event mapping" feature of Girder allows different remotes to be nicely abstracted.

For outputs, I see that it would be possible to create a gml file for each device by creating a gml file with just Actions such as "DVD-PLAY" which would send the IR or IP or serial strings to the device and would abstract away model numbers and serial protocols.

Then the question remains what and how to put in the middle. My inclination is to put the whole lot in one or more Lua files and use AddEventHandler to capture events and TriggerEvent to send software commands to the abstracted outputs.

I see that many of the actions need to be modal. When I push PLAY, the current mode needs to determine if to play DVD, DVR or MP3. Easy to do with some lua variables!

I would appreciate any advice from anyone who has done all of this and is proud of his modularity, organisation, etc. I can see that it is easy to have a spaghetti mess that becomes a career and a nightmare to maintain, update or extend.

Promixis
February 20th, 2006, 05:16 AM
Its can get to be a mess quickly ;)

When you say abstract outputs, what exactly are you thinking?

We are adding a 'device manager' to G4/NR that might be along the lines of what you are thinking...

rbh
February 20th, 2006, 05:42 AM
See my other post from just now "Lua function to execute a named action".

It explains.

rbh
February 21st, 2006, 07:00 PM
I will record some progress

The general setup

Several gml files capture output commands by learning them through USB UIRT. Each gml file is one IR device.

For the rest, I decided to do as much as possible with lua because I know by the time I am finished it will be quite complicated. I am trying to make lua modules (classes, objects) each of which handles one device. All my lua code is in a series of scripts named plasma, dvd, ht, etc setup according to the manual. See the example using "On script enable"
The top level lua module is HomeTheatre (ht). It registers a handler using gir.AddEventHandler() so that it gets first kick at all incoming RW events. Some it captures and uses for mode switching. A mode is "Watch TV", "Play DVD". The ht tries to keep track of who is doing what, but it is never quite sure because there is no feedback from IR devices. Some events can then be siphoned off and sent to the AVR, since most devices need AVR volume. ht then dispatches events to other lua objects such as plasma, dvd. They use directly the obvious buttons such as play, stop. There are many more functions than there are buttons on the RW so all the oddball functions will be done with nested menus using the OSD.
I don't have a true HTPC just my regular PC not too far from everything else. I connect its video card TV output to a second input on the plasma. I can then use the split screen function which splits half and half so that I get live TV on the left and OSD on the right. When push a menu request button, it splits and brings up the OSD. I can then have sub-menus. I used "Menu Example" from demo.gml as a starting point. To get the menu to appear on the split screen, I configured my video card for two monitors and extended the desk top across both. You are supposed to be able to add some key definitions in osd.Classes.Menu and also to specify monitor 2. There are also various width parameters, which did not work for me. You can specify monitor= 2 in the new menu creation. But I found then the menu straddled the two monitors. My main is 1600 x 1200, my secondary is 640 x 480, as low as it will go. My desktop is extended across both. My modified Automenu code snippet is:
AutoMenu = osd.Classes.AutoMenu:New ({AutoCallback = menus.MyAutoCB, Fade=false})
AutoMenu.X=1600 -- width of primary monitor (1600 x 1200)
AutoMenu.Y=0 -- position at top
AutoMenu:Initialize() -- whatever this does, then ...
AutoMenu.FontSize=40 --set font size. Adjust until menu fills screen
AutoMenu.TimeOut=0
AutoMenu.MaxItems=20
...
I got the positioning I wanted by setting X to 1600 and Y to 0. My secondary screen is on the right. So the menu starts at the edge of the main monitor. I then found I needed to put the font call AFTER the initialize call. Why? because it seems to work.Then adjust the font size to scale the menu to fill the screen and hope that other menus fit too. I then plug the TV output of my ATI card into my plasma and switch it to split screen. Then I have my live picture on the left and my OSD on the right. And nothing on my PC screen. If I want to debug, I temporarily set the 1600 to 0.
I captured all the IR commands by dragging a USB UIRT action into a gml file. I then named each command for example dvd.play. For the Denon 4306 I am using all lua with gip to set up simple functions. I tested the AVR first using Telnet. It kind of worked. A snippet from my Denon module looks like this:
--[[
AVR callback function. Handles unsolicited events from the Denon
Usually these mean someone is fiddling with the knobs and selecting a new mode.
--]]
function avrCallBack(p1,p2)
if ( p2 == gip.CONNECTIONCLOSED ) then
print("Connection Closed")
return
end
if ( p2 == gip.CONNECTIONESTABLISHED ) then
if ( p1 == 0 ) then
print("New IP connection to AVR 4306")
avr.state = "open"
else
print("New Connection Failed: ", p1)
end
return
end
print(p1)
end
--[[
Open the socket in the AVR on the Telnet port (23) & register a callback
--]]
function avr.init()
socket = gip.Open('192.168.002.101',23)
socket:Callback(2, '\r', 1000, avrCallBack)-- 1s timeout
end
function avr.write(something)
if avr.state ~= "open" then
avr.init()
end
print("Writing to AVR socket:", something)
socket:Write(something)
end
function avr.on()
avr.write("PWON\r")
end
And the power goes on and off.
The IR commands are a bit of a pain because Girder cant access the defined and named commands by name. I ended up making a table that (snippet) looks like this:
plasma.CmdID = {
TogglePower=1852787992,
Sap=1852788000,
TvVideo=1852787993,}
It is tedious, but as long as I don't delete and create new USB UIRT actions, they will keep their ID (ID is the long number 1852787992). ( There must be a better way!!! Hint) I can still use the tree to relearn or do other IR configuration without redoing the Ids. Then all my command codes are nicely encapsulated and I should never have to change the gml file until I junk the device. I need to reference (not copy) these commands. I do this using functions:
-- Toggle plasma power
function plasma.togglePower()
gir.TriggerNode('{6F683D34-A0BE-446B-8609-2315F4817674}', plasma.CmdID.TogglePower)
end

Having not done this before or even finished, I don't know how it will all turnout. I have the following:
Input command encapsulation
Output command encapsulation
No logic in input or output "device drivers"
lua objects to encapsulate device usage models, e.g. dvd.play()
An on-screen display without video mixing or a PC tuner and allowing native hd to go thru the AVR into the plasma
I should be able to handle zoning too as I think I have good building blocks.
Comments??

Rob H
February 22nd, 2006, 12:32 AM
The IR commands are a bit of a pain because Girder cant access the defined and named commands by name. I ended up making a table that (snippet) looks like this:
plasma.CmdID = {
TogglePower=1852787992,
Sap=1852788000,
TvVideo=1852787993,}
It is tedious, but as long as I don't delete and create new USB UIRT actions, they will keep their ID (ID is the long number 1852787992). ( There must be a better way!!! Hint)
It's probably better to assign an event to each of those then you can trigger them using gir.TriggerEvent().

rbh
February 22nd, 2006, 08:04 AM
Yes, that would be a better way. All actions have an attached non-macro event. I did think of that at one time. Why didn't I do it??