Frames

Untitled

0
1from PIL import Image
2from PIL import ImageDraw
3from PIL import ImageFont
4
5import ST7735 as TFT
6import Adafruit_GPIO as GPIO
7import Adafruit_GPIO.SPI as SPI
8
9from pythonosc import osc_server
10from pythonosc import osc_message_builder
11from pythonosc import dispatcher
12import threading
13import argparse
14import time
15
16WIDTH = 128
17HEIGHT = 160
18SPEED_HZ = 4000000
19
20
21# Raspberry Pi configuration.
22DC = 27
23RST = 26
24SPI_PORT = 1
25SPI_DEVICE = 2
26
27# Create TFT LCD display class.
28disp = TFT.ST7735(
29 DC,
30 rst=RST,
31 spi=SPI.SpiDev(
32 SPI_PORT,
33 SPI_DEVICE,
34 max_speed_hz=SPEED_HZ),
35 width=WIDTH,
36 height=HEIGHT)
37
38# Initialize display.
39disp.begin()
40
41# Get a PIL Draw object to start drawing on the display buffer.
42draw = disp.draw()
43
44# Load default font.
45font = ImageFont.load_default()
46font_name = "LiberationMono-Regular.ttf"
47font = ImageFont.truetype(font_name, 10)
48font_title = ImageFont.truetype(font_name, 16)
49
50# Define a function to create rotated text. Unfortunately PIL doesn't have good
51# native support for rotated fonts, but this function can be used to make a
52# text image and rotate it so it's easy to paste in the buffer.
53def draw_rotated_text(image, text, position, angle, font, fill=(255,255,255),background=(0,0,0) ):
54 # Get rendered font width and height.
55 draw = ImageDraw.Draw(image)
56 width, height = draw.textsize(text, font=font)
57 # Create a new image with transparent background to store the text.
58 textimage = Image.new('RGBA', (width, height), background + (255,))
59 # Render the text.
60 textdraw = ImageDraw.Draw(textimage)
61 textdraw.text((0,0), text, font=font, fill=fill)
62 # Rotate the text image.
63 rotated = textimage.rotate(angle, expand=1)
64 # Paste the text into the image, using it as a mask for transparency.
65 image.paste(rotated, position, rotated)
66
67class Display(object):
68 def __init__(self):
69 self.osc_server = self.setup_osc_server()
70 self.update_count = 0
71 self.inputs = ['SAMPLER', 'SHADERS', 'CAMERA']
72 self.sample_list = []
73 #self.sampler_state = False
74 #self.shaders_state = False
75 self.play_on = False
76 self.fx_on = False
77 self.shader_list = []
78 self.fx_list = []
79 self.camera_list = []
80 self.current_mode = 'SAMPLER'
81 self.fx_screen_visible = False
82 self.is_camera_on = False
83 self.switch_input_mode()
84 self.current_list_offset = 0
85 self.fx_list_offset = 0
86 self.view_list = self.get_view_list()
87 self.selected_row = 0
88 self.selected_fx_row = 0
89 self.playing_sample_row = -1
90 self.playing_shader_row = -1
91 self.playing_fx_row = -1
92
93 def get_view_list(self):
94 return self.current_list[self.current_list_offset:self.current_list_offset + 6]
95
96 def get_fx_view_list(self):
97 return self.fx_list[self.fx_list_offset:self.fx_list_offset + 6]
98
99 @staticmethod
100 def get_state_symbol(state):
101 if state:
102 return '>' #'▶
103 else:
104 return '■' #'■'
105
106 def switch_input_mode(self):
107 if self.current_mode == 'SAMPLER':
108 self.title = '__SAMPLER_{}_'
109 self.current_title_colour = (255,0,255)
110 self.current_list = self.sample_list
111 elif self.current_mode == 'SHADERS':
112 self.title = '__SHADERS_{}_'
113 self.current_list = self.shader_list
114 self.current_title_colour = (255,255,0)
115 elif self.current_mode == 'CAMERA':
116 self.title = '__CAMERA___'
117 self.current_list = self.camera_list
118 self.current_title_colour = (0,255,255)
119
120
121 def create_this_screen(self):
122 if self.fx_screen_visible:
123 self.create_fx_screen()
124 else:
125 self.create_mode_screen()
126
127 def create_mode_screen(self):
128 # print title
129 title = self.title.format(self.get_state_symbol(self.play_on))
130 draw_rotated_text(disp.buffer, title, (110, 10),270, font_title, fill=(0,0,0), background=self.current_title_colour)
131 # print content
132 for i, value in enumerate(self.get_view_list()):
133 if i == self.selected_row - self.current_list_offset:
134 draw_rotated_text(disp.buffer, value, (110 - 15 - i*15, 10) ,270, font, fill=(0,0,0), background=(255,255,255))
135 elif (i == self.playing_sample_row - self.current_list_offset and self.current_mode == 'SAMPLER') or (i == self.playing_shader_row - self.current_list_offset and self.current_mode == 'SHADERS'):
136 draw_rotated_text(disp.buffer, value, (110 - 15 - i*15, 10) ,270, font, fill=(255,255,255), background=self.current_title_colour)
137 else:
138 draw_rotated_text(disp.buffer, value, (110 - 15 - i*15, 10) ,270, font, fill=(255,255,255), )
139
140 def create_fx_screen(self):
141 fx_title = '__FX__{}_'.format(self.get_state_symbol(self.fx_on))
142 fx_title_colour = (0, 255, 255)
143 # print title
144 draw_rotated_text(disp.buffer, fx_title, (110, 10),270, font_title, fill=(0,0,0), background=fx_title_colour)
145 # print content
146 for i, value in enumerate(self.get_fx_view_list()):
147 if i == self.selected_fx_row - self.fx_list_offset:
148 draw_rotated_text(disp.buffer, value, (110 - 15 - i*15, 10) ,270, font, fill=(0,0,0), background=(255,255,255))
149 elif i == self.playing_fx_row - self.fx_list_offset:
150 draw_rotated_text(disp.buffer, value, (110 - 15 - i*15, 10) ,270, font, fill=(0,0,0), background=fx_title_colour)
151 else:
152 draw_rotated_text(disp.buffer, value, (110 - 15 - i*15, 10) ,270, font, fill=(255,255,255), )
153
154
155 def setup_osc_server(self):
156 server_parser = argparse.ArgumentParser()
157 server_parser.add_argument("--ip", default="127.0.0.1", help="the ip")
158 server_parser.add_argument("--port", type=int, default=9000, help="the port")
159
160 server_args = server_parser.parse_args()
161
162 this_dispatcher = dispatcher.Dispatcher()
163
164 this_dispatcher.map("/sampleList", self.set_sample_list)
165 this_dispatcher.map("/shaderList", self.set_shader_list)
166 this_dispatcher.map("/fxList", self.set_fx_list)
167 this_dispatcher.map("/cameraList", self.set_camera_list)
168 this_dispatcher.map("/selectedRow", self.set_selected_row)
169 this_dispatcher.map("/selectedFxRow", self.set_selected_fx_row)
170 this_dispatcher.map("/inputMode", self.set_input_mode)
171 this_dispatcher.map("/fxScreenVisible", self.set_fx_screen_visible)
172 this_dispatcher.map("/playOn", self.set_play_on)
173 this_dispatcher.map("/fxOn", self.set_fx_on)
174 this_dispatcher.map("/isCameraOn", self.set_is_camera_on)
175 this_dispatcher.map("/playingSampleRow", self.set_playing_sample_row)
176 this_dispatcher.map("/playingShaderRow", self.set_playing_shader_row)
177 this_dispatcher.map("/playingFxRow", self.set_playing_fx_row)
178
179
180
181 server = osc_server.ThreadingOSCUDPServer((server_args.ip, server_args.port), this_dispatcher)
182 server_thread = threading.Thread(target=server.serve_forever)
183 server_thread.start()
184 return server
185
186 def set_sample_list(self, unused_addr, *args):
187 self.sample_list = [i.split("/")[-1] for i in list(args)]
188 print("sample list ", self.sample_list)
189 self.switch_input_mode()
190 self.update_display_count()
191
192
193 def set_shader_list(self, unused_addr, *args):
194 self.shader_list = [i.split("/")[-1] for i in list(args)]
195 print('shaderlist' , self.shader_list)
196 self.switch_input_mode()
197 self.update_display_count()
198
199 def set_fx_list(self, unused_addr, *args):
200 self.fx_list = [i.split("/")[-1] for i in list(args)]
201 print('fx list', self.fx_list)
202 self.switch_input_mode()
203 self.update_display_count()
204
205 def set_camera_list(self, unused_addr, *args):
206 self.camera_list = [i.split("/")[-1] for i in list(args)]
207 self.switch_input_mode()
208 self.update_display_count()
209
210 def set_is_camera_on(self, unused_addr, is_camera_on):
211 self.is_camera_on = bool(is_camera_on)
212 self.switch_input_mode()
213 self.update_display_count()
214
215 def set_playing_sample_row(self, unused_addr, playing_sample_row):
216 self.playing_sample_row = playing_sample_row
217 self.update_display_count()
218
219 def set_playing_shader_row(self, unused_addr, playing_shader_row):
220 self.playing_shader_row = playing_shader_row
221 self.update_display_count()
222
223 def set_playing_fx_row(self, unused_addr, playing_fx_row):
224 print("playing_fx_row: ", playing_fx_row)
225 self.playing_fx_row = playing_fx_row
226 self.update_display_count()
227
228 def set_selected_row(self, unused_addr, row):
229 self.selected_row = row
230 if self.selected_row == self.current_list_offset - 1:
231 self.current_list_offset = self.current_list_offset - 1
232 elif self.selected_row == self.current_list_offset + 5 + 1:
233 self.current_list_offset = self.current_list_offset + 1
234 self.update_display_count()
235
236 def set_selected_fx_row(self, unused_addr, row):
237 self.selected_fx_row = row
238 if self.selected_fx_row == self.fx_list_offset - 1:
239 self.fx_list_offset = self.fx_list_offset - 1
240 elif self.selected_fx_row == self.fx_list_offset + 5 + 1:
241 self.fx_list_offset = self.fx_list_offset + 1
242 self.update_display_count()
243
244 def set_input_mode(self, unused_addr, mode):
245 self.current_mode = mode
246 self.current_list_offset = 0
247 self.selected_row = 0
248 self.switch_input_mode()
249 self.update_display_count()
250
251 def set_fx_screen_visible(self, unused_addr, is_visible):
252 self.fx_screen_visible = bool(is_visible)
253 self.update_display_count()
254
255 def set_fx_on(self, unused_addr, is_fx_on):
256 self.fx_on = bool(is_fx_on)
257 self.update_display_count()
258
259 def set_play_on(self, unused_addr, is_play_on):
260 self.play_on = bool(is_play_on)
261 self.update_display_count()
262
263 def loop_over_display_update(self):
264 while True:
265 if self.update_count > 0:
266 self.update_display()
267 time.sleep(0.1)
268 self.update_count = self.update_count - 1
269
270 def update_display(self):
271 disp.clear()
272 self.create_this_screen()
273 disp.draw()
274 disp.display()
275 time.sleep(0.1)
276
277 def update_display_count(self):
278 self.update_count = self.update_count + 1
279
280def setup_gpio():
281 import RPi.GPIO as GPIO
282 GPIO.setmode(GPIO.BCM)
283
284 pins = [4, 5, 6, 7, 12, 13, 17, 18, 19, 22, 23 ]
285 for pin in pins:
286 print('pin is ', pin)
287 GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
288
289
290setup_gpio()
291display = Display()
292display.loop_over_display_update()
293
294
295