This repository has been archived by the owner on Jan 10, 2022. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.lua
executable file
·180 lines (142 loc) · 4.51 KB
/
main.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#!/usr/bin/env lua5.3
--[[
Copyright 2019 Valeri Ochinski
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
]]--
if arg[1] == '--version' then
print('0.2.2')
return true
elseif arg[1] == '--help' then
print[[
linuxmotehook - cemuhook-compatible motion provider based on XWiimote.
Edit config.json to set options.
Supported command line args:
--help Show this information and exit
--version Print version and exit
]]
return true
end
-- Required for "bundle" mode
do
local dir = debug.getinfo(1).source:match("@(.*)main.lua$")
package.path = table.concat({dir, '?.lua;' ,dir, 'deps/share/lua/5.3/?.lua;', dir, 'deps/share/lua/5.3/?/init.lua;', package.path})
package.cpath = dir..'deps/lib/lua/5.3/?.so;'..package.cpath
end
local wii = require 'xwiimote'
local lgi = require 'lgi'
local GLib, Gdk, GObject, Gio =
lgi.GLib, lgi.Gdk, lgi.GObject, lgi.Gio
local common = require 'common'
log = lgi.log.domain('xwiimote-cemu')
getTime = lgi.GLib.get_monotonic_time
loadfromdata = common.makeLoader()
config = loadfromdata('configloader.lua')()
local wiistate = { all = {}, pkgcnt = setmetatable({}, {__index = function() return 0 end}) }
local app = Gio.Application { application_id = 'org.v1993.linuxmotehook', flags = 'NON_UNIQUE' }
local socket = lgi.Gio.Socket.new('IPV4', 'DATAGRAM', 'UDP')
socket.blocking = false
local sa = lgi.Gio.InetSocketAddress.new(Gio.InetAddress.new_loopback('IPV4'), 26760)
assert(socket:bind(sa, true))
local packet = loadfromdata('packet.lua')(socket)
local wiiUtils = loadfromdata('wiimote.lua')()
-- Setup network handler. Actual processing is done in `packet.lua`.
do
-- To avoid extra allocations
-- I assume this is long enough
local buf = require("lgi.core").bytes.new(4096)
local source = socket:create_source('IN')
source:set_callback(function()
local len, src = socket:receive_from(buf)
if len > 0 then
local function sendcb(data)
assert(socket:send_to(src, data)) -- Send data back
end
local success, msg = xpcall(packet.process, debug.traceback,
tostring(buf):sub(1, len),
sendcb,
src,
wiistate
)
if not success then
-- Debug here
log.warning('Error when processing packet: '..msg)
end
end
return true
end)
source:attach(lgi.GLib.MainContext.default())
end
-- Setup WiiMotes and handler new ones
local wiimonitor = assert(wii.monitor(true))
do
for path in wiimonitor:iter() do
wiiUtils.setup(wiistate, path, config, packet.send)
end
local res, fd = wiimonitor:set_blocking(false)
assert(res)
local stream = Gio.UnixInputStream.new(fd, false)
source = stream:create_source()
source:set_callback(function()
-- It sometimes fires as false alarm
for path in wiimonitor:iter() do
-- It errors if I try to open it immedeately, so wait a second first
GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, function()
wiiUtils.setup(wiistate, path, config, packet.send)
end)
end
return true
end)
source:attach(GLib.MainContext.default())
end
-- Setup handler to periodically clean up inactive clients
local function cleanupClients(clients, now, connected)
local todelete = {}
-- 5 seconds
local timeout = 5000000
for k,v in pairs(clients) do
if (v.time + timeout) < now then
todelete[#todelete+1] = k
else
connected[k] = true
end
end
for k,v in ipairs(todelete) do
clients[v] = nil
end
end
GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, function()
local now, connected = getTime(), {}
for k,desc in ipairs(wiistate) do
cleanupClients(desc.clients, now, connected)
end
cleanupClients(wiistate.all, connected)
local todelete = {}
for k,v in pairs(wiistate.pkgcnt) do
if not connected[k] then
todelete[#todelete+1] = k
end
end
for k,v in ipairs(todelete) do
wiistate.pkgcnt[v] = nil
end
return true
end)
local function exitNormal()
print('Exiting')
app:release()
end
function app:on_activate()
app:hold()
end
GLib.unix_signal_add(GLib.PRIORITY_HIGH, 1, exitNormal)
GLib.unix_signal_add(GLib.PRIORITY_HIGH, 2, exitNormal)
GLib.unix_signal_add(GLib.PRIORITY_HIGH, 15, exitNormal)
app:run({arg[0], ...})