1
1
# standard imports
2
2
from socket import socket
3
3
4
+ # kivy imports
5
+ from kivy .config import Config
6
+ from kivy .core .window import Window
7
+ from kivy .app import App
8
+ from kivy .lang import Builder
9
+ from kivy .uix .boxlayout import BoxLayout
10
+ from kivy .uix .gridlayout import GridLayout
11
+ from kivy .clock import Clock
12
+ from kivy .uix .popup import Popup
13
+ from kivy .uix .label import Label
14
+ from kivy .uix .textinput import TextInput
15
+ from kivy .uix .button import Button
16
+
4
17
# lib imports
5
18
from lz4 .frame import decompress
6
19
import pygame
7
20
8
- # this display to show on
9
- display = 0
21
+ Config . set ( 'graphics' , 'resizable' , 0 )
22
+ Window . size = ( 1280 , 720 )
10
23
11
- # todo - allow different resolution than server output
12
- WIDTH = 1920
13
- HEIGHT = 1080
24
+ kv = '''
25
+ Main:
26
+ BoxLayout:
27
+ orientation: 'vertical'
28
+ padding: root.width * 0.05, root.height * .05
29
+ spacing: '5dp'
30
+ BoxLayout:
31
+ size_hint: [1,.85]
32
+ Image:
33
+ id: image
34
+ source: 'foo.png'
35
+ BoxLayout:
36
+ size_hint: [1,.15]
37
+ GridLayout:
38
+ cols: 3
39
+ spacing: '10dp'
40
+ Button:
41
+ id: status
42
+ text:'Play'
43
+ bold: True
44
+ on_press: root.play_pause()
45
+ Button:
46
+ text: 'Close'
47
+ bold: True
48
+ on_press: root.close()
49
+ Button:
50
+ text: 'Setting'
51
+ bold: True
52
+ on_press: root.setting()
53
+ '''
14
54
15
55
16
56
def recv_all (conn , length ):
17
- """ Retreive all pixels. """
57
+ """Retrieve all pixels."""
18
58
19
59
buf = b''
20
60
while len (buf ) < length :
@@ -25,36 +65,85 @@ def recv_all(conn, length):
25
65
return buf
26
66
27
67
28
- def main (host = '127.0.0.1' , port = 5000 ):
29
- pygame .init ()
30
- screen = pygame .display .set_mode (size = (WIDTH , HEIGHT ), display = display )
31
- clock = pygame .time .Clock ()
32
- watching = True
68
+ class Main (BoxLayout ):
69
+ def __init__ (self , ** kwargs ):
70
+ super ().__init__ (** kwargs )
71
+ self .server_address = None
72
+ self .server_port = None
73
+ self .server_input = None
74
+ self .port_input = None
75
+ self .popup = None
76
+ self .sock = socket ()
77
+
78
+ def play_pause (self ):
79
+ if not self .server_address or not self .server_port :
80
+ box = GridLayout (cols = 1 )
81
+ box .add_widget (Label (text = "Ip or Port Not Set" ))
82
+ btn = Button (text = "OK" )
83
+ btn .bind (on_press = self .close_popup )
84
+ box .add_widget (btn )
85
+ self .popup = Popup (title = 'Error' , content = box , size_hint = (.8 , .3 ))
86
+ self .popup .open ()
87
+ else :
88
+ if self .ids .status .text == "Stop" :
89
+ self .stop ()
90
+ else :
91
+ self .sock = socket ()
92
+ self .sock .connect ((self .server_address , self .server_port ))
93
+ self .ids .status .text = "Stop"
94
+ Clock .schedule_interval (self .recv , 0.05 )
95
+
96
+ def close_popup (self , btn ):
97
+ self .popup .dismiss ()
98
+
99
+ def stop (self ):
100
+ Clock .unschedule (self .recv )
101
+ self .sock .close ()
102
+ self .ids .status .text = "Play"
103
+
104
+ def recv (self , dt ):
105
+ size_len = int .from_bytes (self .sock .recv (1 ), byteorder = 'big' )
106
+ size = int .from_bytes (self .sock .recv (size_len ), byteorder = 'big' )
107
+ pixels = decompress (recv_all (self .sock , size ))
108
+
109
+ image = pygame .image .fromstring (pixels , (1920 , 1080 ), "RGB" ) # convert received image from string
110
+
111
+ try :
112
+ pygame .image .save (image , "foo.png" )
113
+ self .ids .image .reload ()
114
+ except :
115
+ pass
116
+
117
+ def close (self ):
118
+ App .get_running_app ().stop ()
33
119
34
- sock = socket ()
35
- sock .connect ((host , port ))
36
- try :
37
- while watching :
38
- for event in pygame .event .get ():
39
- if event .type == pygame .QUIT :
40
- watching = False
41
- break
120
+ def setting (self ):
121
+ box = GridLayout (cols = 2 )
122
+ box .add_widget (Label (text = "IpAddress: " , bold = True ))
123
+ self .server_input = TextInput ()
124
+ box .add_widget (self .server_input )
125
+ box .add_widget (Label (text = "Port: " , bold = True ))
126
+ self .port_input = TextInput ()
127
+ box .add_widget (self .port_input )
128
+ btn = Button (text = "Set" , bold = True )
129
+ btn .bind (on_press = self .setting_save )
130
+ box .add_widget (btn )
131
+ self .popup = Popup (title = 'Settings' , content = box , size_hint = (.6 , .4 ))
132
+ self .popup .open ()
42
133
43
- # Retrieve the size of the pixels length, the pixels length and pixels
44
- size_len = int .from_bytes (sock .recv (1 ), byteorder = 'big' )
45
- size = int .from_bytes (sock .recv (size_len ), byteorder = 'big' )
46
- pixels = decompress (recv_all (sock , size ))
134
+ def setting_save (self , btn ):
135
+ # todo - validate ip address and port
136
+ try :
137
+ self .server_address = self .server_input .text
138
+ self .server_port = int (self .port_input .text )
139
+ except :
140
+ pass
141
+ self .popup .dismiss ()
47
142
48
- # Create the Surface from raw pixels
49
- img = pygame .image .fromstring (pixels , (WIDTH , HEIGHT ), 'RGB' )
50
143
51
- # Display the picture
52
- screen .blit (img , (0 , 0 ))
53
- pygame .display .flip ()
54
- clock .tick (60 )
55
- finally :
56
- sock .close ()
144
+ class PyStreamApp (App ):
145
+ def build (self ):
146
+ return Builder .load_string (kv )
57
147
58
148
59
- if __name__ == '__main__' :
60
- main ()
149
+ PyStreamApp ().run ()
0 commit comments