Jump to content
C4 Forums | Control4

Converting a .c4i -> .c4z


blackfiveo1

Recommended Posts

I am trying to convert my Kodi driver to a c4z so that I can add customized icons using the c4z Image scaler

 

I watched a tutorial video but the c4i driver i have does not even have a <capabilities> tag, so my only thought is that I have that in the wrong place. I double checked all my paths and the name of my drive when i zip it is kodi.c4z, when I add it into the Project it gets just the default control4 icon. Here is my driver.xml and I attached my kodi.c4z if anyone has some time to test it or help me troubleshoot. thanks

<devicedata>
    <copyright>Copyright 2016</copyright>
    <creator>Jason Powell</creator>
    <manufacturer>kodi.TV</manufacturer>
    <name>kodi</name>
    <model>kodi HTPC</model>
    <created>12/19/2015 7:58 AM</created>
    <modified>02/24/2017 12:00 AM</modified>
    <version>2</version>
	<small image_source="c4z">icons/device_sm.png</small>
	<large image_source="c4z">icons/device_lg.png</large>
    <control>lua_gen</control>
    <controlmethod>ip</controlmethod>
    <driver>DriverWorks</driver>
    <search_type>c4:av_gen</search_type>
    <proxies qty="1">
        <proxy proxybindingid="5001" name="kodi" Image_source="c4z" large_image="icons/device_lg.png" small_image="icons/device_sm.png">media_player</proxy>
    </proxies>
    <connections>
        <connection proxybindingid="5001">
            <id>2000</id>
            <facing>6</facing>
            <connectionname>OUTPUT</connectionname>
            <type>5</type>
            <consumer>False</consumer>
            <audiosource>False</audiosource>
            <videosource>True</videosource>
            <linelevel>True</linelevel>
            <classes>
                <class>
                    <classname>VGA</classname>
                </class>
                <class>
                    <classname>HDMI</classname>
                </class>
                <class>
                    <classname>DVI</classname>
                </class>
                <class>
                    <classname>SVIDEO</classname>
                </class>
                <class>
                    <classname>COMPOSITE</classname>
                </class>
                <class>
                    <classname>COMPONENT</classname>
                </class>
            </classes>
        </connection>
        <connection proxybindingid="5001">
            <id>4000</id>
            <facing>6</facing>
            <connectionname>OUTPUT</connectionname>
            <type>6</type>
            <consumer>False</consumer>
            <audiosource>True</audiosource>
            <videosource>False</videosource>
            <linelevel>True</linelevel>
            <classes>
                <class>
                    <classname>DIGITAL_COAX</classname>
                </class>
                <class>
                    <classname>DIGITAL_OPTICAL</classname>
                </class>
                <class>
                    <classname>STEREO</classname>
                </class>
            </classes>
        </connection>
        <connection>
            <id>5001</id>
            <facing>6</facing>
            <connectionname>MEDIA_PLAYER</connectionname>
            <type>2</type>
            <consumer>False</consumer>
            <audiosource>False</audiosource>
            <videosource>True</videosource>
            <linelevel>False</linelevel>
            <classes>
                <class>
                    <classname>MEDIA_PLAYER</classname>
                </class>
            </classes>
        </connection>
        <connection>
            <id>6004</id>
            <facing>1</facing>
            <connectionname>XBMC UDP Connection</connectionname>
            <type>4</type>
            <consumer>True</consumer>
            <audiosource>False</audiosource>
            <videosource>False</videosource>
            <linelevel>True</linelevel>
            <classes>
                <class>
                    <classname>UDP</classname>
                    <ports>
                        <port>
                            <number>9777</number>
                            <auto_connect>True</auto_connect>
                            <monitor_connection>True</monitor_connection>
                            <keep_connection>True</keep_connection>
                        </port>
                    </ports>
                </class>
            </classes>
        </connection>
        <connection proxybindingid="5001">
            <id>7000</id>
            <facing>6</facing>
            <connectionname>Room Selection - OUTPUT</connectionname>
            <type>7</type>
            <consumer>False</consumer>
            <audiosource>True</audiosource>
            <videosource>True</videosource>
            <linelevel>True</linelevel>
            <classes>
                <class>
                    <classname>VIDEO_SELECTION</classname>
                </class>
                <class>
                    <classname>AUDIO_VOLUME</classname>
                </class>
                <class>
                    <classname>AUDIO_SELECTION</classname>
                </class>
            </classes>
        </connection>
    </connections>
    <config>
        <power_management_method>AlwaysOn</power_management_method>
        <power_command_delay>0</power_command_delay>
        <power_delay>0</power_delay>
        <power_command_needed>False</power_command_needed>
        <documentation>
Make sure the "Allow programs on other systems to control XBMC" setting in the network settings of XBMC is enabled

Keymap
---------------------------------------------------------------------------------------
|.Button....|.Navigation...|.Video.Playback......|.Audio.Playback....|.Picture.Viewer.|
---------------------------------------------------------------------------------------
|.Red.......|..............|.Disable.Subtitle....|...................|................|
|.Green.....|..............|.Next.Subtitle.......|...................|................|
|.Yellow....|..............|.....................|...................|................|`	
|.Blue......|..............|.....................|...................|................|
|-----------|--------------------------------------------------------|----------------|
|.GUIDE.....|..............|.....................|.Toggle.Visualizer.|................|
|.RECALL....|.Go.Back......|.Tiny.Step.Backward..|...................|................|
|.PAGE.UP...|.Page.Up......|.....................|...................|................|
|.PAGE.DOWN.|.Page.Down....|.....................|...................|................|
|-----------|--------------|---------------------|-------------------|----------------|
|.UP........|.Move.Up......|.Big.Step.Forward....|.Move.Up...........|................|
|.DOWN......|.Move.Down....|.Big.Step.Backward...|.Move.Down.........|................|
|.LEFT......|.Move.Left....|.Small.Step.Backward.|.Move.Left.........|................|
|.RIGHT.....|.Move.Right...|.Small.Step.Forward..|.Move.Right........|................|
|.ENTER.....|.Select.......|.....................|.Select............|................|
|-----------|--------------|---------------------|-------------------|----------------|
|.INFO......|.Show.Info....|.Show.Info...........|.Show.Info.........|................|
|.MENU......|.Context.Menu.|.Show.OSD............|...................|................|
|.CANCEL....|.Go.Back......|.....................|...................|................|
|-----------|--------------|---------------------|-------------------|----------------|
|.PLAY......|..............|.Play/Pause..........|.Play/Pause........|................|
|.PAUSE.....|..............|.Play/Pause..........|.Play/Pause........|................|
|.STOP......|..............|.Stop................|.Stop..............|................|
|-----------|--------------|---------------------|-------------------|----------------|
|.SKIP.FWD..|..............|.Skip.Next...........|.Skip.Next.........|................|
|.SKIP.REV..|..............|.Skip.Previous.......|.Skip.Previous.....|................|
|.SCAN.FWD..|..............|.Fast.Forward........|.Fast.Forward......|................|
|.SCAN.REV..|..............|.Rewind..............|.Rewind............|................|
|-----------|--------------|---------------------|-------------------|----------------|
|.NUMBER.1..|.1............|.....................|...................|................|
|.NUMBER.2..|.2./.ABC......|.....................|...................|................|
|.NUMBER.3..|.3./.DEF......|.....................|...................|................|
|.NUMBER.4..|.4./.GHI......|.....................|...................|................|
|.NUMBER.5..|.5./.JKL......|.....................|...................|................|
|.NUMBER.6..|.6./.MNO......|.....................|...................|................|
|.NUMBER.7..|.7./.PQRS.....|.....................|...................|................|
|.NUMBER.8..|.8./.TUV......|.....................|...................|................|
|.NUMBER.9..|.9./.WXYZ.....|.....................|...................|................|
|.STAR......|..............|.....................|...................|................|
|.NUMBER.0..|.0............|.....................|...................|................|
|.POUND.....|..............|.....................|...................|................|
---------------------------------------------------------------------------------------

		</documentation>
	<capabilities>
		<audio_consumer_count>1</audio_consumer_count>
		<audio_provider_count>1</audio_provider_count>
		<can_be_dvr>True</can_be_dvr>
		<has_channel_up_down>True</has_channel_up_down>
		<has_discrete_channel_select>True</has_discrete_channel_select>
		<has_toad_input_select>False</has_toad_input_select>
		<video_consumer_count>2</video_consumer_count>
		<video_provider_count>1</video_provider_count>
		<navigator_display_option proxybindingid="5001">
			<display_icons>
				<Icon height="140" width="140">controller://driver/kodi/icons/device/experience_140.png</Icon>
				<Icon height="130" width="120">controller://driver/kodi/icons/device/experience_130.png</Icon>
				<Icon height="120" width="120">controller://driver/kodi/icons/device/experience_120.png</Icon>
				<Icon height="110" width="110">controller://driver/kodi/icons/device/experience_110.png</Icon>
				<Icon height="100" width="100">controller://driver/kodi/icons/device/experience_100.png</Icon>
				<Icon height="90" width="90">controller://driver/kodi/icons/device/experience_90.png</Icon>
				<Icon height="80" width="80">controller://driver/kodi/icons/device/experience_80.png</Icon>
				<Icon height="70" width="70">controller://driver/kodi/icons/device/experience_70.png</Icon>
				<Icon height="60" width="60">controller://driver/kodi/icons/device/experience_60.png</Icon>
				<Icon height="50" width="50">controller://driver/kodi/icons/device/experience_50.png</Icon>
				<Icon height="40" width="40">controller://driver/kodi/icons/device/experience_40.png</Icon>
				<Icon height="30" width="30">controller://driver/kodi/icons/device/experience_30.png</Icon>
				<Icon height="20" width="20">controller://driver/kodi/icons/device/experience_20.png</Icon>
			</display_icons>
		</navigator_display_option>
	</capabilities>
        <script><![CDATA[gPacketSectionA = "XBMC"..string.char(2)..string.rep(string.char(0),2)..string.char(3)..string.rep(string.char(0),3)..string.char(1)..string.rep(string.char(0),3)..string.char(1)..string.char(0)
gPacketSectionB = string.rep(string.char(0),2)..string.char(1)..string.char(168)..string.rep(string.char(0),10)..string.rep(string.char(0),3)..string.char(35)..string.rep(string.char(0),2)..string.char(75)..string.char(66)..string.char(0)
idWakeOnLan = 0
g_debugprint = true
g_debuglog = false
C4:CreateNetworkConnection (6003, "255.255.255.255", 9)


REMOTE_BUTTONS_TRANSLATION = {
	['PROGRAM_A']	= Properties["Program A Keymap"],
	['PROGRAM_B']	= Properties["Program B Keymap"],
	['PROGRAM_C']	= Properties["Program C Keymap"],
	['PROGRAM_D']	= Properties["Program D Keymap"],
	
	['GUIDE']		= "browser_home",
	['RECALL'] 	= "backspace",
	['PAGE_UP']	= "pageup",
	['PAGE_DOWN']	= "pagedown",
	
	['RIGHT']		= "right",
	['LEFT']		= "left",
	['UP']		= "up",
	['DOWN']		= "down",
	['ENTER']		= "enter",
	
	['INFO']		= "i",
	['MENU']		= "menu",
	['CANCEL'] 	= "escape",
	
	['PLAY'] 		= "play_pause",
	['PAUSE'] 	= "play_pause",
	['SKIP_FWD'] 	= "next_track",
	['SKIP_REV'] 	= "prev_track",
	['SCAN_FWD'] 	= "fastforward",
	['SCAN_REV'] 	= "rewind",
	['STOP'] 		= "stop",
	
	['NUMBER_1'] 	= "one",
	['NUMBER_2'] 	= "two",
	['NUMBER_3'] 	= "three",
	['NUMBER_4'] 	= "four",
	['NUMBER_5'] 	= "five",
	['NUMBER_6'] 	= "six",
	['NUMBER_7'] 	= "seven",
	['NUMBER_8'] 	= "eight",
	['NUMBER_9'] 	= "nine",
	['STAR']		= "",
	['NUMBER_0'] 	= "zero",
	['POUND']		= "",
}

XBMC_SHUTDOWN_ACTIONS = {
	["Quit XBMC"] = 
		{
			["jsonrpc"] = "2.0",
			["method"] = "Application.Quit"
		}
	,
  
	["Suspend System"] = 
		{
			["jsonrpc"] = "2.0",
			["method"] = "System.Suspend"
		}
	,
  
	["Hibernate System"] = 
		{
			["jsonrpc"] = "2.0",
			["method"] = "System.Hibernate"
		}
	,
  
	["Reboot System"] = 
		{
			["jsonrpc"] = "2.0",
			["method"] = "System.Reboot"
		}
	,
  
	["Shutdown System"] = 
		{
			["jsonrpc"] = "2.0",
			["method"] = "System.Shutdown"
		}
}


function EventServerSend(strData)
	if(strData ~= "") then
		dbg("Sending EventServer packet: "..strData)
		--hexdump(packetData)
		C4:SendToNetwork(6004, 9777, gPacketSectionA..string.char(string.len(strData)+10)..gPacketSectionB..strData..string.char(0))
	end
end

function JsonRPCSend(tblData)
	local strData = Encode(tblData)
	dbg("Sending JsonRPCSend packet: "..strData)
	C4:SendToNetwork(6004, 9090, strData)
end

function OnTimerExpired(idTimer)
	dbg("On Timer Expired")
	
	if (idTimer == idWakeOnLan) then
	   -- wake on lan support comes from a WOL driver written by a guy named Will from homemation.
	   dbg("Sending Wake on LAN magic packet")
	   local MAC = Properties["XBMC MAC Address"]
	   MAC = MAC:gsub(":", "") -- Remove any colons in the entered MAC addresses
	   MAC = tohex(MAC) -- Convert to HEX
	   packet = string.rep(string.char(255), 6) .. string.rep(MAC, 16) -- Build 'magic packet'.
	   hexdump(packet)
	   C4:SendToNetwork (6003, 9, packet)
	   C4:SendToNetwork (6003, 9, packet)
	elseif (idTimer == g_DebugTimer) then
		dbg('Turning Debug Mode back to Off [default] (timer expired)')
		C4:UpdateProperty('Debug Mode', 'Off')
		g_debugprint = false
		g_debuglog = false
		g_DebugTimer = C4:KillTimer(g_DebugTimer)
		return
	else
		dbg("Unrecognized TimerID")
		C4:KillTimer(idTimer)
	end
	
end


function OnConnectionStatusChanged(idBinding, nPort, strStatus)
	dbg("XBMC: OnConnectionStatusChanged[" .. idBinding .. " (" .. nPort .. ")]: " .. strStatus)

	if (idBinding == 6003) then 
		if (strStatus == "ONLINE") then     
			idWakeOnLan = C4:AddTimer(Properties["Power On Delay-Seconds"], "SECONDS", false)
		end
	elseif(idBinding == 6004) then                        
		if (strStatus == "ONLINE") then     
			dbg("TCP Connected.  Sending Shutdown Command.")
			JsonRPCSend(XBMC_SHUTDOWN_ACTIONS[Properties['Room Off Command']])
		end
	end	
end


function ReceivedFromProxy(idBinding, strCommand, tParams)
	dbg('XBMC: ReceivedFromProxy: ' .. strCommand)

	if (strCommand == "ON") then
		dbg('Got ON Command: ' .. "")
		if (Properties["Wake on LAN"] == "Enabled") then
			C4:NetConnect(6003, 9, "UDP")
		end
	elseif (strCommand == "OFF") then
		dbg('Got OFF Command: ' .. "")
		C4:NetConnect(6004, 9090, 'TCP')
	else
		EventServerSend(REMOTE_BUTTONS_TRANSLATION[strCommand])
	end
end

function ExecuteCommand(Command, Parameters)
	dbg('XBMC: ExecuteCommand: ' .. Command)

	if (Parameters ~= nil) then
		for ParamName, ParamValue in pairs(Parameters) do 
			print(ParamName, ParamValue) 
			if(ParamName == "ACTION") then
				if(ParamValue == "Debug Action") then
					C4:NetConnect(6004, 9090, 'TCP')
				else
					dbg("Sending command to EventServer")
					EventServerSend(REMOTE_BUTTONS_TRANSLATION[ParamValue])
				end
			end
		end
	end
end

function OnDriverDestroyed()
	if (g_DebugTimer) then g_DebugTimer = C4:KillTimer(g_DebugTimer) end
end


function dbg(strDebugText)
	if (g_debugprint) then print(strDebugText) end
	if (g_debuglog) then C4:ErrorLog(strDebugText) end
end


function startDebugTimer()
	if (g_DebugTimer) then
		g_DebugTimer = C4:KillTimer(g_DebugTimer)
	end
	g_DebugTimer = C4:AddTimer(15, 'MINUTES')
end


function OnPropertyChanged(strProperty)

	dbg("Property Changed")
	if (strProperty == 'Debug Mode') then
		if (Properties[strProperty] == 'Off') then
			g_debugprint = false
			g_debuglog = false
			g_DebugTimer = C4:KillTimer(g_DebugTimer)
			g_DebugTimer = 0
		end
		if (Properties[strProperty] == 'Print') then
			g_debugprint = true
			g_debuglog = false
			startDebugTimer()
		end
		if (Properties[strProperty] == 'Log') then
			g_debugprint = false
			g_debuglog = true
			startDebugTimer()
		end
		if (Properties[strProperty] == 'Print and Log') then
			g_debugprint = true
			g_debuglog = true
			startDebugTimer()
		end
	end
end



































--[[

 JSON Encoder and Parser for Lua 5.1

 Copyright ? 2007 Shaun Brown (http://www.chipmunkav.com).
 All Rights Reserved.

 Permission is hereby granted, free of charge, to any person
 obtaining a copy of this software to deal in the Software without
 restriction, including without limitation the rights to use,
 copy, modify, merge, publish, distribute, sublicense, and/or
 sell copies of the Software, and to permit persons to whom the
 Software is furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be
 included in all copies or substantial portions of the Software.
 If you find this software useful please give www.chipmunkav.com a mention.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

 Usage:

 -- Lua script:
 local t = {
	["name1"] = "value1",
	["name2"] = {1, false, true, 23.54, "a \021 string"},
	name3 = Json.Null()
 }

 local json = Json.Encode (t)
 print (json)
 --> {"name1":"value1","name3":null,"name2":[1,false,true,23.54,"a \u0015 string"]}

 local t = Json.Decode(json)
 print(t.name2[4])
 --> 23.54

 Notes:
 1) Encodable Lua types: string, number, boolean, table, nil
 2) Use Json.Null() to insert a null value into a Json object
 3) All control chars are encoded to \uXXXX format eg "\021" encodes to "\u0015"
 4) All Json \uXXXX chars are decoded to chars (0-255 byte range only)
 5) Json single line // and /* */ block comments are discarded during decoding
 6) Numerically indexed Lua arrays are encoded to Json Lists eg [1,2,3]
 7) Lua dictionary tables are converted to Json objects eg {"one":1,"two":2}
 8) Json nulls are decoded to Lua nil and treated by Lua in the normal way

--]]
local string = string
local math = math
local table = table
local error = error
local tonumber = tonumber
local tostring = tostring
local type = type
local setmetatable = setmetatable
local pairs = pairs
local ipairs = ipairs
local assert = assert
local Chipmunk = Chipmunk

--module("Json")

local StringBuilder = {
	buffer = {}
}

function StringBuilder:New()
	local o = {}
	setmetatable(o, self)
	self.__index = self
	o.buffer = {}
	return o
end

function StringBuilder:Append(s)
	self.buffer[#self.buffer+1] = s
end

function StringBuilder:ToString()
	return table.concat(self.buffer)
end

local JsonWriter = {
	backslashes = {
		['\b'] = "\\b",
		['\t'] = "\\t",
		['\n'] = "\\n",
		['\f'] = "\\f",
		['\r'] = "\\r",
		['"']  = "\\\"",
		['\\'] = "\\\\",
		['/']  = "\\/"
	}
}

function JsonWriter:New()
	local o = {}
	o.writer = StringBuilder:New()
	setmetatable(o, self)
	self.__index = self
	return o
end

function JsonWriter:Append(s)
	self.writer:Append(s)
end

function JsonWriter:ToString()
	return self.writer:ToString()
end

function JsonWriter:Write(o)
	local t = type(o)
	if t == "nil" then
		self:WriteNil()
	elseif t == "boolean" then
		self:WriteString(o)
	elseif t == "number" then
		self:WriteString(o)
	elseif t == "string" then
		self:ParseString(o)
	elseif t == "table" then
		self:WriteTable(o)
	elseif t == "function" then
		self:WriteFunction(o)
	elseif t == "thread" then
		self:WriteError(o)
	elseif t == "userdata" then
		self:WriteError(o)
	end
end

function JsonWriter:WriteNil()
	self:Append("null")
end

function JsonWriter:WriteString(o)
	self:Append(tostring(o))
end

function JsonWriter:ParseString(s)
	self:Append('"')
	self:Append(string.gsub(s, "[%z%c\\\"/]", function(n)
		local c = self.backslashes[n]
		if c then return c end
		return string.format("\\u%.4X", string.byte(n))
	end))
	self:Append('"')
end

function JsonWriter:IsArray(t)
	local count = 0
	local isindex = function(k)
		if type(k) == "number" and k > 0 then
			if math.floor(k) == k then
				return true
			end
		end
		return false
	end
	for k,v in pairs(t) do
		if not isindex(k) then
			return false, '{', '}'
		else
			count = math.max(count, k)
		end
	end
	return true, '[', ']', count
end

function JsonWriter:WriteTable(t)
	local ba, st, et, n = self:IsArray(t)
	self:Append(st)
	if ba then
		for i = 1, n do
			self:Write(t[i])
			if i < n then
				self:Append(',')
			end
		end
	else
		local first = true;
		for k, v in pairs(t) do
			if not first then
				self:Append(',')
			end
			first = false;
			self:ParseString(k)
			self:Append(':')
			self:Write(v)
		end
	end
	self:Append(et)
end

function JsonWriter:WriteError(o)
	error(string.format(
		"Encoding of %s unsupported",
		tostring(o)))
end

function JsonWriter:WriteFunction(o)
	if o == Null then
		self:WriteNil()
	else
		self:WriteError(o)
	end
end

local StringReader = {
	s = "",
	i = 0
}

function StringReader:New(s)
	local o = {}
	setmetatable(o, self)
	self.__index = self
	o.s = s or o.s
	return o
end

function StringReader:Peek()
	local i = self.i + 1
	if i <= #self.s then
		return string.sub(self.s, i, i)
	end
	return nil
end

function StringReader:Next()
	self.i = self.i+1
	if self.i <= #self.s then
		return string.sub(self.s, self.i, self.i)
	end
	return nil
end

function StringReader:All()
	return self.s
end

local JsonReader = {
	escapes = {
		['t'] = '\t',
		['n'] = '\n',
		['f'] = '\f',
		['r'] = '\r',
		['b'] = '\b',
	}
}

function JsonReader:New(s)
	local o = {}
	o.reader = StringReader:New(s)
	setmetatable(o, self)
	self.__index = self
	return o;
end

function JsonReader:Read()
	self:SkipWhiteSpace()
	local peek = self:Peek()
	if peek == nil then
		error(string.format(
			"Nil string: '%s'",
			self:All()))
	elseif peek == '{' then
		return self:ReadObject()
	elseif peek == '[' then
		return self:ReadArray()
	elseif peek == '"' then
		return self:ReadString()
	elseif string.find(peek, "[%+%-%d]") then
		return self:ReadNumber()
	elseif peek == 't' then
		return self:ReadTrue()
	elseif peek == 'f' then
		return self:ReadFalse()
	elseif peek == 'n' then
		return self:ReadNull()
	elseif peek == '/' then
		self:ReadComment()
		return self:Read()
	else
		error(string.format(
			"Invalid input: '%s'",
			self:All()))
	end
end

function JsonReader:ReadTrue()
	self:TestReservedWord{'t','r','u','e'}
	return true
end

function JsonReader:ReadFalse()
	self:TestReservedWord{'f','a','l','s','e'}
	return false
end

function JsonReader:ReadNull()
	self:TestReservedWord{'n','u','l','l'}
	return nil
end

function JsonReader:TestReservedWord(t)
	for i, v in ipairs(t) do
		if self:Next() ~= v then
			 error(string.format(
				"Error reading '%s': %s",
				table.concat(t),
				self:All()))
		end
	end
end

function JsonReader:ReadNumber()
        local result = self:Next()
        local peek = self:Peek()
        while peek ~= nil and string.find(
		peek,
		"[%+%-%d%.eE]") do
            result = result .. self:Next()
            peek = self:Peek()
	end
	result = tonumber(result)
	if result == nil then
	        error(string.format(
			"Invalid number: '%s'",
			result))
	else
		return result
	end
end

function JsonReader:ReadString()
	local result = ""
	assert(self:Next() == '"')
        while self:Peek() ~= '"' do
		local ch = self:Next()
		if ch == '\\' then
			ch = self:Next()
			if self.escapes[ch] then
				ch = self.escapes[ch]
			end
		end
                result = result .. ch
	end
        assert(self:Next() == '"')
	local fromunicode = function(m)
		return string.char(tonumber(m, 16))
	end
	return string.gsub(
		result,
		"u%x%x(%x%x)",
		fromunicode)
end

function JsonReader:ReadComment()
        assert(self:Next() == '/')
        local second = self:Next()
        if second == '/' then
            self:ReadSingleLineComment()
        elseif second == '*' then
            self:ReadBlockComment()
        else
            error(string.format(
		"Invalid comment: %s",
		self:All()))
	end
end

function JsonReader:ReadBlockComment()
	local done = false
	while not done do
		local ch = self:Next()
		if ch == '*' and self:Peek() == '/' then
			done = true
                end
		if not done and
			ch == '/' and
			self:Peek() == "*" then
                    error(string.format(
			"Invalid comment: %s, '/*' illegal.",
			self:All()))
		end
	end
	self:Next()
end

function JsonReader:ReadSingleLineComment()
	local ch = self:Next()
	while ch ~= '\r' and ch ~= '\n' do
		ch = self:Next()
	end
end

function JsonReader:ReadArray()
	local result = {}
	assert(self:Next() == '[')
	local done = false
	if self:Peek() == ']' then
		done = true;
	end
	while not done do
		local item = self:Read()
		result[#result+1] = item
		self:SkipWhiteSpace()
		if self:Peek() == ']' then
			done = true
		end
		if not done then
			local ch = self:Next()
			if ch ~= ',' then
				error(string.format(
					"Invalid array: '%s' due to: '%s'",
					self:All(), ch))
			end
		end
	end
	assert(']' == self:Next())
	return result
end

function JsonReader:ReadObject()
	local result = {}
	assert(self:Next() == '{')
	local done = false
	if self:Peek() == '}' then
		done = true
	end
	while not done do
		local key = self:Read()
		if type(key) ~= "string" then
			error(string.format(
				"Invalid non-string object key: %s",
				key))
		end
		self:SkipWhiteSpace()
		local ch = self:Next()
		if ch ~= ':' then
			error(string.format(
				"Invalid object: '%s' due to: '%s'",
				self:All(),
				ch))
		end
		self:SkipWhiteSpace()
		local val = self:Read()
		result[key] = val
		self:SkipWhiteSpace()
		if self:Peek() == '}' then
			done = true
		end
		if not done then
			ch = self:Next()
                	if ch ~= ',' then
				error(string.format(
					"Invalid array: '%s' near: '%s'",
					self:All(),
					ch))
			end
		end
	end
	assert(self:Next() == "}")
	return result
end

function JsonReader:SkipWhiteSpace()
	local p = self:Peek()
	while p ~= nil and string.find(p, "[%s/]") do
		if p == '/' then
			self:ReadComment()
		else
			self:Next()
		end
		p = self:Peek()
	end
end

function JsonReader:Peek()
	return self.reader:Peek()
end

function JsonReader:Next()
	return self.reader:Next()
end

function JsonReader:All()
	return self.reader:All()
end

function Encode(o)
	local writer = JsonWriter:New()
	writer:Write(o)
	return writer:ToString()
end

function Decode(s)
	local reader = JsonReader:New(s)
	return reader:Read()
end

function Null()
	return Null
end



]]></script>
        <actions>
            <action>
                <name>Debug Action</name>
                <command>Debug Action</command>
            </action>
        </actions>
        <properties>
            <property>
                <name>Power On Delay-Seconds</name>
                <type>RANGED_INTEGER</type>
                <readonly>false</readonly>
                <default>5</default>
                <minimum>0</minimum>
                <maximum>60</maximum>
            </property>
            <property>
                <name>Debug Mode</name>
                <type>LIST</type>
                <readonly>false</readonly>
                <default>Off</default>
                <items>
                    <item>Off</item>
                    <item>Print</item>
                    <item>Log</item>
                    <item>Print and Log</item>
                </items>
            </property>
            <property>
                <name>Wake on LAN</name>
                <type>LIST</type>
                <readonly>false</readonly>
                <default>Enabled</default>
                <items>
                    <item>Disabled</item>
                    <item>Enabled</item>
                </items>
            </property>
            <property>
                <name>XBMC MAC Address</name>
                <type>STRING</type>
                <readonly>false</readonly>
                <default />
            </property>
            <property>
                <name>Program A Keymap</name>
                <type>STRING</type>
                <readonly>false</readonly>
                <default>t</default>
            </property>
            <property>
                <name>Program B Keymap</name>
                <type>STRING</type>
                <readonly>false</readonly>
                <default />
            </property>
            <property>
                <name>Program C Keymap</name>
                <type>STRING</type>
                <readonly>false</readonly>
                <default />
            </property>
            <property>
                <name>Program D Keymap</name>
                <type>STRING</type>
                <readonly>false</readonly>
                <default />
            </property>
            <property>
                <name>Room Off Command</name>
                <type>LIST</type>
                <readonly>false</readonly>
                <default>Shutdown System</default>
                <items>
                    <item>Do Nothing</item>
                    <item>Quit XBMC</item>
                    <item>Shutdown System</item>
                    <item>Suspend System</item>
                    <item>Hibernate System</item>
                    <item>Reboot System</item>
                </items>
            </property>
        </properties>
    </config>
</devicedata>

 

kodi.c4z

Link to comment
Share on other sites


I am currently using this driver as well for a few years now. I have made a few button mapping changes to my preference. I will take a look at this and comment tomorrow. May do this on mine and share it here. Do you have an icon you want to use? Post it here and I will use it.

 

 

Happy Automating!

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.