extract desktop control interface

This commit is contained in:
Keyvan Fatehi
2023-02-04 23:35:25 -08:00
parent 3aacf9dd60
commit 6b2c68017e
3 changed files with 47 additions and 35 deletions

View File

@@ -0,0 +1,41 @@
import pyautogui
import numpy
import evdev
import keymap
pyautogui.FAILSAFE = False
class DesktopControlInterface():
def __init__(self, resolution):
self.resolution = resolution
self.ui = evdev.UInput()
self.valid_actions = ["keyboard", "click", "rightclick", "mousemove", "joystick", "paste"]
def handle_action(self, action, data):
if action == "mousemove":
x = numpy.interp(data["cursorPositionX"], (0, data["displayWidth"]), (0, self.resolution.width))
y = numpy.interp(data["cursorPositionY"], (0, data["displayHeight"]), (0, self.resolution.height))
pyautogui.moveTo(x, y, _pause=False)
# elif action == "joystick":
# x = numpy.interp(data["x"], (-38, 38), (0, self.resolution.width))
# y = numpy.interp(data["y"], (-38, 38), (self.resolution.height, 0))
# print(f'{data["y"]} {self.resolution.height} {y}')
# pyautogui.moveTo(x, y, _pause=False)
elif action == "click":
pyautogui.click()
elif action == "rightclick":
pyautogui.rightClick()
elif action == "keyboard":
try:
# keymap.reload()
osKey = keymap.iOStoLinux[data["key"]]
self.ui.write(evdev.ecodes.EV_KEY, osKey, data["direction"])
self.ui.syn()
except KeyError:
print(f"Unknown key: {data['key']}")
elif action == "paste":
# might as well support the secureput protocol completely
pyautogui.write(data["payload"]["string"])
def stop(self):
self.ui.close()

View File

@@ -5,18 +5,14 @@ from aiortc import VideoStreamTrack
import Xlib import Xlib
import Xlib.display import Xlib.display
import os import os
import pyautogui from desktop_control_interface import DesktopControlInterface
import numpy
import evdev
import keymap
pyautogui.FAILSAFE = False
# https://ffmpeg.org/ffmpeg-devices.html#x11grab # https://ffmpeg.org/ffmpeg-devices.html#x11grab
class DesktopStreamTrack(VideoStreamTrack): class DesktopStreamTrack(VideoStreamTrack):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
self.resolution = Xlib.display.Display(os.environ["DISPLAY"]).screen().root.get_geometry() self.resolution = Xlib.display.Display(os.environ["DISPLAY"]).screen().root.get_geometry()
self.control_interface = DesktopControlInterface(self.resolution)
options = { options = {
'draw_mouse': '1', 'draw_mouse': '1',
'i':':0.0+0,0', 'i':':0.0+0,0',
@@ -24,8 +20,6 @@ class DesktopStreamTrack(VideoStreamTrack):
'video_size': str(self.resolution.width) + "x" + str(self.resolution.height) 'video_size': str(self.resolution.width) + "x" + str(self.resolution.height)
} }
self.container = av.open(':0', format='x11grab', options=options) self.container = av.open(':0', format='x11grab', options=options)
self.ui = evdev.UInput()
self.valid_actions = ["keyboard", "click", "rightclick", "mousemove", "joystick", "paste"]
async def recv(self): async def recv(self):
pts, time_base = await self.next_timestamp() pts, time_base = await self.next_timestamp()
@@ -36,36 +30,13 @@ class DesktopStreamTrack(VideoStreamTrack):
frame.pts = pts frame.pts = pts
frame.time_base = time_base frame.time_base = time_base
return frame return frame
def handle_action(self, action, data): def handle_action(self, action, data):
if action == "mousemove": self.control_interface.handle_action(action, data)
x = numpy.interp(data["cursorPositionX"], (0, data["displayWidth"]), (0, self.resolution.width))
y = numpy.interp(data["cursorPositionY"], (0, data["displayHeight"]), (0, self.resolution.height))
pyautogui.moveTo(x, y, _pause=False)
# elif action == "joystick":
# x = numpy.interp(data["x"], (-38, 38), (0, self.resolution.width))
# y = numpy.interp(data["y"], (-38, 38), (self.resolution.height, 0))
# print(f'{data["y"]} {self.resolution.height} {y}')
# pyautogui.moveTo(x, y, _pause=False)
elif action == "click":
pyautogui.click()
elif action == "rightclick":
pyautogui.rightClick()
elif action == "keyboard":
try:
# keymap.reload()
osKey = keymap.iOStoLinux[data["key"]]
self.ui.write(evdev.ecodes.EV_KEY, osKey, data["direction"])
self.ui.syn()
except KeyError:
print(f"Unknown key: {data['key']}")
elif action == "paste":
# might as well support the secureput protocol completely
pyautogui.write(data["payload"]["string"])
def stop(self) -> None: def stop(self) -> None:
super().stop() super().stop()
self.ui.close() self.control_interface.stop()
if __name__ == "__main__": if __name__ == "__main__":
from time import time_ns from time import time_ns

View File

@@ -164,7 +164,7 @@ async def signal(signaling):
print(data) print(data)
elif data["type"] == "joystick": elif data["type"] == "joystick":
webjoystick(data["x"], data["y"]) webjoystick(data["x"], data["y"])
elif desktop_track and data["type"] in desktop_track.valid_actions: elif desktop_track and data["type"] in desktop_track.control_interface.valid_actions:
desktop_track.handle_action(data["type"], data) desktop_track.handle_action(data["type"], data)
else: else:
print("ignored message") print("ignored message")