View Full Version : Dm and Meridian Control
rpalmer68
December 29th, 2006, 11:39 PM
OK,
After many hours of code cutting/pasting and debugging (and the help of the various files Rob H sent me) I have finally got something to work, although I must confess I'm still flying in the dark with it!
I'm trying to control my Meridian 500 series equipment using the device manager, and I'm getting there slowly but am still having some problems.
I have attached my lua files and the meridian protocol for reference.
Here are my probelms/questions;
Currently I have the source selection working, but PowerOff and Mute don't work any suggesions as to what I've done wrong?
I can't get the Volume slider in the Receiver or Generic Action to send the command to the Meridian gear (VNxx), how do I add the Volume slider to my provider file? I've got a function AdjustVolume defined in the plugin, but I can't call it from the provider file. (I tried various things but had no luck)
With the Meridian equipment The Surround Processor (56 and DVD (59 are interconnected via a meridian comms cable and the Surround Processor is connected via RS232 to the PC. So all the DVD and Processor commands are sent through the same Serial connection. How should I add the DVD transport and menu commands to the provider file so they appear in the correct place?And I guess the other BIG question is, am I doing this correctly in terms of the correct structure for DM? I'm a bit confused with the various "types" that can/should be set and how to structure it all correctly.
Thanks
Richard
Rob H
December 30th, 2006, 02:18 AM
For the power and mute commands try adding the line
local plugin = self:GetPlugin()
as the first line in the GetDeviceTable method
Re: the volume command, try this
VolumeCommand = function(value)
if tonumber(value) then
plugin:AdjustVolume(tonumber(value))
end
end,
Note that volume levels are standardised from 0 to 100, so if your plugin has a different range you'll have to scale it accordingly. Value can also be one of the strings UP and DOWN so you may want to take account of that too.
On your third point, I'd add an additional device to the table dt for the DVD player after the main Meridian device, of type AV\\Player
Other than that, it looks fine to me.
rpalmer68
December 30th, 2006, 04:53 AM
Thanks Rob,
I'll try them shortly.
oh and sorry I put "Ben H" not "Rob H" in my original message (corrected now).
Ok, next question;
You'll notice in the meridian Rs232 pdf that PNxx selects the various presets (0 - 23).
How would I add these to my plugin/provider so that I can have a dropdown list of "Presets" with the words (Direct, Dig THX etc) but map these to the preset numbers for the actual command?
I assume I do something like this in the provider file (taken from LG sample);
local 568Presets =
{
Direct = '0',
Music = '1',
Trifield = '2',
Ambisonics = '3,
Super = '4',
Stereo = '5',
}
But I'm not sure how to use this to create/populate the "Presets" dt. (gee I'm getting into the lingo now!)
Cheers
Richard
rpalmer68
December 30th, 2006, 05:42 AM
For the power and mute commands try adding the line
local plugin = self:GetPlugin()
as the first line in the GetDeviceTable method
Re: the volume command, try this
VolumeCommand = function(value)
if tonumber(value) then
plugin:AdjustVolume(tonumber(value))
end
end,
That fixed it!
Thanks
Promixis
December 30th, 2006, 07:41 AM
Rob,
I haven't look through all your stuff carefully but wanted to clarify some stuff. When looking at the DM, we want to break devices down into their basic functions. And in some cases, an external device maybe represented by > 1 device inside Girder. Ie. a security panel may actually have HVAC devices, Security Devices, and Lighting Devices. In you case, it looks like you will a receiver device and a transport devices. I will let Rob H help you with those pieces. It sounds like you are making progress.
Rob H
December 30th, 2006, 10:31 AM
I assume I do something like this in the provider file (taken from LG sample);
local 568Presets =
{
Direct = '0',
Music = '1',
Trifield = '2',
Ambisonics = '3,
Super = '4',
Stereo = '5',
}
But I'm not sure how to use this to create/populate the "Presets" dt. (gee I'm getting into the lingo now!)
For that you could use one of the List controls e.g. Dropdown or TextSpin, you would pass in a numerically indexed table i.e. {'Direct', 'Music', 'Trifield'} as the Values property.
rpalmer68
December 30th, 2006, 04:17 PM
For that you could use one of the List controls e.g. Dropdown or TextSpin, you would pass in a numerically indexed table i.e. {'Direct', 'Music', 'Trifield'} as the Values property.
Sorry more questions....
I've added a dropdown "Presets" to the devicetable, but it doesn't appear in the list of Settings under the Generic Action.
I assume I have to call a function to add the list/dropdown somehow do I?
GetDeviceTable = function(self)
local plugin = self:GetPlugin()
local dt = {
['Meridian 568'] = {Type = 'AV\\Receiver', Name = 'Meridian 568', Description = 'Meridian 568 Surround Processor',
Sources = {'CD', 'RD', 'LP', 'TV', 'T1','T2', 'CDR', 'CB', 'DVD', 'V1', 'V2', 'LD'},
SourceCommand = function(source) self.Plugin['Source'..source](self.Plugin) end,
PowerCommand = self:MakeToggleFunc(function() plugin:PowerOn() end, function() plugin:PowerOff() end),
MuteCommand = self:MakeToggleFunc(function() plugin:Mute() end, function() plugin:UnMute() end),
PresetCommand = {Class = 'Dropdown', ID = 'Presets', Values = {"Direct", "Music", "Trifield"}, Command = function(value) plugin:ChangePreset(value) end},
VolumeCommand = function(value)
if tonumber(value) then
plugin:AdjustVolume(tonumber(value))
end
end,
},
['Meridian 598'] = {Type = 'AV\\Player', Name = 'Meridian 598', Description = 'Meridian 598 DVD Player',}
}
return dt
end,
Cheers
Richard
Rob H
December 30th, 2006, 06:15 PM
Ah, I see the problem.
You need to add the control to the optional Controls table ie
GetDeviceTable = function(self)
local plugin = self:GetPlugin()
local dt = {
['Meridian 568'] = {Type = 'AV\\Receiver', Name = 'Meridian 568', Description = 'Meridian 568 Surround Processor',
Sources = {'CD', 'RD', 'LP', 'TV', 'T1','T2', 'CDR', 'CB', 'DVD', 'V1', 'V2', 'LD'},
SourceCommand = function(source) self.Plugin['Source'..source](self.Plugin) end,
PowerCommand = self:MakeToggleFunc(function() plugin:PowerOn() end, function() plugin:PowerOff() end),
MuteCommand = self:MakeToggleFunc(function() plugin:Mute() end, function() plugin:UnMute() end),
Controls = {
Presets = {Class = 'Dropdown', ID = 'Presets', Values = {"Direct", "Music", "Trifield"}, Command = function(value) plugin:ChangePreset(value) end},
},
VolumeCommand = function(value)
if tonumber(value) then
plugin:AdjustVolume(tonumber(value))
end
end,
},
['Meridian 598'] = {Type = 'AV\\Player', Name = 'Meridian 598', Description = 'Meridian 598 DVD Player',}
}
return dt
end,
rpalmer68
December 30th, 2006, 07:35 PM
Thanks,
I was just looking at the commands linked with the AV\Player type.
There's power and transport. If this is supposed to cover DVD players, then can I suggest the default definitiont includes menu commands (Top Menu, Menu, Up, Down, Left, Right and Enter) and any other DVD related commands a well. or are these covered somewhere else?
Off to start the New year drinking, so HAPPY NEW YEAR and thanks for all your help.
regards
Richard
Rob H
December 31st, 2006, 02:20 AM
AV\Player is intended to be the base class for all player devices, not just DVD players. There will be an AV\DVDPlayer class at some point.
rpalmer68
December 31st, 2006, 06:26 PM
For that you could use one of the List controls e.g. Dropdown or TextSpin, you would pass in a numerically indexed table i.e. {'Direct', 'Music', 'Trifield'} as the Values property.
OK my device table looks like this now;
GetDeviceTable = function(self)
local plugin = self:GetPlugin()
local dt = {
['Meridian 568'] = {Type = 'AV\\Zone', Name = 'Meridian 568', Description = 'Meridian 568 Surround Processor',
Sources = {'CD', 'RD', 'LP', 'TV', 'T1','T2', 'CDR', 'CB', 'DVD', 'V1', 'V2', 'LD'},
SourceCommand = function(source) self.Plugin['Source'..source](self.Plugin) end,
PowerCommand = self:MakeToggleFunc(function() plugin:PowerOn() end, function() plugin:PowerOff() end),
MuteCommand = self:MakeToggleFunc(function() plugin:Mute() end, function() plugin:UnMute() end),
Controls = {
Presets = {Class = 'Dropdown', ID = 'Presets', Values = {"Direct", "Music", "Trifield", "Ambisonics", "Super",
"Stereo", "Mulogic", "Pro Logic", "THX", "Mono", "TV Logic", "Digital", "Dig THX", "DTS", "DTX THX", "DTS Music",
"MPEG", "MPEG THX", "MPEG Music", "MLP", "PLII Music", "PLII Movie", "PLII THX"}, Command = function(value) plugin:ChangePreset(value) end},
},
VolumeCommand = function(value)
if tonumber(value) then
plugin:AdjustVolume(tonumber(value))
end
end,
},
['Meridian 598'] = {Type = 'AV\\Player', Name = 'Meridian 598', Description = 'Meridian 598 DVD Player',
PowerCommand = self:MakeToggleFunc(function() plugin:PowerOn() end, function() plugin:PowerOff() end),
MuteCommand = self:MakeToggleFunc(function() plugin:Mute() end, function() plugin:UnMute() end),
}
}
return dt
end,
but when I change the "preset" Girder sends "PNstereo" not "PN6", how do I get the command to send the index not the actual value out?
Also, what is the syntax to setup the transport commands in the [Meridian 598] section? (I can't find an example anywhere using transports. )
I want "Stop, Play, Pause, FF, Rew, Next, Prev" as my transport options rather than the default ones.
Cheers
Richard
Rob H
January 1st, 2007, 01:49 AM
I would make your preset values into a local table ie put this code before the definition of the dt table
local PresetValues = {"Direct", "Music", "Trifield", "Ambisonics",
"Super", "Stereo", "Mulogic", "Pro Logic",
"THX", "Mono", "TV Logic", "Digital", "Dig THX",
"DTS", "DTX THX", "DTS Music", "MPEG",
"MPEG THX", "MPEG Music", "MLP", "PLII Music",
"PLII Movie", "PLII THX"}
Then use something like
Presets = {Class = 'Dropdown', ID = 'Presets', Values = PresetValues,
Command = function(value)
plugin:ChangePreset(table.findvalue(PresetValues,v alue))
end},
For the second part add a table TransportValues to the device definition ie
['Meridian 598'] = {Type = 'AV\\Player', Name = 'Meridian 598', Description = 'Meridian 598 DVD Player',
PowerCommand = self:MakeToggleFunc(function() plugin:PowerOn() end, function() plugin:PowerOff() end),
MuteCommand = self:MakeToggleFunc(function() plugin:Mute() end, function() plugin:UnMute() end),
TransportValues = {"Stop", "Play", "Pause", "FF", "Rew", "Next", "Prev"}}
Obviously you'll need a TransportCommand function as well
rpalmer68
January 1st, 2007, 06:08 AM
Ah thanks Rob.
I originally had..
Transports = {"Stop", "Play", "Pause", "FF", "Rew", "Next", "Prev"},
..which didn't work, I didn't realise it had to be "TransportValues".
So I can learn how this is all working, is there a way I could have worked this out from a definitions file somewhere? (I looked in the Transport.lua, but this didn't tell me I needed "TransportValues" set).
I think I'm almost there now, just need to add the DVD commands and then I have to work out how to get NR2 to send these commands.... I'm sure this will mean more questions I'm afraid!
Cheers
Richard
Rob H
January 1st, 2007, 07:30 AM
If you look in DeviceManager\Devices\AudioVisual.lua you'll see the definition of the Player device near the end. That's where the Transport control is created.
I'm sure this will mean more questions I'm afraid!
That's what I'm here for :)
We really need a manual for the DM.
Promixis
January 1st, 2007, 11:58 AM
If you look in DeviceManager\Devices\AudioVisual.lua you'll see the definition of the Player device near the end. That's where the Transport control is created.
That's what I'm here for :)
We really need a manual for the DM.
Where is John? I think the implementation is stable enough to start documentation.... ;)
rpalmer68
January 1st, 2007, 08:49 PM
OK I'm afraid it's NR2 time now!
I have added the
require'DMSupport' into my System Script for my ccf.
Could I get an example of how to do a couple of things please?
1) A simple button to mute my Meridian equipment; I assume I should attach lua code to the button now instead of browsing Girder for the defined action so what code do I need to attach to the button to send the MuteOn command to the equipment setup in DM? (Or how do I reference the Meridian568\MuteOn command?)
2) How do I use my volume control slider to send the volume value to the Meridian gear now? I currently have this in my OnCCFLoad
NetRemote.RegisterVariableWatch('Meridian.Volume', NetRemote.GetPlugin('Girder'))
And the slider using the Meridian.Volume variable. I assume this has all changed now?
I've looked at the Flat Style example but can't work out how to do what I need so with a couple of relevant examples I'm sure I'll be able to work the rest out!
Thanks
Richard
Rob H
January 2nd, 2007, 03:14 AM
First of all, it's probably enough to use
require 'DMCore'
When referring to a DeviceManager control you need to use the full path e.g. for my Denon receiver the full path to the main zone's mute button is
cordelia\DenonAVR\Main\Mute
where cordelia is the name of the PC that is running the DeviceManager.
Now, these names can get to be a bit unwieldy, so I'd recommend that you use bind-at-load variables for this. ie I would create a frame with the name
cordelia\DenonAVR\Main
And then put my buttons on that frame.
At present, it's a little tricky having a single button that toggles a state, so here's a new version of DMCore that helps with that.
Create your mute button (in the above example I would call it <^>\Mute) and give it an appropriate on-state that is <^>\Mute IS ON, and a Lua event action of DM.AutoToggle.
Actually, I've just created such a CCF, which should also be attached to this message.
Just change the name of the containing frame to the appropriate name for your Meridian. The CCF contains 3 buttons, a plain toggle button using the new DM.AutoToggle event and a pair of complementary buttons using the DM.Auto event.
For a volume slider, you should use the full DM path in your call to RegisterVariableWatch, but otherwise it should work the same way as it did with just Meridian.Volume
rpalmer68
January 2nd, 2007, 04:34 AM
Actually, I've just created such a CCF, which should also be attached to this message.
Just change the name of the containing frame to the appropriate name for your Meridian. The CCF contains 3 buttons, a plain toggle button using the new DM.AutoToggle event and a pair of complementary buttons using the DM.Auto event.
Thanks Rob! I wondered what the <^> was all about.
I changed the frame name to "htpc1\Meridian500\568" which is what the DM path is now (I've changed the provider file to just [568] in the dt.)
But the lua console just comes up with "DM: No DMHost!" when I press the Mute On /OFF buttons and "DM: Strange - got weird value 0" when I press the toggle button.
The plugin/provider is loaded on htpc1 and is responding and I have checked the path in DM on htpc1 to confirm it's as I entered and I have reset the lua on htpc1.
For a volume slider, you should use the full DM path in your call to RegisterVariableWatch, but otherwise it should work the same way as it did with just Meridian.Volume
So should this be;
NetRemote.RegisterVariableWatch("DM.htpc1\\Meridian500\\568\\Volume",NetRemote.GetPlugin('Girder'))
(I read somewhere I needed "\\" in there!)
Richard
Rob H
January 2nd, 2007, 04:54 AM
Well, the DM expects to see On and Off as values for toggle switches rather than 0 and 1, I'd recommend changing the provider to suit.
Don't worry about the No DMHost - that's a leftover from old code.
NetRemote.RegisterVariableWatch("htpc1\\Meridian500\\568\\Volume",NetRemote.GetPlugin('Girder'))
Or
NetRemote.RegisterVariableWatch([[htpc1\Meridian500\568\Volume]],NetRemote.GetPlugin('Girder'))
I prefer the second form myself
rpalmer68
January 2nd, 2007, 05:36 AM
Well, the DM expects to see On and Off as values for toggle switches rather than 0 and 1, I'd recommend changing the provider to suit.
Don't worry about the No DMHost - that's a leftover from old code.
Cool.
With the volume control slider I currently have the slider set to the Variable Meridian.Volume, this sends an event to Girder (Comms server: Meridian.Volume) that triggers a "Send Serial" action that passes "VN[pld3]" directly to the serial port.
Using DM I can't do this, can I? I would have thought I wouldn't need a Girder Action/Event defined as NR2 would talk directly to DM like the Mute is? And hence I shouldn't need the Variablewatch defined.
Or am I missing something here (quite possible as it's 12:30am here now.)
Richard
rpalmer68
January 2nd, 2007, 06:09 AM
I've just discovered that for some reason G5 isn't receiving the Dm commands sent from my NR2 machine, so all my last hour of testing various lua/button possibities has all been misguided as I thought I had syntax wrong not that g5 wasn't getting the messgaes.
So let me ask instead.
With the test ccf you sent me the button name is <^>\Mute:ON and the lua action is DM.Auto.
I need the button name to just be "Mute" so it can display correctly on the button, can the Lua action be somethig like <^>\Mute:ON instead? (I tried all sorts of combinations, but obviously nothing was working as comms wasn't working between NR2/g5 for some reason)
Thanks
Richard
Rob H
January 2nd, 2007, 07:49 AM
Okay, here's a new version of DMCore - this adds a function DM.Toggle, note that this must be used in a Lua OnRelease action rather than a Lua event action.
Usage as follows (for the mute button above in my example above)
DM.Toggle([[<^>\Mute]])
Note that you must use [[ and ]] to delimit the string or it won't work at all, this is because when <^> is substituted with the path of the device it is done when the page is loaded, this is then passed on to Lua so if you were to use it as e.g. "<^>\\Mute" that would end up as a Lua string constant of "cordelia\DenonAVR\Main\\Mute" which is not what would be intended.
Rob H
January 2nd, 2007, 07:56 AM
Sorry, missed this one earlier.
Cool.
With the volume control slider I currently have the slider set to the Variable Meridian.Volume, this sends an event to Girder (Comms server: Meridian.Volume) that triggers a "Send Serial" action that passes "VN[pld3]" directly to the serial port.
Using DM I can't do this, can I? I would have thought I wouldn't need a Girder Action/Event defined as NR2 would talk directly to DM like the Mute is? And hence I shouldn't need the Variablewatch defined.
Or am I missing something here (quite possible as it's 12:30am here now.)
Richard
The DM should take care of it, but you still need the RegisterVariableWatch in NR to take care of the two-way feedback if you like. I would recommend that you set the throttle option on the volume slider though, or possibly set it to only send on release.
rpalmer68
January 2nd, 2007, 08:42 AM
Sorry, missed this one earlier.
The DM should take care of it, but you still need the RegisterVariableWatch in NR to take care of the two-way feedback if you like. I would recommend that you set the throttle option on the volume slider though, or possibly set it to only send on release.
The
NetRemote.RegisterVariableWatch("DM.htpc1\\Meridia n500\\568\\Volume",NetRemote.GetPlugin('Girder'))
triggers a girder event which I shouldn't need any more, should I be removing the
NetRemote.GetPlugin('Girder') and replacing it with something else?
Richard
Rob H
January 2nd, 2007, 09:35 AM
Just drop the DM. from the beginning of the variable
rpalmer68
January 2nd, 2007, 01:15 PM
Okay, here's a new version of DMCore - this adds a function DM.Toggle, note that this must be used in a Lua OnRelease action rather than a Lua event action.
Usage as follows (for the mute button above in my example above)
DM.Toggle([[<^>\Mute]])
Note that you must use [[ and ]] to delimit the string or it won't work at all, this is because when <^> is substituted with the path of the device it is done when the page is loaded, this is then passed on to Lua so if you were to use it as e.g. "<^>\\Mute" that would end up as a Lua string constant of "cordelia\DenonAVR\Main\\Mute" which is not what would be intended.
Wow thanks Rob, great service!
Richard
rpalmer68
January 3rd, 2007, 05:08 AM
I've finally got the Volume slider working!
I've also just discovered the DM.SetValue function in the DMCore.lua, just what I need for setting my Source buttons up.. excellent.
Oh for the documentation! (hello John come back all is forgiven!)
I must say the response is MUCH faster than when I was using the Meridian serial plugin under G4, which is GREAT news as it was quite suggish under g4.
Richard
Rob H
January 3rd, 2007, 06:47 AM
Congratulations!
Interesting to hear that it's quicker
rpalmer68
January 3rd, 2007, 07:24 PM
Yes it's much quicker and seems more reliable which is good.
Now for my next problem;
When I start NR2 my volume slider defaults to 0 not the actual value that G5 has set it to.
The Netremote variable htpc1\Mridian500\568\volume is "unknown" until I move the slider then it has the correct value.
How do I make the slider track the actual value set by DM on htpc1 so the slider always has the correct value at startup or if another users change the volume from another remote?
Do I need to "Subscribe" somehow, if so I don't quite know how or what to subscribe to!
Cheers
Richard
Rob H
January 4th, 2007, 12:48 AM
Are you seeing a DM.DeviceUpdateDone event in Girder's Logger window after an NR client connects?
rpalmer68
January 4th, 2007, 01:56 AM
Are you seeing a DM.DeviceUpdateDone event in Girder's Logger window after an NR client connects?
Here's the logs from Girder when I run the client.
I did notice today that if I run 2 clients, then every time I move the slider on one client the other client resets the htpc1\Meridian500\568 volume variable to "unknown" and the slider jumps down to the bottom. So data is being moved around but it's not quite doing what I need.
Richard
rpalmer68
January 12th, 2007, 05:39 AM
Rob,
I am trying to setup my DVD menu buttons but I'm not quite sure of the syntax.
I have most of the buttons working as they are sitting on a frame named "<^>\DVDMenu" which in turn sits on a frame "htpc1\Meridian500\598" and I have named the buttons like "<^>:Enter" and used Dm.Auto in the actions.
But I have a few buttons where the name needs to be the button label, so in these cases I assigned the action as
DM.SetValue("htpc1\\Meridian500\\598", "DVDMenu","TopMenu" )
this works fine, but I was hoping to use the frame name rather than hard coding the DM path into the action. Is there a way of me doing this?
DM.SetValue("<^^>","DVDMenu","TopMenu" ). I've tried various things but have has no success.
Cheers
Richard
Rob H
January 12th, 2007, 09:08 AM
If you're using Lua then you need to use [[ and ]] to delimit the string because it will contain a number of \ characters.
So,
DM.SetValue([[<^^>]],"DVDMenu","TopMenu" )
should work.
rpalmer68
January 18th, 2007, 01:22 PM
I need some more help....
1) I need to cater for VolumeUp, VolumeDown as well as my volume slider.
Can I use the VolumeCommand somehow to step +1 or -1?
I created a StepVolume control in my provider file, but I assume I should be using the standard volume control somehow.
2) How do I enable feedback from my Meridian 568 so that DM knows the current volume setting?
The Meridian 568 sends "Trifield XX" out every time the volume changes where XX is the current volume. Can I trap the XX and set the DM volume with this so that all my DM clients get volume changes when they happen?
Eg. Girder sets the volume when I start TV playback based on ther time of day (quiet early/late, louder during the day) so I need the NR clients to update their sliders based on the volume Girder sets.
My current DM files are posted in this thread
http://www.promixis.com/forums/showthread.php?t=16052
Cheers
Richard
Rob H
January 18th, 2007, 01:51 PM
1) The standard volume control will take a value of '+' and '-' and will increment or decrement the volume accordingly.
In a CCF you can use a DMAuto event with a name of e.g. control:+ where control is the DeviceManager path to the control.
2) You'll need to add code to your ReceiveResponse method in the serial device to decode the Trifield response. Then call the Notify method which will inform the provider about this via the PluginEventHandler method of your provider. You may need to tweak the PluginEventHandler method to map from the serial device's idea of a device and control to a real DM device.
rpalmer68
January 18th, 2007, 07:30 PM
[quote=Rob H;110528]
1) The standard volume control will take a value of '+' and '-' and will increment or decrement the volume accordingly.
In a CCF you can use a DMAuto event with a name of e.g. control:+ where control is the DeviceManager path to the control.[quote]
Thanks Rob,
I'm not sure how to trap the +/- and send this to the serial plugin.
My device table for the 568 looks like this and I have "VolumeUP" and "VolumeDOWN" defined in the serial plugin for sending the discrete Up/DOWN command to the 568. (I tried to have Volume+ and Volume-, but they don't work as it creates Lua errors in girder.)
['568'] = {Type = 'AV\\Zone', Name = 'Meridian 568', Description = 'Meridian 568 Surround Processor',
Sources = {'CD', 'RD', 'LP', 'TV', 'T1','T2', 'CDR', 'CB', 'DVD', 'V1', 'V2', 'LD'},
SourceCommand = function(value) self.Plugin['Source'..value](self.Plugin) end,
PowerCommand = self:MakeToggleFunc(function() plugin:PowerOn() end, function() plugin:PowerOff() end),
MuteCommand = self:MakeToggleFunc(function() plugin:Mute() end, function() plugin:UnMute() end),
Controls = {
Presets = {Class = 'Dropdown', ID = 'Presets', Values = PresetValues,
Command = function(value) plugin:ChangePreset(table.findvalue(PresetValues,v alue))end},
-- StepVolume = {Class = 'Dropdown', ID = 'StepVolume', Values = {"VolumeUP", "VolumeDOWN"},
-- Command = function(value) self.Plugin[value](self.Plugin) end},
},
VolumeCommand = function(value)
if tonumber(value) then
plugin:AdjustVolume(tonumber(value))
print('got volume slider value')
else
self.Plugin['Volume'..value](self.Plugin)]
print('Got Volume Up or Down')
end
end,
},
I created a Volume Up button with this action
DM.SetValue("htpc1\\Meridian500\\568", "Volume","UP" ).
As you can see I tried to trap anything not a number and send this to the serial plugin (but it didn't work), but I have a feeling I'm supposed to do it another way with the button assigned
DM.SetValue("htpc1\\Meridian500\\568", "Volume","+" ) but don't quite know how to code it in the VolumeCommand section of the provider file.
So can you please show me how to trap the DM.SetValue("htpc1\\Meridian500\\568", "Volume","+" and send this as VolumeUP to my serial plugin whilst still catering for the existing Volume slider using the AdjustVolume command?
Cheers
Richard
Rob H
January 19th, 2007, 12:06 AM
Here's the equivalent function from my Denon provider
local VolFunc = function(value)
if tonumber(value) then
zone:SetPercentVol(value)
elseif string.upper(value) == 'UP' then
zone:VolUp()
elseif string.upper(value) == 'DOWN' then
zone:VolDown()
end
end
Although once you have feedback working and the DM knows the current value of volume then you shouldn't need this as the control will handle + and - itself.
rpalmer68
January 19th, 2007, 02:13 AM
Although once you have feedback working and the DM knows the current value of volume then you shouldn't need this as the control will handle + and - itself.
Thanks,
But I'd still need to tell the control what to send to the serial plugin somehow as it won't know what to do with a + or - or is this then done somewhere else?
R
rpalmer68
January 19th, 2007, 05:11 AM
Here's the equivalent function from my Denon provider
local VolFunc = function(value)
if tonumber(value) then
zone:SetPercentVol(value)
elseif string.upper(value) == 'UP' then
zone:VolUp()
elseif string.upper(value) == 'DOWN' then
zone:VolDown()
end
end
Rob, this doesn't seem to work.
NR has button action set to
DM.SetValue("htpc1\\Meridian500\\568", "Volume","UP" )
My provider file has
VolumeCommand = function(value)
if tonumber(value) then
plugin:SetPercentVol(tonumber(value))
print('Got Volume Percent')
elseif string.upper(value) == 'UP' then
plugin:VolUp()
print('Got Volume UP')
elseif string.upper(value) == 'DOWN' then
plugin:VolDown()
print('Got Volume DOWN')
else
print('Got unknown Volume Command')
end
end,
When I press the button the Girder log shows \htpc1\Meridian500\568\volume so I know somethings being sent, but nothing happens with the volume and the Print commands aren't executed either.
If I move my volume slider the volume changes and the lua console gets the "Got Volume Percent" message.
What am I doing wrong?
Cheers
Richard
Rob H
January 19th, 2007, 06:15 AM
The VolumeCommand is a property of the device not the provider. Take a look at my Denon provider (included here) at the GetDeviceTable method.
Rob H
January 19th, 2007, 06:16 AM
Thanks,
But I'd still need to tell the control what to send to the serial plugin somehow as it won't know what to do with a + or - or is this then done somewhere else?
R
This is the SetValue method of the Range control (a superclass of the Volume control)
SetValue = function (self,newvalue)
local value
local _, _, sign = string.find(newvalue, '^([+-])$')
if sign then
increment = tonumber(self.Values.Increment) or 1
if sign == '+' then
value = self.Value + increment
elseif sign == '-' then
value = self.Value - increment
end
else
value = tonumber (newvalue)
end
if value then
value = math.min (value,self.Values.Max)
value = math.max (value,self.Values.Min)
return Base.SetValue (self,value) -- makes change
else
return false -- invalid value
end
end,
As you can see it knows about '+' and '-'
rpalmer68
January 19th, 2007, 01:53 PM
The VolumeCommand is a property of the device not the provider. Take a look at my Denon provider (included here) at the GetDeviceTable method.
I'm afraid you've lost me (again). Are you saying I shouldn't be using VolumeCommand when defining my device table in the provider file?
Although you define VolFunc and then assign VolumeCommand=VolFunc further down, isn't this the same as just defining the VolumeCommand in one step?
I feel like I'm starting to waste a lot of your time with all these questions given there is no documentation for me to refer to in understanding what's ACTUALLY required and how a provider file should be constructed in the first place.
Would it be easier/quicker for you just to "Fix" my file and let me learn from what you're done?
If so, could you please fix the file(s) so to support a volume slider where if I change the volume from say a girder Generic DM action, the NR slider should update. And of course it should work with the SetValue +/- business.
We're only working with one zone as well, so that should simplify things I would hope.
As mentioned above my files are attached here;
http://www.promixis.com/forums/showthread.php?t=16052
Cheers
Richard
Rob H
January 19th, 2007, 02:15 PM
Sorry, I misunderstood what you were saying in your earlier post - it looked as though the VolumeCommand function was at the provider level rather than in GetDeviceTable.
Do you have functions SetPercentVol, VolUp and VolDown in your current serial device file? I see AdjustVolume, VolumeUP and VolumeDOWN in the files you have uploaded.
rpalmer68
January 19th, 2007, 03:29 PM
Do you have functions SetPercentVol, VolUp and VolDown in your current serial device file? I see AdjustVolume, VolumeUP and VolumeDOWN in the files you have uploaded.
Yes I changed them to SetPercentVol etc as an experiment, matching serial file attached.
The thing is the Print lines under Up/DOWN aren't being executed which I assume means the Up/DOWN elseif's aren't being triggered. Even though the Girder log shows "Comms server ... htpc1\Meridian500\568\volume"
Having said this, I shouldn't need up/down should I? Can't I just use Volume:+/- and then based on the SetValue code you posted above the VolumeCommand will do a SetPercentVol? This is assuming the DM has my current value for the volume, but it should as I set it from Girder (DM receiver action) when I start my system (or do I need to do extra code for this)?
R
Rob H
January 19th, 2007, 03:58 PM
Hmm... I would expect the elseifs to be called. Can you add a print(value) before the if statement in the VolumeCommand function.
I'd recommend you add the code to monitor the volume to your serial device to allow the volume + and - to work properly.
rpalmer68
January 19th, 2007, 04:10 PM
I'd recommend you add the code to monitor the volume to your serial device to allow the volume + and - to work properly.
You mean test the response from the 568 and feed this back in to the DM?
Cheers
Richard
Rob H
January 19th, 2007, 04:19 PM
Yep, that's it.
rpalmer68
January 20th, 2007, 01:57 AM
[quote=Rob H;110590]Hmm... I would expect the elseifs to be called. Can you add a print(value) before the if statement in the VolumeCommand function.
[quote]
I would have too!
Added the print and still don't get anything from the buttons only from the slider.
I tried my Mute button that uses a SetValue as well and this still works, so it's just the Volume ones.
Could it be related to the
NetRemote.RegisterVariableWatch([[htpc1\Meridian500\568\Volume]],NetRemote.GetPlugin('Girder'))
in the system lua file that's used for the slider?
Also as a test I tried replacing the "UP" in the SetValue of the button with a "+" and then I get the following error.
EventHandler: ...s\Girder5\luascript\DeviceManager/Controls/Range.lua:42: attempt to perform arithmetic on field `Value' (a boolean value)
stack traceback:
...s\Girder5\luascript\DeviceManager/Controls/Range.lua:42: in function `SetValue'
...irder5\luascript\DeviceManager/ConnectionManager.lua:470: in function `ProcessNREvent'
...irder5\luascript\DeviceManager/ConnectionManager.lua:103: in function <...irder5\luascript\DeviceManager/ConnectionManager.lua:102>
not sure if this is expected or not?
R
Rob H
January 20th, 2007, 02:18 AM
The RegisterVariableWatch shouldn't have any effect.
Yes, I would probably expect that error to happen if the Value of the volume control hasn't yet been assigned (it defaults to false). It should work if you've used the slider first though, although it will actually require the feedback from the serial device to work properly.
Ah, I bet that's the problem... You're sending the volume UP to the control, but the control's SetValue method is rejecting it as invalid input and so never passes that on to the provider.
rpalmer68
January 20th, 2007, 02:31 AM
Ah, I bet that's the problem... You're sending the volume UP to the control, but the control's SetValue method is rejecting it as invalid input and so never passes that on to the provider.
Is there a quick way of setting the Volume value to something valid to test this? (Before I head off trying to get the serial feedback working.)
Using the slider first doesn't help, neither does creating a girder DM Receiver action that sets the volume.
I also tried to find the volume value in the Variable Inspector but couldn't find it (or didn't look in the right place)
Also do you have an example serial file that provides feedback to the DM?
I've looked at the ones in the serial directry and I don't think they are written with DM in mind. (They certainly don't have a NOTIFY call anywhere.)
Richard
Rob H
January 20th, 2007, 08:07 AM
Here's my Denon receiver plugin which uses Notify to inform the provider of the current volume; see lines 444 - 460
rpalmer68
January 20th, 2007, 04:11 PM
Here's my Denon receiver plugin which uses Notify to inform the provider of the current volume; see lines 444 - 460
Thanks,
I need to get the volume value from the returned string, I've been reading through the lua manual but can't quite work it out.
I know I can test with tonumber() to check I get a number, but how do I extract the last 2 digits from the returned string ("Trifield 55") to test them?
Thanks
Richard
Rob H
January 20th, 2007, 04:22 PM
Try this regular expression
local _, _, digits = string.find(value, '%s(%d-)$')
rpalmer68
January 20th, 2007, 07:09 PM
Thanks Rob,
With the Notify, what is the first paramater?
In your file I assume it means your "Main" Zone, but how would I relate this to my definition of htpc1\\Meridian500\568\Volume?
self:Notify('Main', 'Volume', RawVolume)
Would I put
self:Notify('568', 'Volume', RawVolume)
I always get "Code is nil". What is 'self.code' supposed to be?
ReceiveResponse = function ( self)
if not self.code then
print('Code is nil!!!')
elseif self:IsDataAvailable() and self.data then
--gir.TriggerEvent ('DENON:'..data,18)
local cmd = string.sub(self.data, 1, 2)
if cmd then
local func = self.Responses[cmd]
if func then
local status, err = pcall(func, self.Settings, self.data)
if err then
print(err)
end
end
end
end
Super.ReceiveResponse (self)
end,
Cheers
Richard
Rob H
January 21st, 2007, 04:39 AM
Yes, you'd probably put '568' in as the device name (although I have to say I'm not 100% happy with a purely numeric device name).
My Denon receiver plugin is based on serial.classes.Queued2 whereas yours is based on serial.classes.Queued.
In Queued2 the ReceiveResponse method only takes the self parameter, and the class has properties data and code, but in Queued, data and code are additional parameters.
I would think the easiest way to correct this is to change your base class to serial.Classes.Queued2. The only other change you may have to make is to change the line
self.Serial:RxClear()
to
self:RxClear()
in your Initialize method.
rpalmer68
January 21st, 2007, 06:34 AM
That fixed it!
I can now report that feedback is working, changing the volume manually on the 568 moves the slider in NR and the Volume:+/- also work in NR.
I'll update my files in the Meridian DM thread to these new ones.
Cheers
Richard
Promixis
January 21st, 2007, 06:50 AM
Hi Richard, if you post them here I will include them in the standard G5 install.
rpalmer68
January 21st, 2007, 12:26 PM
Hi Richard, if you post them here I will include them in the standard G5 install.
Probably not ready for that yet!
You mentioned in another thread about a new transport system for G5, can you elaborate on this a bit so I know if I need to change my provider files please?
Cheers
Richard
rpalmer68
January 21st, 2007, 12:38 PM
Yes, you'd probably put '568' in as the device name (although I have to say I'm not 100% happy with a purely numeric device name).
I'm not that happy with my "structure" either, so am open to suggestions. (Mike/Rob).
The problem is the Meridain equipment works a bit differently to other AV equipment.
Normally if you had a surround processor/amp and DVD player you would have 2 serial connections and thus 2 serial plugins/provider files.
With Meridian the equipment is all connected together with it's own comms so you communicate with everything though 1 serial line, and hence 1 serial plugin/provider.
So hence the reason I created a [568] and [598] in the device table so to seperate the Processor from the DVD. When people use the Girder DM action "Receiver" they can select htpc1\Meridian500\568 as the target and the DVD control/transport stuff is tied to the 598.
So where you would normally hae htpc1\Meridian568\Main\Volume I end up with htpc1\Meridian500\568\Volume.
How would you suggest it be setup, as I'd like to make it as "standard" as possible if I can.
Cheers
Richard
Promixis
January 21st, 2007, 12:46 PM
Richard, we see this for many devices - ie AV with mult zones, security controllers with lighting and hvac functions.
So there is one serial file and one provider with the provider creating as many devices as needed.
You will be able to, but do not need to, move your serial file to the new transport system. It will make building new devices with their own menus much easier. Not needed though.
Rob H
January 21st, 2007, 03:02 PM
So hence the reason I created a [568] and [598] in the device table so to seperate the Processor from the DVD. When people use the Girder DM action "Receiver" they can select htpc1\Meridian500\568 as the target and the DVD control/transport stuff is tied to the 598.
I would probably suggest using 'Processor' and 'DVD' in that case, rather than tying it to the model numbers.
rpalmer68
January 22nd, 2007, 05:08 AM
I would probably suggest using 'Processor' and 'DVD' in that case, rather than tying it to the model numbers.
Changed.
Now my next question.
I'm trying to extract the first part of the Response to try to feedback the curently selected Preset.
The
local _, _, RawVolume = string.find(self.data, '%s(%d-)$') is giving me the volume digits, but I can't work out how to get the first set of characters. I tried all sorts of combinations and even read the manual, but can't get what I need.
So how do I extract the first set of characters up to the first space?
Actualy if you have time could you explain the code '%s(%d-)$' and the response to the above question so I can understand how these patterns are constructed?
Cheers
Richard
Promixis
January 22nd, 2007, 05:51 AM
see http://www.lua.org/pil/20.html
rpalmer68
January 22nd, 2007, 06:26 AM
see http://www.lua.org/pil/20.html
I'd read this, but couldn't get it to work.
If I print(self.data) I get
Music 56
My code looks like this, but I always get "Received Preset: nil" returned even hard coding the length of string to return with the string.sub
ReceiveResponse = function (self)
if not self.code then
print('Code is nil!!!')
elseif self:IsDataAvailable() and self.data then
print('Received response: '..self.data)
local _, _, RawVolume = string.find(self.data, '%s(%d-)$')
local _, _, RawPreset = string.sub(self.data, 1,5)
if tonumber(RawVolume) then
print("Volume received = "..RawVolume)
self:Notify('Processor', 'Volume', RawVolume)
end
if RawPreset == nil then
print("Received Preset: nil")
else
print("Received Preset: "..RawPreset)
end
end
Super.ReceiveResponse (self)
end,
Sorry, but I'm lost!
Richard
Rob H
January 22nd, 2007, 07:32 AM
Changed.
Now my next question.
I'm trying to extract the first part of the Response to try to feedback the curently selected Preset.
The
local _, _, RawVolume = string.find(self.data, '%s(%d-)$') is giving me the volume digits, but I can't work out how to get the first set of characters. I tried all sorts of combinations and even read the manual, but can't get what I need.
So how do I extract the first set of characters up to the first space?
Actualy if you have time could you explain the code '%s(%d-)$' and the response to the above question so I can understand how these patterns are constructed?
Cheers
Richard
Okay let's take the string '%s(%d-)$'
%s matches a single space
%d matches a single digit
%d- matches the shortest sequence of digits
$ matches the end of the input string
Anything in parentheses is what is known as a capture which is how it knows that this is the thing you are interested in.
To match a string like Music 55 you could use a pattern like this
local _, _, prefix, value = string.find(aString, '^(%w-)%s+(%d-)$')
^ matches the start of the string.
The first capture (%w-) matches the shortest sequence of characters that can form a word (ie non whitespace and non-punctuation)
%s+ matches the longest sequence of spaces
and the rest of the pattern is as before.
rpalmer68
January 22nd, 2007, 03:33 PM
OK I have this;
ReceiveResponse = function (self)
if not self.code then
print('Code is nil!!!')
elseif self:IsDataAvailable() and self.data then
print('Received response: '..self.data)
local _, _, prefix, ReturnedPreset = string.find(self.data, '^(%w-)%s+(%d-)$')
local _, _, ReturnedVolume = string.find(self.data, '%s(%d-)$')
if tonumber(ReturnedVolume) then
print("Volume received = "..ReturnedVolume)
self:Notify('Processor', 'Volume', ReturnedVolume)
end
if ReturnedPreset == nil then
print("Returned Preset: nil")
else
print("Returned Preset: "..ReturnedPreset)
end
end
Super.ReceiveResponse (self)
end,
And I get this back in the log;
Received response: VP
Returned Preset: nil
Received response: Music 58
Volume received = 58
Meridian500: Publishing event Processor 58
Got Meridian500 Event: nil Volume 58
Device id: Processor
Returned Preset: 58
If I try
local _, _, prefix, ReturnedPreset = string.find(self.data, '^(%w-)%s')
or
local _, _, prefix, ReturnedPreset = string.find(self.data, '^(%a-)%s')
I get
Returned Preset: nil returned but I would expect "Music"
Richard
Rob H
January 22nd, 2007, 03:44 PM
Try this code :-
ReceiveResponse = function (self)
if not self.code then
print('Code is nil!!!')
elseif self:IsDataAvailable() and self.data then
print('Received response: '..self.data)
local _, _, prefix, value = string.find(self.data, '^(%w-)%s+(%d-)$')
print('Returned prefix:', prefix)
if tonumber(value) then
print("Volume received = "..value)
self:Notify('Processor', 'Volume', value)
end
Super.ReceiveResponse (self)
end,
rpalmer68
January 22nd, 2007, 06:59 PM
Added an extra "end" and it's working.
Thanks
R
Rob H
January 23rd, 2007, 03:48 AM
Oops, sorry - it's difficult typing code online. Glad it's working now.
rpalmer68
January 24th, 2007, 01:35 AM
Oops, sorry - it's difficult typing code online. Glad it's working now.
That's cool.
Now working on getting NR showing current input and preset status based on the feedback from the Meridian equipment.
I hope I can get that done without too many more questions!
Richard
rpalmer68
February 28th, 2007, 03:35 AM
Well after 2 weesk of being without my system during our house move, I'm back on my little project.
I have upgraded to Girder 514 and NR2 .88 and am now experiancing a new problem.
I have been testing my ccf file on my laptop and have most things working so copied the ccf and lua files to my PPC (Dell x51v WM5) to see how it looked/work on that.
Low and behold for some reason the DVD controls don't work as expected.
The TopMenu and Menu work, but none on the transport or arrows work on the PPC but they all work on the laptop.
I'm running .88 on both machines, the girder plugin uses the machine name htpc1 as the host and the "test" passes on both machines.
Any ideas as to why only TopMenu and Menu work on the PPC? I know these use different syntax to send the commands compared to the other buttons, but in theory the other buttons should work if they work on the laptop.
Cheers
Richard
Rob H
February 28th, 2007, 04:02 AM
Just to check, you do have DMSupport.lua and DMCore.lua and the DM directory in the luascript directory on the PPC?
rpalmer68
February 28th, 2007, 04:05 AM
Just to check, you do have DMSupport.lua and DMCore.lua and the DM directory in the luascript directory on the PPC?
Yes, yes and yes.
The volume slider and Mute work along with the TopMenu and Menu, but the transport and arrows don't.
Wierd!
Richard
rpalmer68
March 1st, 2007, 04:38 AM
Just thought I'd mention I'm having the same problem with NR2 (.89) and the DVD transport/arrow buttons not working on PPC.
I have also rolled back to .84 and .86 and they don't work either on the PPC but do on laptop.
Why do I have that funny feeling I'm missing something obvious???
Richard
Rob H
March 1st, 2007, 07:34 AM
Do you have a NetRemote.log file on your PPC? I think you'll find it in Program Files\NetRemote or Program Files\Promixis\NetRemote - can't check at the moment because my PPC doesn't seem to want to sync just now!
You may find some error messages there.
rpalmer68
March 1st, 2007, 01:26 PM
Do you have a NetRemote.log file on your PPC? I think you'll find it in Program Files\NetRemote or Program Files\Promixis\NetRemote - can't check at the moment because my PPC doesn't seem to want to sync just now!
You may find some error messages there.
Do now, log is attached.
When I press a transport button on the PPC the following is logged
08:17:57.78743] Lua] Syntax error
[string "NRLUA"]:1: invalid control char near `char(0)'
I also noticed another error a bit earlier in the log;
08:17:34.55687] ScriptEngine] \Program Files\NetRemote/luascript/DMCore.lua:165: bad argument #1 to `foreach' (table expected, got userdata)
Any suggestions?
Cheers
Richard
Rob H
March 2nd, 2007, 02:33 AM
You've hit a couple of bugs
#1 is a long standing bug that I thought had been fixed - add a space after the name of the Lua events ie instead of 'DM.Auto' use 'DM.Auto ' (without the quotes).
#2 is a new one - it seems that plugin:GetInstances() now returns a userdata rather than a table - not sure when this happened. Ben? Greg? How do I get at the the table of plugin instances now?
Ben S
March 2nd, 2007, 02:26 PM
Hi Rob -
Can you try the attached NetRemote? I believe I've found the issue.
rpalmer68
March 2nd, 2007, 07:18 PM
Hi Rob -
Can you try the attached NetRemote? I believe I've found the issue.
Is this for PC or PPC (or both?)
And which issue should it fix?
Cheers
Richard
Rob H
March 3rd, 2007, 04:54 AM
That's certainly fixed the problem with plugin:GetInstances()
Ben S
March 3rd, 2007, 08:23 AM
Great Rob - I'll do another NetRemote release today. Sorry about the snafu.
rpalmer68
March 3rd, 2007, 10:49 AM
Great Rob - I'll do another NetRemote release today. Sorry about the snafu.
Any chance the DM.Auto bug can be fixed as well Ben?
Cheers
Richard
Ben S
March 3rd, 2007, 12:21 PM
I think that's a Rob one, unless I'm mistaken, Richard. Rob is the DM genius. :)
Rob H
March 3rd, 2007, 03:02 PM
That one is related to the PPC and the invalid control character near char(0) that I mentioned to you yesterday.
rpalmer68
March 4th, 2007, 04:10 AM
That one is related to the PPC and the invalid control character near char(0) that I mentioned to you yesterday.
I saved the netremote.exe to my PPC, but it doesn't run, it says it's not for the OS (WM5). Guess I'll await .90 release.
Now can I ask who's looking after the fix for the DM.Auto bug?
Cheers
Richard
rpalmer68
March 6th, 2007, 12:17 PM
Great Rob - I'll do another NetRemote release today. Sorry about the snafu.
Hi Ben,
Is .90 close?
Cheers
Richard
Ben S
March 7th, 2007, 07:58 PM
The exe was for Windows only, but looks like it still doesn't fix the issue.
Richard - yes, close. Sorry for the delay.
Powered by vBulletin® Version 4.1.8 Copyright © 2012 vBulletin Solutions, Inc. All rights reserved.