Skip to content
This repository was archived by the owner on Mar 15, 2024. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 122 additions & 33 deletions client.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,60 @@
# standard imports
from socket import socket

# kivy imports
from kivy.config import Config
from kivy.core.window import Window
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.clock import Clock
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button

# lib imports
from lz4.frame import decompress
import pygame

# this display to show on
display = 0
Config.set('graphics', 'resizable', 0)
Window.size = (1280, 720)

# todo - allow different resolution than server output
WIDTH = 1920
HEIGHT = 1080
kv = '''
Main:
BoxLayout:
orientation: 'vertical'
padding: root.width * 0.05, root.height * .05
spacing: '5dp'
BoxLayout:
size_hint: [1,.85]
Image:
id: image
source: 'foo.png'
BoxLayout:
size_hint: [1,.15]
GridLayout:
cols: 3
spacing: '10dp'
Button:
id: status
text:'Play'
bold: True
on_press: root.play_pause()
Button:
text: 'Close'
bold: True
on_press: root.close()
Button:
text: 'Setting'
bold: True
on_press: root.setting()
'''


def recv_all(conn, length):
""" Retreive all pixels. """
"""Retrieve all pixels."""

buf = b''
while len(buf) < length:
Expand All @@ -25,36 +65,85 @@ def recv_all(conn, length):
return buf


def main(host='127.0.0.1', port=5000):
pygame.init()
screen = pygame.display.set_mode(size=(WIDTH, HEIGHT), display=display)
clock = pygame.time.Clock()
watching = True
class Main(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.server_address = None
self.server_port = None
self.server_input = None
self.port_input = None
self.popup = None
self.sock = socket()

def play_pause(self):
if not self.server_address or not self.server_port:
box = GridLayout(cols=1)
box.add_widget(Label(text="Ip or Port Not Set"))
btn = Button(text="OK")
btn.bind(on_press=self.close_popup)
box.add_widget(btn)
self.popup = Popup(title='Error', content=box, size_hint=(.8, .3))
self.popup.open()
else:
if self.ids.status.text == "Stop":
self.stop()
else:
self.sock = socket()
self.sock.connect((self.server_address, self.server_port))
self.ids.status.text = "Stop"
Clock.schedule_interval(self.recv, 0.05)

def close_popup(self, btn):
self.popup.dismiss()

def stop(self):
Clock.unschedule(self.recv)
self.sock.close()
self.ids.status.text = "Play"

def recv(self, dt):
size_len = int.from_bytes(self.sock.recv(1), byteorder='big')
size = int.from_bytes(self.sock.recv(size_len), byteorder='big')
pixels = decompress(recv_all(self.sock, size))

image = pygame.image.fromstring(pixels, (1920, 1080), "RGB") # convert received image from string

try:
pygame.image.save(image, "foo.png")
self.ids.image.reload()
except:
pass

def close(self):
App.get_running_app().stop()

sock = socket()
sock.connect((host, port))
try:
while watching:
for event in pygame.event.get():
if event.type == pygame.QUIT:
watching = False
break
def setting(self):
box = GridLayout(cols=2)
box.add_widget(Label(text="IpAddress: ", bold=True))
self.server_input = TextInput()
box.add_widget(self.server_input)
box.add_widget(Label(text="Port: ", bold=True))
self.port_input = TextInput()
box.add_widget(self.port_input)
btn = Button(text="Set", bold=True)
btn.bind(on_press=self.setting_save)
box.add_widget(btn)
self.popup = Popup(title='Settings', content=box, size_hint=(.6, .4))
self.popup.open()

# Retrieve the size of the pixels length, the pixels length and pixels
size_len = int.from_bytes(sock.recv(1), byteorder='big')
size = int.from_bytes(sock.recv(size_len), byteorder='big')
pixels = decompress(recv_all(sock, size))
def setting_save(self, btn):
# todo - validate ip address and port
try:
self.server_address = self.server_input.text
self.server_port = int(self.port_input.text)
except:
pass
self.popup.dismiss()

# Create the Surface from raw pixels
img = pygame.image.fromstring(pixels, (WIDTH, HEIGHT), 'RGB')

# Display the picture
screen.blit(img, (0, 0))
pygame.display.flip()
clock.tick(60)
finally:
sock.close()
class PyStreamApp(App):
def build(self):
return Builder.load_string(kv)


if __name__ == '__main__':
main()
PyStreamApp().run()
11 changes: 11 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
# client app
Kivy==2.1.0
kivymd==0.104.2

# compression
lz4==4.0.1

# capture
mss==6.1.0
numpy==1.23.0
Pillow==9.1.1
pygame==2.1.2
git+https://github.com/ra1nty/DXcam#egg=dxcam

# control and input
pyautogui==0.9.53 # can be used to control mouse and keyboard on server
# https://pyautogui.readthedocs.io/en/latest/index.html