info@shuvit.org 2 years ago
parent
commit
8896febf91

+ 1
- 0
.gitignore View File

@@ -42,6 +42,7 @@ Thumbs.db
42 42
 *.mp3
43 43
 *.WAV
44 44
 *.MP3
45
+*.sng
45 46
 *__pycache__/
46 47
 lib/__pycache__/
47 48
 lib/*.pyc

+ 2
- 2
config.txt View File

@@ -1,5 +1,5 @@
1
-default_song = default
2
-theme = default
1
+default_song = phat
2
+theme = red2
3 3
 title = default
4 4
 bpm = 90
5 5
 volume = 10

BIN
fonts/Pixellari.ttf View File


+ 6
- 1
lib/FSM.py View File

@@ -82,7 +82,12 @@ class ProgFSM(Char):
82 82
         'SelTheme',
83 83
         'OpenSong',
84 84
         'EnterText',
85
-        'LoadSound'
85
+        'LoadSound',
86
+        'Shutdown',
87
+        'Reboot',
88
+        'Ping', 
89
+        'Wifi',
90
+        'Defender'
86 91
         ]
87 92
         
88 93
         for s in state_list:

+ 737
- 123
lib/StatesProg.py View File

@@ -9,9 +9,11 @@ import glob
9 9
 import os
10 10
 from itertools import cycle
11 11
 from datetime import datetime
12
+from datetime import date
12 13
 import ast
13 14
 import random
14 15
 from pathlib import Path
16
+import socket
15 17
 #====================================     
16 18
 
17 19
 State = type("State", (object,), {})
@@ -86,6 +88,65 @@ def text_center(o, a, b):
86 88
 	o.center_block(a, o.h1, [w1,h1,w2,h2], o.light_grey)
87 89
 	o.center_block(b, o.h1, [w1,h1+20,w2,h2+45], o.light_grey)
88 90
 
91
+#==================================== 
92
+			
93
+def breakup_song_text(song):
94
+	line1 = ""
95
+	line2 = ""
96
+	line3 = ""
97
+	line4 = ""
98
+	if len(song) < 9:
99
+		for x in song:
100
+			line1 += str(x) + '.'
101
+	elif len(song) < 17:
102
+		_iter = 0
103
+		for x in song:
104
+			if _iter < 8:
105
+				line1 += str(x) + '.'
106
+			else:
107
+				line2 += str(x) + '.'
108
+			_iter += 1
109
+	elif len(song) < 25:
110
+		_iter = 0
111
+		for x in song:
112
+			if _iter < 8:
113
+				line1 += str(x) + '.'
114
+			elif _iter < 16:
115
+				line2 += str(x) + '.'
116
+			else:
117
+				line3 += str(x) + '.'
118
+			_iter += 1
119
+	elif len(song) < 33:
120
+		_iter = 0
121
+		for x in song:
122
+			if _iter < 8:
123
+				line1 += str(x) + '.'
124
+			elif _iter < 16:
125
+				line2 += str(x) + '.'
126
+			elif _iter < 24:
127
+				line3 += str(x) + '.'
128
+			else:
129
+				line4 += str(x) + '.'
130
+			_iter += 1
131
+	else:
132
+		_iter = 0
133
+		cur_id = len(song) - 1
134
+		_iter = 0
135
+		ns = song.copy()
136
+		while len(ns) > 31:
137
+			del ns[0]
138
+		for x in ns:
139
+			if _iter < 7:
140
+				line1 += str(x) + '.'
141
+			elif _iter < 15:
142
+				line2 += str(x) + '.'
143
+			elif _iter < 23:
144
+				line3 += str(x) + '.'
145
+			else:
146
+				line4 += str(x) + '.'
147
+			_iter += 1
148
+		line1 = ".." + line1
149
+	return [line1, line2, line3, line4]
89 150
 
90 151
 def draw_menu1(o):
91 152
 	bpm_inc = 4
@@ -112,10 +173,10 @@ def draw_menu1(o):
112 173
 			o.center_block("File", o.h2, [o_x, o_y, o_x + x_size, o_y - y_size], o.light_grey)
113 174
 		if _id == 5:
114 175
 			o.center_block("Util", o.h2, [o_x, o_y, o_x + x_size, o_y - y_size], o.light_grey)
115
-		if _id == 6:
116
-			o.center_block("Bank-", o.h2, [o_x, o_y, o_x + x_size, o_y - y_size], o.light_grey)
117
-		if _id == 7:
118
-			o.center_block("Bank+", o.h2, [o_x, o_y, o_x + x_size, o_y - y_size], o.light_grey)
176
+		# if _id == 6:
177
+		# 	o.center_block("Bank-", o.h2, [o_x, o_y, o_x + x_size, o_y - y_size], o.light_grey)
178
+		# if _id == 7:
179
+		# 	o.center_block("Bank+", o.h2, [o_x, o_y, o_x + x_size, o_y - y_size], o.light_grey)
119 180
 		if _id == 8:
120 181
 			o.center_block("Vol-", o.h2, [o_x, o_y, o_x + x_size, o_y - y_size], o.light_grey)
121 182
 		if _id == 9:
@@ -167,9 +228,25 @@ def draw_menu2_sample(o):
167 228
 		if _id == 5:
168 229
 			o.center_block("Vol+", o.h2, [o_x, o_y, o_x + x_size, o_y - y_size], o.light_grey)
169 230
 		if _id == 6:
170
-			o.center_block("Pitch-", o.h2, [o_x, o_y, o_x + x_size, o_y - y_size], o.light_grey)
231
+			o.center_block("Bank-", o.h2, [o_x, o_y, o_x + x_size, o_y - y_size], o.light_grey)
171 232
 		if _id == 7:
233
+			o.center_block("Bank+", o.h2, [o_x, o_y, o_x + x_size, o_y - y_size], o.light_grey)
234
+		if _id == 8:
235
+			o.center_block("Pitch-", o.h2, [o_x, o_y, o_x + x_size, o_y - y_size], o.light_grey)
236
+		if _id == 9:
172 237
 			o.center_block("Pitch+", o.h2, [o_x, o_y, o_x + x_size, o_y - y_size], o.light_grey)
238
+
239
+
240
+
241
+		if _id == 12:
242
+			if o.odub == True:
243
+				o.center_block("Odub", o.h2, [o_x, o_y, o_x + x_size, o_y - y_size], o.pink)
244
+			else:
245
+				o.center_block("Odub", o.h2, [o_x, o_y, o_x + x_size, o_y - y_size], o.light_grey)
246
+		if _id == 13:
247
+			o.center_block("Undo", o.h2, [o_x, o_y, o_x + x_size, o_y - y_size], o.light_grey)
248
+
249
+
173 250
 		o_x = o_x + x_size
174 251
 		_id += 1
175 252
 		if _id % 4 == 0:
@@ -221,15 +298,46 @@ def draw_menu2_note(o):
221 298
 
222 299
 		if _id == 0:
223 300
 			o.center_block("Vol -", o.h2, [o_x, o_y, o_x + x_size, o_y - y_size], o.light_grey)
224
-		if _id == 1:
301
+		elif _id == 1:
225 302
 			o.center_block("Vol +", o.h2, [o_x, o_y, o_x + x_size, o_y - y_size], o.light_grey)
303
+		elif _id == 12:
304
+			if o.patternFollow:
305
+				o.center_block("Follow", o.h2, [o_x, o_y, o_x + x_size, o_y - y_size], o.pink)
306
+			else:
307
+				o.center_block("Follow", o.h2, [o_x, o_y, o_x + x_size, o_y - y_size], o.light_grey)
226 308
 		
309
+
227 310
 		o_x = o_x + x_size
228 311
 		_id += 1
229 312
 		if _id % 4 == 0:
230 313
 			o_y -= y_size
231 314
 			o_x = og_x
232 315
 
316
+def draw_menu2_song(o):
317
+	bpm_inc = 4
318
+	x_size = o.width / 4
319
+	y_size = o.height / 4
320
+	og_x = 0
321
+	o_x = og_x
322
+	o_y = o.height
323
+	text_padding = 6
324
+	_id = 0
325
+	while _id < 16:
326
+	   
327
+		o.draw.rectangle((o_x, o_y, o_x + x_size, o_y - y_size), outline=0, fill=o.dark_grey)
328
+
329
+		if _id == 6:
330
+			o.center_block("Bank -", o.h2, [o_x, o_y, o_x + x_size, o_y - y_size], o.light_grey)
331
+		if _id == 7:
332
+			o.center_block("Bank +", o.h2, [o_x, o_y, o_x + x_size, o_y - y_size], o.light_grey)
333
+
334
+		o_x = o_x + x_size
335
+		_id += 1
336
+		if _id % 4 == 0:
337
+			o_y -= y_size
338
+			o_x = og_x
339
+
340
+
233 341
 def menu1_actions(self, o):
234 342
 	if o.keyState[16] == 2:
235 343
 		if o.keyState[0] == 1:
@@ -246,14 +354,15 @@ def menu1_actions(self, o):
246 354
 			self.FSM.ToTransition('toUtil')
247 355
 		if o.keyState[12] == 1:
248 356
 			o.start_playback()
357
+			play_seq(o, [o.curPattern, 0])
249 358
 		if o.keyState[13] == 1:
250 359
 			o.stop_playback()
251
-		if o.keyState[6] == 1:
252
-			if o.note_bank > 0:
253
-				o.note_bank -= 1
254
-		if o.keyState[7] == 1:
255
-			if o.note_bank < 4:
256
-				o.note_bank += 1
360
+		# if o.keyState[6] == 1:
361
+		# 	if o.note_bank > 0:
362
+		# 		o.note_bank -= 1
363
+		# if o.keyState[7] == 1:
364
+		# 	if o.note_bank < 3:
365
+		# 		o.note_bank += 1
257 366
 		if o.keyState[8] == 1:
258 367
 			if o.volume > 0:
259 368
 				o.volume -= 1
@@ -268,16 +377,16 @@ def menu1_actions(self, o):
268 377
 			#o.save_song()
269 378
 			pass
270 379
 		if o.keyState[14] == 1:
271
-			if o.sconf.as_int('bpm') > 60:
272
-				o.sconf['bpm'] = o.sconf.as_int('bpm') - o.bpm_inc
380
+			if o.bpm > 60:
381
+				o.bpm = o.bpm - o.bpm_inc
273 382
 				o.update_bpm()
274
-				text_center(o, "Master BPM", str(o.sconf['bpm']))
383
+				text_center(o, "Master BPM", str(o.bpm))
275 384
 				o.update_display(0)
276 385
 		if o.keyState[15] == 1:
277
-			if o.sconf.as_int('bpm') < 240:
278
-				o.sconf['bpm'] = o.sconf.as_int('bpm') + o.bpm_inc
386
+			if o.bpm < 240:
387
+				o.bpm = o.bpm + o.bpm_inc
279 388
 				o.update_bpm()
280
-				text_center(o, "Master BPM", str(o.sconf['bpm']))
389
+				text_center(o, "Master BPM", str(o.bpm))
281 390
 				o.update_display(0)
282 391
 
283 392
 
@@ -307,11 +416,10 @@ def menu2_actions_sample(self, o):
307 416
 			#o.soundSlots[o.eSound] = s
308 417
 			
309 418
 		elif o.keyState[2] == 1:
310
-			if o.soundSlots[o.eSound].pitch > -10:
311
-				o.soundSlots[o.eSound].pitch -= 1
312
-				text_center(o, "Sample Pitch", str(o.soundSlots[o.eSound].pitch))
313
-				o.soundSlots[o.eSound].set_pitch()
314
-				o.update_display(0)
419
+			print('delete sound ', o.eSound)
420
+			o.soundSlots[o.eSound].file = None
421
+			o.soundSlots[o.eSound].volume = 16
422
+			o.soundSlots[o.eSound].pitch = 0
315 423
 		elif o.keyState[3] == 1:
316 424
 			print('load')
317 425
 			o.FSM.FSM.ToTransition("toLoadSound")
@@ -321,23 +429,48 @@ def menu2_actions_sample(self, o):
321 429
 				o.soundSlots[o.eSound].volume -= 1
322 430
 				text_center(o, "Sample Volume", str(o.soundSlots[o.eSound].volume))
323 431
 				o.update_display(0)
432
+
324 433
 		elif o.keyState[5] == 1:
325 434
 			if o.soundSlots[o.eSound].volume < 16:
326 435
 				o.soundSlots[o.eSound].volume += 1
327 436
 				text_center(o, "Sample Volume", str(o.soundSlots[o.eSound].volume))
328 437
 				o.update_display(0)
438
+
329 439
 		elif o.keyState[6] == 1:
440
+			if o.note_bank > 0:
441
+				o.note_bank -= 1
442
+				text_center(o, "Sound Bank", str(o.note_bank))
443
+				o.update_display(0)
444
+		elif o.keyState[7] == 1:
445
+			if o.note_bank < 3:
446
+				o.note_bank += 1
447
+				text_center(o, "Sound Bank", str(o.note_bank))
448
+				o.update_display(0)
449
+
450
+		elif o.keyState[8] == 1:
330 451
 			if o.soundSlots[o.eSound].pitch > -10:
331 452
 				o.soundSlots[o.eSound].pitch -= 1
332 453
 				text_center(o, "Sample Pitch", str(o.soundSlots[o.eSound].pitch))
333 454
 				o.soundSlots[o.eSound].set_pitch()
334 455
 				o.update_display(0)
335
-		elif o.keyState[7] == 1:
456
+		elif o.keyState[9] == 1:
336 457
 			if o.soundSlots[o.eSound].pitch < 10:
337 458
 				o.soundSlots[o.eSound].pitch += 1
338 459
 				text_center(o, "Sample Pitch", str(o.soundSlots[o.eSound].pitch))
339 460
 				o.soundSlots[o.eSound].set_pitch()
340 461
 				o.update_display(0)
462
+		elif o.keyState[12] == 1:
463
+			o.odub = not o.odub
464
+			o.undo_buf = []
465
+			print('odub now is ', o.odub)
466
+			draw_menu2_sample(o)
467
+			o.update_display(0)
468
+		elif o.keyState[13] == 1:
469
+			print('undo something')
470
+			for i in o.undo_buf:
471
+				o.soundSlots[i[0]].notes[i[1]][i[2]][0] = 0
472
+				o.soundSlots[i[0]].notes[i[1]][i[2]][1] = 0
473
+			o.undo_buf = []
341 474
 
342 475
 def menu2_actions_pattern(self, o):
343 476
 	if o.keyState[17] == 2:
@@ -396,11 +529,26 @@ def menu2_actions_pattern(self, o):
396 529
 				o.update_display(0)		
397 530
 
398 531
 		elif o.keyState[7] == 1:
399
-			if o.pat_bank < 4:
532
+			if o.pat_bank < 3:
400 533
 				o.pat_bank += 1
401 534
 				text_center(o, "Pattern Bank", str(o.pat_bank))
402 535
 				o.update_display(0)		
403 536
 				
537
+def menu2_actions_song(self, o):
538
+	if o.keyState[17] == 2:
539
+		
540
+		if o.keyState[6] == 1:
541
+			if o.pat_bank > 0:
542
+				o.pat_bank -= 1
543
+				text_center(o, "Pattern Bank", str(o.pat_bank))
544
+				o.update_display(0)		
545
+		elif o.keyState[7] == 1:
546
+			if o.pat_bank < 3:
547
+				o.pat_bank += 1
548
+				text_center(o, "Pattern Bank", str(o.pat_bank))
549
+				o.update_display(0)		
550
+				
551
+
404 552
 				
405 553
 
406 554
 def menu2_actions_note(self, o):
@@ -411,12 +559,21 @@ def menu2_actions_note(self, o):
411 559
 				text_center(o, "Note Volume", str(o.note_vol))
412 560
 				o.update_display(0)		
413 561
 
414
-
415 562
 		elif o.keyState[1] == 1:
416 563
 			if o.note_vol < 16:
417 564
 				o.note_vol += 1
418 565
 				text_center(o, "Note Volume", str(o.note_vol))
419 566
 				o.update_display(0)
567
+		elif o.keyState[12] == 1:
568
+			if o.patternFollow:
569
+				o.patternFollow = False
570
+			else:
571
+				o.patternFollow = True
572
+			#o.patternFollow != o.patternFollow
573
+			print('pattern follow is ', o.patternFollow)
574
+			draw_menu2_note(o)
575
+			o.update_display(0)	
576
+			
420 577
 			
421 578
 		
422 579
 					
@@ -424,25 +581,40 @@ def menu2_actions_note(self, o):
424 581
 def util_command(self, o, command):
425 582
 	if command == "Clock":
426 583
 		self.FSM.ToTransition('toClock')		
427
-	elif command == "Ball":
584
+	elif command == "Balls":
428 585
 		self.FSM.ToTransition('toBall')		
586
+	elif command == "Defender":
587
+		self.FSM.ToTransition('toDefender')	
429 588
 	elif command == "Exit":
430 589
 		self.FSM.ToTransition('toExit')		
431 590
 	elif command == "Theme":
432 591
 		self.FSM.ToTransition('toSelTheme')		
433 592
 	elif command == "Reboot":
434
-		#self.FSM.ToTransition('toSelTheme')		
435
-		os.system("sudo reboot")
436
-
593
+		self.FSM.ToTransition('toReboot')		
594
+		#os.system("sudo reboot")
595
+	elif command == "Shutdown":
596
+		self.FSM.ToTransition('toShutdown')		
597
+	elif command == "Ping":
598
+		self.FSM.ToTransition('toPing')	
599
+	elif command == "Wifi":
600
+		self.FSM.ToTransition('toWifi')	
437 601
 
438 602
 def file_command(self, o, command):
439 603
 	if command == "Save":
440
-		o.save_song()
604
+		if o.sconf['title'] != "blank":
605
+			o.save_song()
606
+		else:
607
+			print('cant save over blank')
441 608
 	
442 609
 	elif command == "Open":
443 610
 		self.FSM.ToTransition('toOpenSong')	
444 611
 	elif command == "Save As":
445 612
 		self.FSM.ToTransition('toEnterText')	
613
+	elif command == "New":
614
+		#self.FSM.ToTransition('toEnterText')
615
+		#o.title = '_blank'
616
+		o.mconf['default_song'] = '_blank'
617
+		o.load_song()
446 618
 #==================================== 
447 619
 
448 620
 class Example(State):
@@ -580,19 +752,22 @@ class Main(State):
580 752
 			self.draw_square()
581 753
 
582 754
 			text_box1(o, "Vol", str(o.soundSlots[o.eSound].volume))
583
-			text_box2(o, "BPM", str(o.sconf['bpm']))
755
+			text_box2(o, "BPM", str(o.bpm))
584 756
 			text_box4(o, "Bank", str(o.note_bank))
585 757
 			text_box3(o, "Pitch", str(o.soundSlots[o.eSound].pitch))
586 758
 			o.update_display(0)
587 759
 
588 760
 		#o.soundSlots[2].volume = 2
761
+		self.recording = True
762
+		self.record_queue = []
763
+		self.undo_queue = []
589 764
 		super(Main, self).Enter()        
590 765
 		
591 766
 	def Execute(self):
592 767
 		o = self.FSM.owner 
593 768
 		menu1_actions(self, o)
594 769
 		menu2_actions_sample(self, o)
595
-		
770
+		#self.FSM.ToTransition('toClock')
596 771
 		if o.keyState[16] == 1:
597 772
 			draw_menu1(o)
598 773
 			o.update_display(0)
@@ -601,8 +776,8 @@ class Main(State):
601 776
 			self.draw_square()
602 777
 			#print('esound ', o.eSound)
603 778
 			#print('oss ', o.soundSlots[o.eSound].volume)
604
-			text_box1(o, "SVol", str(o.soundSlots[o.eSound].volume))
605
-			text_box2(o, "BPM", str(o.sconf['bpm']))
779
+			text_box1(o, "Vol", str(o.soundSlots[o.eSound].volume))
780
+			text_box2(o, "BPM", str(o.bpm))
606 781
 			text_box4(o, "Bank", str(o.note_bank))
607 782
 			text_box3(o, "Pitch", str(o.soundSlots[o.eSound].pitch))
608 783
 			o.update_display(0)
@@ -614,8 +789,8 @@ class Main(State):
614 789
 		elif o.keyState[17] == 4:
615 790
 			draw_header(o)
616 791
 			self.draw_square()
617
-			text_box1(o, "SVol", str(o.soundSlots[o.eSound].volume))
618
-			text_box2(o, "BPM", str(o.sconf['bpm']))
792
+			text_box1(o, "Vol", str(o.soundSlots[o.eSound].volume))
793
+			text_box2(o, "BPM", str(o.bpm))
619 794
 			text_box4(o, "Bank", str(o.note_bank))
620 795
 			text_box3(o, "Pitch", str(o.soundSlots[o.eSound].pitch))
621 796
 			o.update_display(0)
@@ -630,22 +805,21 @@ class Main(State):
630 805
 				else:
631 806
 					if k == 1:
632 807
 						note = _id + o.note_bank * 16
633
-						#if len(o.soundSlots) > note:
634
-						if 12 == 12:
635
-							
636
-							#o.soundSlots[note].play(o.note_vol)
637
-							o.soundSlots[note].play(o.note_vol)
638
-							o.eSound = note
639
-							print('now editing sound ', o.eSound) 
640
-							draw_header(o)
641
-							#text_box1(o, "SVol", str(o.soundSlots[o.eSound].volume))
642
-							text_box1(o, "SVol", str(o.slots[o.eSound].volume))
643
-							text_box2(o, "BPM", str(o.sconf['bpm']))
644
-							text_box4(o, "Bank", str(o.note_bank))
645
-							#text_box3(o, "Pitch", str(o.soundSlots[o.eSound].pitch))
646
-							text_box3(o, "Pitch", str(o.soundSlots[o.eSound].pitch))
647
-							self.draw_square()
648
-							o.update_display(0)
808
+						self.record_queue = pygame.time.get_ticks()
809
+						print('bpm is ', o.half_bpm, ' ', self.record_queue)
810
+
811
+						o.soundSlots[note].play(o.note_vol)
812
+						o.eSound = note
813
+						print('now editing sound ', o.eSound) 
814
+						draw_header(o)
815
+						#text_box1(o, "SVol", str(o.soundSlots[o.eSound].volume))
816
+						text_box1(o, "SVol", str(o.slots[o.eSound].volume))
817
+						text_box2(o, "BPM", str(o.bpm))
818
+						text_box4(o, "Bank", str(o.note_bank))
819
+						#text_box3(o, "Pitch", str(o.soundSlots[o.eSound].pitch))
820
+						text_box3(o, "Pitch", str(o.soundSlots[o.eSound].pitch))
821
+						self.draw_square()
822
+						o.update_display(0)
649 823
 			_id += 1
650 824
 
651 825
 	def ReceiveMessage(self, message):
@@ -657,10 +831,37 @@ class Main(State):
657 831
 			draw_header(o)            
658 832
 			self.draw_square()   
659 833
 			text_box1(o, "SVol", str(o.soundSlots[o.eSound].volume))
660
-			text_box2(o, "BPM", str(o.sconf['bpm']))
834
+			text_box2(o, "BPM", str(o.bpm))
661 835
 			text_box4(o, "Bank", str(o.note_bank))
662 836
 			text_box3(o, "Pitch", str(o.soundSlots[o.eSound].pitch))			         
663 837
 			o.update_display(0)
838
+		if self.record_queue != []:
839
+			cur_time = pygame.time.get_ticks()
840
+			note_pos = (cur_time - self.record_queue) - (o.half_bpm / 2)
841
+			print(note_pos)
842
+			if o.odub == True:
843
+				if note_pos > (o.half_bpm):
844
+					_note = 0
845
+					if message[1] == 0:
846
+						_note = 15
847
+					else:
848
+						_note = message[1] - 1
849
+					
850
+					if o.soundSlots[o.eSound].notes[message[0]][_note][0] != 1:
851
+						o.soundSlots[o.eSound].notes[message[0]][_note][0] = 1
852
+						o.soundSlots[o.eSound].notes[message[0]][_note][1] = o.note_vol
853
+						o.undo_buf.append([o.eSound, message[0], _note])
854
+						print(o.undo_buf)
855
+
856
+				else:
857
+					if o.soundSlots[o.eSound].notes[message[0]][message[1]][0] != 1:
858
+						o.soundSlots[o.eSound].notes[message[0]][message[1]][0] = 1
859
+						o.soundSlots[o.eSound].notes[message[0]][message[1]][1] = o.note_vol
860
+						o.undo_buf.append([o.eSound, message[0], message[1]])
861
+						print(o.undo_buf)
862
+
863
+		self.record_queue = []
864
+
664 865
 	
665 866
 	def draw_square(self):
666 867
 		o = self.FSM.owner 
@@ -677,7 +878,7 @@ class Main(State):
677 878
 				o.draw.rectangle((o_x, o_y, o_x + size, o_y - size), outline=o.light_grey, fill=o.grey, width=1)
678 879
 			#elif _id > (len(o.soundSlots) - 1):
679 880
 			elif self.has_sample(o, _id) == False:
680
-				o.draw.rectangle((o_x, o_y, o_x + size, o_y - size), outline=o.light_grey, fill=o.dark_blue, width=1)
881
+				o.draw.rectangle((o_x, o_y, o_x + size, o_y - size), outline=o.light_grey, fill=o.dark_grey, width=1)
681 882
 
682 883
 
683 884
 			else:
@@ -749,6 +950,7 @@ class SeqPlayer(State):
749 950
 
750 951
 		if o.keyState[12] == 1:
751 952
 			o.start_playback()
953
+			play_seq(o, [o.curPattern, 0])
752 954
 		if o.keyState[13] == 1:
753 955
 			o.stop_playback()        
754 956
 		#self.beat = o.playhead
@@ -809,8 +1011,8 @@ class SelectSound(State):
809 1011
 					if k == 1:
810 1012
 						o.eSound = _id
811 1013
 						o.draw.rectangle((0, 0, o.width, o.height), outline=0, fill=o.blue)
812
-						o.draw.text((0, 0), "SelSou", font=o.h1, fill=o.color_a)
813
-						o.draw.text((20, 60), str(o.eSound), font=o.h2, fill=o.color_b)
1014
+						o.draw.text((0, 0), "SelSou", font=o.h1, fill=o.light_blue)
1015
+						o.draw.text((20, 60), str(o.eSound), font=o.h2, fill=o.light_grey)
814 1016
 						self.draw_square()
815 1017
 						o.update_display(0)
816 1018
 						self.FSM.owner.soundSlots[_id].play()
@@ -836,7 +1038,7 @@ class SelectSound(State):
836 1038
 	
837 1039
 		for n in o.soundSlots[o.eSound].notes[o.ePattern]:
838 1040
 			if _id == o.eSound:
839
-				o.draw.rectangle((o_x, o_y, o_x + size, o_y + size), outline=0, fill=o.color_b)
1041
+				o.draw.rectangle((o_x, o_y, o_x + size, o_y + size), outline=0, fill=o.light_grey)
840 1042
 			else:
841 1043
 				o.draw.rectangle((o_x, o_y, o_x + size, o_y + size), outline=0, fill=o.dark_grey)
842 1044
 			o_x = o_x + size
@@ -863,6 +1065,7 @@ class SelectPattern(State):
863 1065
 		self.cur_playing = 0
864 1066
 		self.active_patterns = []
865 1067
 		self.get_active_patterns(o)
1068
+
866 1069
 		if o.keyState[16] > 0 or o.keyState[17] > 0:
867 1070
 			pass
868 1071
 		else:
@@ -893,13 +1096,11 @@ class SelectPattern(State):
893 1096
 			o.update_display(0)
894 1097
 		elif o.keyState[17] == 4:
895 1098
 			draw_header(o)
1099
+			self.get_active_patterns(o)
896 1100
 			self.draw_square()
897
-			#text_box1(o, "SVol", str(o.soundSlots[o.eSound].volume))
898
-			#text_box2(o, "BPM", str(o.sconf['bpm']))
899 1101
 			text_box1(o, "Pat", str(o.ePattern))
900 1102
 			text_box4(o, "Bank", str(o.pat_bank))
901
-			#text_box3(o, "Pitch", str(o.soundSlots[o.eSound].pitch))
902
-			self.get_active_patterns(o)
1103
+			
903 1104
 			o.update_display(0)
904 1105
 
905 1106
 
@@ -937,7 +1138,7 @@ class SelectPattern(State):
937 1138
 				draw_header(o)
938 1139
 				self.draw_square()
939 1140
 				text_box1(o, "Pat", str(o.ePattern))
940
-				text_box4(o, "PBank", str(o.pat_bank))
1141
+				text_box4(o, "Bank", str(o.pat_bank))
941 1142
 				o.update_display(0)
942 1143
 
943 1144
 	def draw_square(self):
@@ -949,13 +1150,13 @@ class SelectPattern(State):
949 1150
 		_id = 0
950 1151
 		for n in o.soundSlots[o.eSound].notes[o.ePattern]:
951 1152
 			if (_id + (o.pat_bank * 16)) == o.ePattern:
952
-				o.draw.rectangle((o_x, o_y, o_x + size, o_y - size), outline=o.olive, fill=o.olive, width=1)
1153
+				o.draw.rectangle((o_x, o_y, o_x + size, o_y - size), outline=o.light_grey, fill=o.olive, width=1)
953 1154
 			elif (_id + (o.pat_bank * 16)) == self.cur_playing:
954
-				o.draw.rectangle((o_x, o_y, o_x + size, o_y - size), outline=o.olive, fill=o.light_grey, width=1)
1155
+				o.draw.rectangle((o_x, o_y, o_x + size, o_y - size), outline=o.light_grey, fill=o.light_grey, width=1)
955 1156
 			elif self.active_patterns[_id] == 1:
956 1157
 				o.draw.rectangle((o_x, o_y, o_x + size, o_y - size), outline=o.light_grey, fill=o.blue, width=1)
957 1158
 			else:
958
-				o.draw.rectangle((o_x, o_y, o_x + size, o_y - size), outline=o.light_grey, fill=o.dark_blue, width=1)
1159
+				o.draw.rectangle((o_x, o_y, o_x + size, o_y - size), outline=o.light_grey, fill=o.dark_grey, width=1)
959 1160
 			o_x = o_x + size
960 1161
 			_id += 1
961 1162
 			if _id % 4 == 0:
@@ -1003,12 +1204,14 @@ class EditSoundSequence(State):
1003 1204
 		o = self.FSM.owner 
1004 1205
 		o.header_text = "Note Edit"
1005 1206
 		o.pub.register("beat", self)
1207
+		self.curPattern = o.ePattern
1006 1208
 		if o.keyState[16] > 0 or o.keyState[17] > 0:
1007 1209
 			pass
1008 1210
 		else:
1009 1211
 			draw_header(o)
1010 1212
 			self.draw_square()
1011 1213
 			text_box1(o, "Note Vol", str(o.note_vol))
1214
+			text_box3(o, "Pat", str(self.curPattern))
1012 1215
 			o.update_display(0)
1013 1216
 		super(EditSoundSequence, self).Enter()        
1014 1217
 		
@@ -1023,6 +1226,7 @@ class EditSoundSequence(State):
1023 1226
 			draw_header(o)
1024 1227
 			self.draw_square()
1025 1228
 			text_box1(o, "Note Vol", str(o.note_vol))
1229
+			text_box3(o, "Pat", str(self.curPattern))
1026 1230
 			o.update_display(0)
1027 1231
 
1028 1232
 		if o.keyState[17] == 1:
@@ -1032,26 +1236,32 @@ class EditSoundSequence(State):
1032 1236
 			draw_header(o)
1033 1237
 			self.draw_square()
1034 1238
 			text_box1(o, "Note Vol", str(o.note_vol))
1035
-			
1239
+			text_box3(o, "Pat", str(self.curPattern))
1036 1240
 			o.update_display(0)
1037 1241
 
1038
-		if o.keyState[16] == 2:
1242
+		if o.keyState[16] > 0 or o.keyState[17] > 0:
1039 1243
 			pass
1040 1244
 
1041 1245
 		else:
1042 1246
 			_id = 0
1043 1247
 			for k in self.FSM.owner.keyState:
1044 1248
 				if _id < 16 and k == 1:
1045
-					if o.soundSlots[o.eSound].notes[o.ePattern][_id][0] == 1:
1249
+					if o.soundSlots[o.eSound].notes[self.curPattern][_id][0] == 1:
1046 1250
 						print('turn note off')
1047
-						o.soundSlots[o.eSound].notes[o.ePattern][_id][0] = 0
1048
-						o.soundSlots[o.eSound].notes[o.ePattern][_id][1] = 0
1251
+						o.soundSlots[o.eSound].notes[self.curPattern][_id][0] = 0
1252
+						o.soundSlots[o.eSound].notes[self.curPattern][_id][1] = 0
1049 1253
 					else:
1050 1254
 						print('turn note on')
1051
-						o.soundSlots[o.eSound].notes[o.ePattern][_id][0] = 1
1052
-						o.soundSlots[o.eSound].notes[o.ePattern][_id][1] = o.note_vol
1255
+						o.soundSlots[o.eSound].notes[self.curPattern][_id][0] = 1
1256
+						o.soundSlots[o.eSound].notes[self.curPattern][_id][1] = o.note_vol
1257
+					draw_header(o)
1258
+					self.draw_square()
1259
+					text_box1(o, "Note Vol", str(o.note_vol))			
1260
+					text_box3(o, "Pat", str(self.curPattern))
1261
+					o.update_display(0)
1053 1262
 				_id += 1
1054 1263
 
1264
+
1055 1265
 		
1056 1266
 	def draw_square(self):
1057 1267
 		o = self.FSM.owner 
@@ -1060,12 +1270,12 @@ class EditSoundSequence(State):
1060 1270
 		o_x = og_x
1061 1271
 		o_y = 127
1062 1272
 		_id = 0
1063
-		for n in o.soundSlots[o.eSound].notes[o.ePattern]:
1064
-			if _id == o.playhead:
1065
-				if o.curPattern == o.ePattern:
1066
-					o.draw.rectangle((o_x, o_y, o_x + size, o_y - size), outline=o.olive, fill=o.olive, width=1)
1273
+		for n in o.soundSlots[o.eSound].notes[self.curPattern]:
1274
+			if _id == o.playhead and o.playing:
1275
+				if o.curPattern == self.curPattern:
1276
+					o.draw.rectangle((o_x, o_y, o_x + size, o_y - size), outline=o.light_grey, fill=o.olive, width=1)
1067 1277
 				else:
1068
-					o.draw.rectangle((o_x, o_y, o_x + size, o_y - size), outline=o.olive, fill=o.pink, width=1)
1278
+					o.draw.rectangle((o_x, o_y, o_x + size, o_y - size), outline=o.light_grey, fill=o.pink, width=1)
1069 1279
 			elif n[0] == 1:
1070 1280
 				o.draw.rectangle((o_x, o_y, o_x + size, o_y - size), outline=o.light_grey, fill=o.light_grey, width=1)
1071 1281
 			else:
@@ -1086,13 +1296,18 @@ class EditSoundSequence(State):
1086 1296
 			draw_header(o)            
1087 1297
 			self.draw_square()  
1088 1298
 			text_box1(o, "Note Vol", str(o.note_vol))
1299
+			text_box3(o, "Pat", str(self.curPattern))
1300
+		if o.patternFollow:
1301
+			self.curPattern = message[0]
1302
+		else:
1303
+			self.curPattern = o.ePattern
1304
+		print('message ', message)
1089 1305
 		o.update_display(0)
1090 1306
 		
1091 1307
 	def Exit(self):
1092 1308
 		self.FSM.owner.pub.unregister("beat", self)
1093 1309
 
1094
-#==================================== 
1095
-			
1310
+
1096 1311
 class EditSong(State):
1097 1312
 	def __init__(self,FSM):
1098 1313
 		super(EditSong, self).__init__(FSM)    
@@ -1105,8 +1320,9 @@ class EditSong(State):
1105 1320
 			pass
1106 1321
 		else:
1107 1322
 			draw_header(o)
1108
-			o.draw.text((20, 30), "Current Song", font=o.h2, fill=o.light_grey)
1109
-			o.draw.text((20, 50), str(o.song), font=o.h2, fill=o.light_grey)
1323
+			self.draw_main(o)
1324
+			# o.draw.text((20, 30), "Current Song", font=o.h2, fill=o.light_grey)
1325
+			# o.draw.text((20, 50), str(o.song), font=o.h2, fill=o.light_grey)
1110 1326
 			o.update_display(0)
1111 1327
 		self.new_song = []
1112 1328
 		super(EditSong, self).Enter()        
@@ -1115,20 +1331,31 @@ class EditSong(State):
1115 1331
 		o = self.FSM.owner 
1116 1332
 
1117 1333
 		menu1_actions(self, o)
1334
+		menu2_actions_song(self, o)
1118 1335
 		if o.keyState[16] == 1:
1119 1336
 			draw_menu1(o)
1120 1337
 			o.update_display(0)
1121 1338
 		elif o.keyState[16] == 4:
1122 1339
 			draw_header(o)
1123
-			if self.new_song == []:
1124
-				o.draw.text((20, 30), "Current Song", font=o.h2, fill=o.light_grey)
1125
-				o.draw.text((20, 50), str(o.song), font=o.h2, fill=o.light_grey)
1126
-			else:
1127
-				o.draw.text((20, 30), "New Song", font=o.h2, fill=o.pink)
1128
-				o.draw.text((20, 50), str(self.new_song), font=o.h2, fill=o.pink)
1340
+			self.draw_main(o)
1341
+			# if self.new_song == []:
1342
+			# 	o.draw.text((20, 30), "Current Song", font=o.h2, fill=o.light_grey)
1343
+			# 	o.draw.text((20, 50), str(o.song), font=o.h2, fill=o.light_grey)
1344
+			# else:
1345
+			# 	o.draw.text((20, 30), "New Song", font=o.h2, fill=o.pink)
1346
+			# 	o.draw.text((20, 50), str(self.new_song), font=o.h2, fill=o.pink)
1347
+			o.update_display(0)
1348
+
1349
+		if o.keyState[17] == 1:
1350
+			draw_menu2_song(o)
1351
+			o.update_display(0)
1352
+		elif o.keyState[17] == 4:
1353
+			draw_header(o)
1354
+			self.draw_main(o)
1129 1355
 			o.update_display(0)
1356
+		if o.keyState[16] > 0 or o.keyState[17] > 0:
1130 1357
 
1131
-		if o.keyState[16] > 0:
1358
+		#if o.keyState[16] > 0:
1132 1359
 			pass
1133 1360
 		else:
1134 1361
 			_id = 0
@@ -1136,11 +1363,37 @@ class EditSong(State):
1136 1363
 				if k == 1 and _id < 16:
1137 1364
 					self.new_song.append((_id + (o.pat_bank * 16)))
1138 1365
 					draw_header(o)
1139
-					o.draw.text((20, 30), "New Song", font=o.h2, fill=o.pink)
1140
-					o.draw.text((20, 50), str(self.new_song), font=o.h2, fill=o.pink)
1366
+					self.draw_main(o)
1367
+					#o.draw.text((20, 30), "New Song", font=o.h2, fill=o.pink)
1368
+					#o.draw.text((20, 50), str(self.new_song), font=o.h2, fill=o.pink)
1141 1369
 					o.update_display(0)
1142 1370
 				_id += 1        
1143 1371
 
1372
+
1373
+	def draw_main(self, o):
1374
+		ypos = 35
1375
+		ysize = 20
1376
+		tmp_song = [8, 6, 7, 5, 3, 0, 9]
1377
+		lines = breakup_song_text(o.song)
1378
+		#lines = breakup_song_text(tmp_song)
1379
+
1380
+		if self.new_song != []:
1381
+			#o.draw.text((20, 30), "New Song", font=o.h2, fill=o.pink)
1382
+			lines = breakup_song_text(self.new_song)
1383
+			o.center_block("New Song", o.h2, [0, ypos, o.width, ypos + ysize], o.pink)
1384
+		else:
1385
+			#o.draw.text((20, 30), "Current Song", font=o.h2, fill=o.light_grey)
1386
+			o.center_block("Current Song", o.h2, [0, ypos, o.width, ypos + ysize], o.light_grey)
1387
+
1388
+		ypos += ysize	
1389
+		o.center_block(lines[0], o.h2, [0, ypos, o.width, ypos + ysize], o.light_grey)
1390
+		ypos += ysize
1391
+		o.center_block(lines[1], o.h2, [0, ypos, o.width, ypos + ysize], o.light_grey)
1392
+		ypos += ysize
1393
+		o.center_block(lines[2], o.h2, [0, ypos, o.width, ypos + ysize], o.light_grey)
1394
+		ypos += ysize
1395
+		o.center_block(lines[3], o.h2, [0, ypos, o.width, ypos + ysize], o.light_grey)
1396
+
1144 1397
 	def ReceiveMessage(self, message):
1145 1398
 		_id = 0
1146 1399
 		o = self.FSM.owner 
@@ -1290,7 +1543,7 @@ class Util(State):
1290 1543
 		o = self.FSM.owner 
1291 1544
 		o.header_text = "Utilities"
1292 1545
 		o.pub.register("beat", self)
1293
-		self.menu = ["Clock", "Ball", "Exit", "Shutdown", "Reboot", "Theme", "Update"]
1546
+		self.menu = ["Clock", "Balls", "Defender", "Exit", "Shutdown", "Reboot", "Theme", "Ping", "Wifi", "Update"]
1294 1547
 		self.cur_el = 0
1295 1548
 
1296 1549
 		if o.keyState[16] > 0 or o.keyState[17] > 0:
@@ -1421,7 +1674,7 @@ class Ball(State):
1421 1674
 		self.ballx = self.ball_size
1422 1675
 		self.bally = self.ball_size
1423 1676
 		
1424
-		self.ball_speed = 15
1677
+		self.ball_speed = 8
1425 1678
 		self.ball_x_dir = 1
1426 1679
 		self.ball_y_dir = 1
1427 1680
 		
@@ -1434,7 +1687,7 @@ class Ball(State):
1434 1687
 		self.xmult = 1.0
1435 1688
 
1436 1689
 		o = self.FSM.owner 
1437
-		o.header_text = "Ball"
1690
+		o.header_text = "Balls"
1438 1691
 		o.pub.register("beat", self)
1439 1692
 		if o.keyState[16] > 0 or o.keyState[17] > 0:
1440 1693
 			pass
@@ -1526,9 +1779,10 @@ class Clock(State):
1526 1779
 		self.ball_sizex, self.ball_sizey = o.h3.getsize("18:88:88")
1527 1780
 		self.ball_sizex /= 2
1528 1781
 		self.ball_sizey /= 2
1782
+		#self.ball_sizey += 10
1529 1783
 		self.ballx = o.width / 2 
1530 1784
 		self.bally = o.height / 2
1531
-		self.ball_speed = 1
1785
+		self.ball_speed = .5
1532 1786
 		self.ball_x_dir = 1
1533 1787
 		self.ball_y_dir = 1
1534 1788
 		
@@ -1553,16 +1807,31 @@ class Clock(State):
1553 1807
 			pass
1554 1808
 		else:			
1555 1809
 			current_time = time.strftime("%-I:%M:%S")
1810
+			s = int(time.strftime("%S"))
1811
+			if s % 2 == 0:
1812
+				current_time = time.strftime("%-I:%M.%S")
1556 1813
 
1557 1814
 			if self.ballx > (o.width - self.ball_sizex) or self.ballx < (0 + self.ball_sizex):
1558 1815
 				self.ball_x_dir *= -1
1559
-			if (self.bally > o.height - self.ball_sizey) or (self.bally < 0 + self.ball_sizey):
1816
+			if (self.bally > o.height - self.ball_sizey - 20) or (self.bally < 0 + self.ball_sizey):
1560 1817
 				self.ball_y_dir *= -1
1561 1818
 
1819
+			x1 = self.ballx - self.ball_sizex
1820
+			x2 = self.ballx + self.ball_sizex
1821
+			y1 = self.bally - self.ball_sizey
1822
+			y2 = self.bally + self.ball_sizey
1562 1823
 			self.ballx += self.ball_speed * self.ball_x_dir
1563 1824
 			self.bally += self.ball_speed * self.ball_y_dir
1564
-			o.draw.rectangle((0, 0, o.width, o.height), outline=0, fill=o.bg_color)			
1565
-			o.draw.text((self.ballx - self.ball_sizex, self.bally - self.ball_sizey), current_time, align='center', font=o.h3, fill=o.light_grey)
1825
+			o.draw.rectangle((0, 0, o.width, o.height), outline=0, fill=o.blue)			
1826
+			#o.draw.rectangle((x1, y1, x2, y2), outline=0, fill=o.dark_grey)			
1827
+
1828
+			#o.draw.text((self.ballx - self.ball_sizex, self.bally - self.ball_sizey), current_time, align='center', font=o.h3, fill=o.light_grey)
1829
+			o.center_block(current_time, o.h3, [x1, y1, x2, y2], o.light_grey)
1830
+			today = date.today()
1831
+			current_date = today.strftime('%A')
1832
+			current_date += ', ' + today.strftime("%b %d, %Y")
1833
+			#o.draw.text((self.ballx - self.ball_sizex, (self.bally + 45) - self.ball_sizey), current_date, align='center', font=o.h2, fill=o.light_grey)
1834
+			o.center_block(current_date, o.h2, [x1, y1 + 35, x2, y2 + 35], o.light_grey)
1566 1835
 			o.update_display(0)
1567 1836
 		
1568 1837
 	def ReceiveMessage(self, message):
@@ -1595,6 +1864,62 @@ class Exit(State):
1595 1864
 
1596 1865
 #==================================== 
1597 1866
 
1867
+#==================================== 
1868
+
1869
+class Reboot(State):
1870
+	def __init__(self,FSM):
1871
+		super(Reboot, self).__init__(FSM)    
1872
+		
1873
+	def Enter(self):
1874
+		o = self.FSM.owner
1875
+		o.draw.rectangle((0, 0, o.width, o.height), outline=0, fill=o.blue)			
1876
+		o.center_block("rebooting", o.h2, [0, 0, o.width,o.height], o.light_grey)
1877
+		o.update_display(0)
1878
+		command = 'bash -c "sleep 5; sudo shutdown -r now"&'
1879
+		os.system(command)
1880
+		pygame.quit()
1881
+		sys.exit()
1882
+		super(Reboot, self).Enter()        
1883
+		
1884
+	def Execute(self):
1885
+		pass
1886
+		#self.FSM.stateLife += 1
1887
+		#os.system('sudo shutdown -r now')
1888
+		
1889
+	def Exit(self):
1890
+		pass
1891
+
1892
+#==================================== 
1893
+
1894
+
1895
+#==================================== 
1896
+
1897
+class Shutdown(State):
1898
+	def __init__(self,FSM):
1899
+		super(Shutdown, self).__init__(FSM)    
1900
+		
1901
+	def Enter(self):
1902
+		o = self.FSM.owner
1903
+		o.draw.rectangle((0, 0, o.width, o.height), outline=0, fill=o.blue)			
1904
+		o.center_block("shutting down", o.h2, [0, 0, o.width,o.height - 20], o.light_grey)
1905
+		o.center_block("(unplug in 20s)", o.h2, [0, 10, o.width,o.height+10], o.light_grey)
1906
+		o.center_block("thank you for playing", o.h2, [0, 30, o.width,o.height+30], o.light_grey)
1907
+		o.update_display(0)
1908
+		command = 'bash -c "sleep 5; sudo shutdown -h now"&'
1909
+		os.system(command)
1910
+		pygame.quit()
1911
+		sys.exit()
1912
+		super(Shutdown, self).Enter()        
1913
+		
1914
+	def Execute(self):
1915
+		pass
1916
+		#self.FSM.stateLife += 1
1917
+		#os.system('sudo shutdown -r now')
1918
+		
1919
+	def Exit(self):
1920
+		pass
1921
+
1922
+#==================================== 
1598 1923
 class SelTheme(State):
1599 1924
 	def __init__(self,FSM):
1600 1925
 		super(SelTheme, self).__init__(FSM)    
@@ -1604,7 +1929,7 @@ class SelTheme(State):
1604 1929
 		o.header_text = "Select Theme"
1605 1930
 		o.pub.register("beat", self)
1606 1931
 		self.cur_el = 0
1607
-		self.globbed = glob.glob('/home/pi/zpc_ct/themes/*.thm')
1932
+		self.globbed = glob.glob('/home/pi/zpc_ct/user/themes/*.thm')
1608 1933
 		self.globbed.sort()
1609 1934
 		self.names = [os.path.basename(x) for x in self.globbed]
1610 1935
 		self.names = [os.path.splitext(x)[0] for x in self.names]
@@ -1797,7 +2122,7 @@ class OpenSong(State):
1797 2122
 			self.draw_footer(o)
1798 2123
 			self.draw_main(o)
1799 2124
 			o.update_display(0)	
1800
-			print('draw butt')				
2125
+			
1801 2126
 
1802 2127
 		if o.keyState[16] > 0 or o.keyState[17] > 0:
1803 2128
 			pass
@@ -1824,6 +2149,7 @@ class OpenSong(State):
1824 2149
 			if o.keyState[3] == 1:
1825 2150
 				#open_command(self, o, self.menu[self.cur_el])
1826 2151
 				o.mconf['default_song'] = self.menu[self.cur_el]
2152
+				o.save_config()
1827 2153
 				o.load_song()
1828 2154
 				#pass
1829 2155
 
@@ -1901,8 +2227,23 @@ class EnterText(State):
1901 2227
 		
1902 2228
 	def Enter(self):
1903 2229
 		o = self.FSM.owner 
1904
-		
2230
+	
2231
+		menu1_actions(self, o)
2232
+		if o.keyState[16] == 1:
2233
+			draw_menu1(o)
2234
+			o.update_display(0)
2235
+		elif o.keyState[16] == 4:
2236
+			draw_header(o)
2237
+			self.draw_footer(o)
2238
+			self.draw_main(o)
2239
+			o.update_display(0)
1905 2240
 		self.input_string = ""
2241
+		if o.sconf['title'] == 'blank':
2242
+
2243
+			self.input_string += str(datetime.today().strftime('%Y%m%d'))
2244
+		else:
2245
+
2246
+			self.input_string += o.sconf['title']
1906 2247
 		#if 
1907 2248
 		o.header_text = "EnterText"
1908 2249
 		o.pub.register("beat", self)
@@ -1946,7 +2287,14 @@ class EnterText(State):
1946 2287
 		o = self.FSM.owner 
1947 2288
 		y_size = o.height / 4
1948 2289
 		if o.keyState[11] == 1:
1949
-			self.FSM.ToTransition('toFile')		
2290
+			if self.input_string != 'blank':
2291
+				o.title = self.input_string
2292
+				#o.bpm = o.sconf['bpm']
2293
+				o.sconf['title'] = self.input_string
2294
+				
2295
+				print('fsm saving')
2296
+				o.save_song()
2297
+				self.FSM.ToTransition('toFile')		
1950 2298
 		if o.keyState[16] > 0 and o.keyState[17] > 0:
1951 2299
 			pass
1952 2300
 		else:
@@ -2053,11 +2401,16 @@ class LoadSound(State):
2053 2401
 		o.pub.register("beat", self)
2054 2402
 		self.cur_el = 0
2055 2403
 		
2404
+		self.press_ticks_up = None
2405
+		self.press_ticks_down = None
2056 2406
 
2057 2407
 		self.menu = []
2058 2408
 
2059 2409
 		self.menu.append("..")
2060 2410
 		self.menu += self.get_file_list(o)
2411
+		if o.last_load_sound_id != None and o.last_load_sound_id <= len(self.menu):
2412
+			self.cur_el = o.last_load_sound_id
2413
+			print('setting cur_el ', self.cur_el)
2061 2414
 		self.last_preview = None
2062 2415
 
2063 2416
 		if o.keyState[16] > 0 or o.keyState[17] > 0:
@@ -2091,25 +2444,48 @@ class LoadSound(State):
2091 2444
 		if o.keyState[16] > 0 or o.keyState[17] > 0:
2092 2445
 			pass
2093 2446
 		else:
2094
-			if o.keyState[0] == 1:
2447
+
2448
+			since_up = 0		
2449
+			if o.keyState[0] == 2:
2450
+				if self.press_ticks_up == None:
2451
+					self.press_ticks_up = pygame.time.get_ticks()
2452
+				since_up = pygame.time.get_ticks() - self.press_ticks_up
2453
+			else:
2454
+				self.press_ticks_up = None
2455
+
2456
+				self.press_ticks_up = pygame.time.get_ticks()
2457
+
2458
+
2459
+			if o.keyState[0] == 1 or since_up > 250:
2095 2460
 				if self.cur_el > 0:
2096 2461
 					self.cur_el -= 1
2097
-					# o.mconf['theme'] = self.menu[self.cur_el]					
2098
-					# o.save_config()
2099
-					# o.load_config()
2100
-					# o.apply_theme()
2101
-					#print('cur el down is ', self.cur_el)
2462
+					self.draw_main(o)
2463
+					o.update_display(0)	
2464
+					self.press_ticks_up = pygame.time.get_ticks()
2465
+			
2466
+					
2102 2467
 
2103
-					#o.applyTheme
2104
-			if o.keyState[1] == 1:
2468
+			since_down = 0		
2469
+			if o.keyState[1] == 2:
2470
+				if self.press_ticks_down == None:
2471
+					self.press_ticks_down = pygame.time.get_ticks()
2472
+				since_down = pygame.time.get_ticks() - self.press_ticks_down
2473
+			else:
2474
+				self.press_ticks_down = None
2475
+
2476
+				self.press_ticks_down = pygame.time.get_ticks()
2477
+
2478
+
2479
+			if o.keyState[1] == 1 or since_down > 250:
2105 2480
 				if self.cur_el < (len(self.menu) - 1):
2106 2481
 					self.cur_el += 1
2107
-					# o.mconf['theme'] = self.menu[self.cur_el]					
2108
-					# o.save_config()
2109
-					# o.load_config()
2110
-					# o.apply_theme()
2111
-					#print('cur el up is ', self.cur_el)
2112
-					#print('loading theme ', self.menu[self.cur_el], '-- ', o.mconf['theme'])
2482
+					self.draw_main(o)
2483
+					o.update_display(0)	
2484
+					self.press_ticks_down = pygame.time.get_ticks()
2485
+			
2486
+			
2487
+
2488
+
2113 2489
 			if o.keyState[2] == 1:
2114 2490
 				if self.is_wav():
2115 2491
 					if self.last_preview == self.menu[self.cur_el]:
@@ -2117,11 +2493,14 @@ class LoadSound(State):
2117 2493
 					else:
2118 2494
 						snd = pygame.mixer.Sound(o.load_song_dir + self.menu[self.cur_el])
2119 2495
 						pygame.mixer.Sound.play(snd) 
2496
+						#o.last_load_sound_id = self.cur_el
2497
+
2120 2498
 
2121 2499
 			if o.keyState[3] == 1:
2122 2500
 				if self.menu[self.cur_el] == '..':
2123 2501
 					print('directory up')
2124
-					if o.load_song_dir == '/home/pi/zpc_ct/sounds/':
2502
+					o.last_load_sound_id = None
2503
+					if o.load_song_dir == '/home/pi/zpc_ct/user/sounds/':
2125 2504
 						print('root dir - cant go up')
2126 2505
 					else:
2127 2506
 						o.load_song_dir = os.path.dirname(os.path.dirname(o.load_song_dir))
@@ -2148,16 +2527,12 @@ class LoadSound(State):
2148 2527
 					o.soundSlots[o.eSound].pitch = 0
2149 2528
 					o.soundSlots[o.eSound].create_sound()
2150 2529
 					o.soundSlots[o.eSound].set_pitch()
2151
-				#pass
2530
+					o.last_load_sound_id = self.cur_el
2531
+					self.FSM.ToTransition('toMain')
2152 2532
 
2153 2533
 	def get_file_list(self, o):
2154
-		#root, dirs, files = os.walk(o.load_song_dir).next()
2155 2534
 		dirs = os.listdir(o.load_song_dir)
2156
-		#print('got file list')
2157
-		#print(root)
2158
-		#print(dirs)
2159 2535
 		dirs.sort()
2160
-		#print(files)
2161 2536
 
2162 2537
 		return dirs
2163 2538
 
@@ -2247,3 +2622,242 @@ class LoadSound(State):
2247 2622
 	def Exit(self):
2248 2623
 		self.FSM.owner.pub.unregister("beat", self)
2249 2624
 
2625
+#==================================== 
2626
+
2627
+class Ping(State):
2628
+	def __init__(self,FSM):
2629
+		super(Ping, self).__init__(FSM)    
2630
+		
2631
+	def Enter(self):
2632
+		o = self.FSM.owner
2633
+		
2634
+		o.header_text = "Ping"
2635
+		o.pub.register("beat", self)
2636
+
2637
+		#o.draw.rectangle((0, 0, o.width, o.height), outline=0, fill=o.blue)			
2638
+		#o.center_block("ping", o.h2, [0, 0, o.width,o.height], o.light_grey)
2639
+		#o.update_display(0)
2640
+
2641
+		
2642
+		
2643
+
2644
+		self.pinging = self.check_ping()
2645
+
2646
+		self.draw_main(o)
2647
+
2648
+		draw_header(o)
2649
+		o.update_display(0)
2650
+		super(Ping, self).Enter()        
2651
+		
2652
+	def Execute(self):
2653
+		o = self.FSM.owner 
2654
+		menu1_actions(self, o)
2655
+		if o.keyState[16] == 1:
2656
+			draw_menu1(o)
2657
+			o.update_display(0)
2658
+		elif o.keyState[16] == 4:
2659
+			draw_header(o)
2660
+			#self.draw_footer(o)
2661
+			self.draw_main(o)
2662
+			o.update_display(0)
2663
+
2664
+		if o.keyState[0] == 1 or o.keyState[0] == 3 or o.keyState[1] == 1 or o.keyState[1] == 3 or o.keyState[2] == 1 or o.keyState[2] == 3 or o.keyState[3] == 1 or o.keyState[3] == 3:
2665
+			draw_header(o)
2666
+			#self.draw_footer(o)
2667
+			self.draw_main(o)
2668
+			o.update_display(0)	
2669
+			
2670
+		
2671
+	def draw_main(self, o):
2672
+		o.center_block(self.pinging, o.h2, [0, 0, o.width, o.height], o.light_grey)
2673
+
2674
+	def check_ping(self):
2675
+		hostname = "8.8.8.8"
2676
+		response = os.system("ping -c 1 " + hostname)
2677
+		# and then check the response...
2678
+		if response == 0:
2679
+			pingstatus = "Network Active "
2680
+		else:
2681
+			pingstatus = "Network Error "
2682
+
2683
+		return pingstatus
2684
+
2685
+	def ReceiveMessage(self, message):
2686
+		o = self.FSM.owner 
2687
+		play_seq(o, message)
2688
+
2689
+	def Exit(self):
2690
+		self.FSM.owner.pub.unregister("beat", self)
2691
+
2692
+#==================================== 
2693
+
2694
+
2695
+class Wifi(State):
2696
+	def __init__(self,FSM):
2697
+		super(Wifi, self).__init__(FSM)    
2698
+		
2699
+	def Enter(self):
2700
+		o = self.FSM.owner
2701
+		
2702
+		o.header_text = "Wifi"
2703
+		o.pub.register("beat", self)
2704
+		
2705
+		self.ipad = self.extract_ip()
2706
+		self.ssid = os.popen("sudo iwgetid -r").read()
2707
+		o.center_block(self.ipad, o.h2, [0, 0, o.width,o.height], o.light_grey)
2708
+
2709
+		draw_header(o)
2710
+		self.draw_main(o)
2711
+		o.update_display(0)
2712
+		super(Wifi, self).Enter()        
2713
+		
2714
+	def Execute(self):
2715
+		o = self.FSM.owner 
2716
+		menu1_actions(self, o)
2717
+		if o.keyState[16] == 1:
2718
+			draw_menu1(o)
2719
+			o.update_display(0)
2720
+		elif o.keyState[16] == 4:
2721
+			draw_header(o)
2722
+			#self.draw_footer(o)
2723
+			self.draw_main(o)
2724
+			o.update_display(0)
2725
+
2726
+		if o.keyState[0] == 1 or o.keyState[0] == 3 or o.keyState[1] == 1 or o.keyState[1] == 3 or o.keyState[2] == 1 or o.keyState[2] == 3 or o.keyState[3] == 1 or o.keyState[3] == 3:
2727
+			draw_header(o)
2728
+			#self.draw_footer(o)
2729
+			self.draw_main(o)
2730
+			o.update_display(0)	
2731
+			
2732
+		
2733
+	def draw_main(self, o):
2734
+		o.center_block(self.ipad, o.h2, [0, 0, o.width, o.height], o.light_grey)
2735
+		o.center_block(self.ssid, o.h2, [0, 40, o.width, o.height+40], o.light_grey)
2736
+
2737
+
2738
+	def extract_ip(self):
2739
+		st = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
2740
+		try:       
2741
+			#st.connect(('10.255.255.255', 1))
2742
+			st.connect(("8.8.8.8", 80))
2743
+			IP = st.getsockname()[0]
2744
+		except Exception:
2745
+			IP = '127.0.0.1'
2746
+		finally:
2747
+			st.close()
2748
+		return IP
2749
+	#print(extract_ip())		
2750
+
2751
+	def ReceiveMessage(self, message):
2752
+		o = self.FSM.owner 
2753
+		play_seq(o, message)
2754
+
2755
+	def Exit(self):
2756
+		self.FSM.owner.pub.unregister("beat", self)
2757
+
2758
+#==================================== 
2759
+
2760
+
2761
+
2762
+class Defender(State):
2763
+	def __init__(self,FSM):
2764
+		super(Defender, self).__init__(FSM)    
2765
+		
2766
+	def Enter(self):
2767
+		self.ball_size = 10
2768
+		self.ballx = self.ball_size
2769
+		self.bally = self.ball_size
2770
+		
2771
+		self.ball_speed = 8
2772
+		self.ball_x_dir = 1
2773
+		self.ball_y_dir = 1
2774
+		
2775
+		self.ball2x = self.ball_size + 180
2776
+		self.ball2y = self.ball_size + 70
2777
+	
2778
+		self.ball2_x_dir = -1
2779
+		self.ball2_y_dir = -1
2780
+
2781
+		self.xmult = 1.0
2782
+
2783
+		o = self.FSM.owner 
2784
+		o.header_text = "Balls"
2785
+		o.pub.register("beat", self)
2786
+		if o.keyState[16] > 0 or o.keyState[17] > 0:
2787
+			pass
2788
+		else:
2789
+			draw_header(o)
2790
+			o.update_display(0)
2791
+		super(Defender, self).Enter()        
2792
+		
2793
+	def Execute(self):
2794
+		o = self.FSM.owner 
2795
+		menu1_actions(self, o)
2796
+		if o.keyState[16] == 1:
2797
+			draw_menu1(o)
2798
+			o.update_display(0)
2799
+		
2800
+
2801
+		if o.keyState[16] > 0 or o.keyState[17] > 0:
2802
+			pass
2803
+		else:			
2804
+			now = datetime.now()
2805
+			current_time = time.strftime("%-I:%M %p")
2806
+
2807
+
2808
+			if self.ballx < (0 + self.ball_size):
2809
+				self.ball_x_dir = 1
2810
+			if self.ballx > (o.width - self.ball_size):
2811
+				self.ball_x_dir = -1
2812
+
2813
+			if self.bally < (0 + self.ball_size):
2814
+				self.ball_y_dir = 1
2815
+			if self.bally > (o.height - self.ball_size):
2816
+				self.ball_y_dir = -1
2817
+
2818
+			# if self.ballx > (o.width - self.ball_size) or self.ballx < (0 + self.ball_size):
2819
+			# 	self.ball_x_dir *= -1
2820
+			# if self.bally > (o.height - self.ball_size) or self.bally < (0 + self.ball_size):
2821
+			# 	self.ball_y_dir *= -1
2822
+
2823
+			self.ballx += self.ball_speed * self.ball_x_dir
2824
+			self.bally += self.ball_speed * self.ball_y_dir
2825
+
2826
+
2827
+			if self.ball2x < (0 + self.ball_size):
2828
+				self.ball2_x_dir = 1
2829
+				self.xmult = random.uniform(.6, 1.2)
2830
+			if self.ball2x > (o.width - self.ball_size):
2831
+				self.ball2_x_dir = -1
2832
+				self.xmult = random.uniform(.6, 1.2)
2833
+
2834
+			if self.ball2y < (0 + self.ball_size):
2835
+				self.ball2_y_dir = 1
2836
+			if self.ball2y > (o.height - self.ball_size):
2837
+				self.ball2_y_dir = -1			
2838
+
2839
+
2840
+			# if self.ball2x > (o.width - self.ball_size) or self.ball2x < (0 + self.ball_size):
2841
+			# 	self.ball2_x_dir *= -1
2842
+			# 	self.xmult = random.uniform(.8, 1.2)
2843
+			# if self.ball2y > (o.height - self.ball_size) or self.ball2y < (0 + self.ball_size):
2844
+			# 	self.ball2_y_dir *= -1
2845
+
2846
+			self.ball2x += (self.ball_speed * self.ball2_x_dir) * self.xmult
2847
+			self.ball2y += (self.ball_speed * self.ball2_y_dir) 
2848
+
2849
+			o.draw.rectangle((0, 0, o.width, o.height), outline=0, fill=o.blue)
2850
+			
2851
+			o.draw.ellipse((self.ballx - self.ball_size, self.bally - self.ball_size, self.ballx + self.ball_size, self.bally + self.ball_size), fill = o.light_grey, outline =o.light_grey)
2852
+			o.draw.ellipse((self.ball2x - self.ball_size, self.ball2y - self.ball_size, self.ball2x + self.ball_size, self.ball2y + self.ball_size), fill = o.light_grey, outline =o.light_grey)
2853
+			#o.center_block(current_time, o.h3, [0,0,o.width,o.height], o.pink)
2854
+			o.update_display(0)
2855
+		
2856
+	def ReceiveMessage(self, message):
2857
+		o = self.FSM.owner 
2858
+		play_seq(o, message)
2859
+		
2860
+	def Exit(self):
2861
+		self.FSM.owner.pub.unregister("beat", self)        
2862
+
2863
+#==================================== 

+ 79
- 153
main.py View File

@@ -23,10 +23,11 @@ import ast
23 23
 import RPi.GPIO as GPIO
24 24
 from time import sleep
25 25
 import threading
26
+import os
26 27
 GPIO.setmode(GPIO.BCM)
27 28
 
28 29
 # set up GPIO output channel - internal led
29
-GPIO.setup(47, GPIO.OUT)
30
+GPIO.setup(29, GPIO.OUT)
30 31
 
31 32
 
32 33
 cols = [digitalio.DigitalInOut(x) for x in (board.D21, board.D20, board.D16, board.D12)]
@@ -41,8 +42,8 @@ keys = ((15, 14, 13, 12),
41 42
 keypad = adafruit_matrixkeypad.Matrix_Keypad(rows, cols, keys)
42 43
 
43 44
 pygame.init()
44
-mixer.init()
45
-mixer.set_num_channels(32)
45
+# mixer.init()
46
+# mixer.set_num_channels(32)
46 47
 done = False
47 48
 clock = pygame.time.Clock()
48 49
 TIMER = pygame.USEREVENT + 1
@@ -106,11 +107,12 @@ backlight.value = True
106 107
 class Prog:
107 108
 	def __init__(self):
108 109
 		self.FSM = FSM.ProgFSM(self)
109
-		self.font = ImageFont.truetype("/home/pi/examples/HLM.ttf", 64)
110
+		#self.start_mixer()
111
+		#self.font = ImageFont.truetype("/home/pi/examples/HLM.ttf", 64)
110 112
 		#self.h1 = ImageFont.truetype("/home/pi/examples/HLM.ttf", 26)
111
-		self.h1 = ImageFont.truetype("/home/pi/Pixellari.ttf", 30)
112
-		self.h2 = ImageFont.truetype("/home/pi/Pixellari.ttf", 20)
113
-		self.h3 = ImageFont.truetype("/home/pi/Pixellari.ttf", 54)
113
+		self.h1 = ImageFont.truetype("/home/pi/zpc_ct/fonts/Pixellari.ttf", 30)
114
+		self.h2 = ImageFont.truetype("/home/pi/zpc_ct/fonts/Pixellari.ttf", 20)
115
+		self.h3 = ImageFont.truetype("/home/pi/zpc_ct/fonts/Pixellari.ttf", 54)
114 116
 		
115 117
 		self.disp = st7789.ST7789(
116 118
 			spi,
@@ -136,8 +138,9 @@ class Prog:
136 138
 		self.draw = ImageDraw.Draw(self.image)
137 139
 		self.playhead = 0
138 140
 		self.playing = False
139
-		#self.bpm = 90
141
+		self.bpm = 90
140 142
 		self.bpm_inc = 1
143
+		self.half_bpm = 0.0
141 144
 		self.note_bank = 0
142 145
 		self.pat_bank = 0
143 146
 		self.volume = 10
@@ -154,22 +157,26 @@ class Prog:
154 157
 		self.songStart = self.curPattern
155 158
 		self.eSound = 0
156 159
 		self.ePattern = 0
160
+		self.patternFollow = False
157 161
 		self.patternClipboard = []
158 162
 		self.soundClipboard = []
163
+		self.last_load_sound_id = None
164
+		self.odub = False
165
+		self.undo_buf = []
159 166
 		self.black = "#000000"
160 167
 		self.bg_color = "#336699"
161
-		self.color_a = "#FFFFFF"
168
+		#self.color_a = "#FFFFFF"
162 169
 		self.color_b = "#929230"
163
-		self.color_c = "#FFFF00"
170
+		#self.color_c = "#FFFF00"
164 171
 		self.dark_grey = "#404040"
165 172
 		self.grey = "#808080"
166 173
 		self.light_grey = "#D3D3D3"
167 174
 		self.blue = "#336699"
168 175
 		self.dark_blue = "#2A2AD5"
169 176
 		self.pink = "#D52A80"
170
-		self.red = "#D52A2A"
177
+		#self.red = "#D52A2A"
171 178
 		self.olive = "#80D52A"
172
-		self.green = "#2AD52A"
179
+		#self.green = "#2AD52A"
173 180
 		self.notes_on = []
174 181
 		self.clear_notes_on()
175 182
 
@@ -179,8 +186,8 @@ class Prog:
179 186
 		#self.song_file_name = "default.sng"
180 187
 		self.mconf = ConfigObj("config.txt")
181 188
 		self.sconf = ConfigObj("/home/pi/zpc_ct/user/songs/" + self.mconf['default_song'])
182
-		self.theme = ConfigObj("/home/pi/zpc_ct/themes/" + self.mconf['theme'] + ".thm")
183
-		self.load_song_dir = '/home/pi/zpc_ct/sounds/'
189
+		self.theme = ConfigObj("/home/pi/zpc_ct/user/themes/" + self.mconf['theme'] + ".thm")
190
+		self.load_song_dir = '/home/pi/zpc_ct/user/sounds/'
184 191
 
185 192
 		self.light_grey = self.theme['light_grey']
186 193
 		self.apply_theme()
@@ -263,7 +270,7 @@ class Prog:
263 270
 			p1 = self.SoundSlot(None, _iter, self)
264 271
 			self.slots.append(p1)
265 272
 			_iter += 1
266
-			print('adding slot ', _iter)
273
+			#print('adding slot ', _iter)
267 274
 
268 275
 	def Execute(self):
269 276
 		self.keys = keypad.pressed_keys
@@ -326,8 +333,10 @@ class Prog:
326 333
 				self.keyState[17] = 0
327 334
 
328 335
 	def update_bpm(self):
329
-		bpm = (60000 / self.sconf['bpm']) / 4
330
-		pygame.time.set_timer(TIMER, int(bpm))
336
+		bpm = (60000 / self.bpm) / 4
337
+		self.half_bpm = bpm / 2
338
+		if self.playing:
339
+			pygame.time.set_timer(TIMER, int(bpm))
331 340
 
332 341
 	def start_playback(self):
333 342
 		self.playing = True
@@ -336,7 +345,7 @@ class Prog:
336 345
 		self.songCycle = cycle(self.song)
337 346
 		self.curPattern = next(self.songCycle)
338 347
 		self.songStart = self.curPattern
339
-		bpm = (60000 / self.sconf.as_int('bpm')) / 4
348
+		bpm = (60000 / self.bpm) / 4
340 349
 		pygame.time.set_timer(TIMER, int(bpm))
341 350
 		
342 351
 
@@ -359,59 +368,41 @@ class Prog:
359 368
 		self.draw.text((x, y), message, align='center', font=font, fill=color)
360 369
 		
361 370
 	def apply_theme(self):
371
+		self.grey = self.theme["grey"]
362 372
 		self.light_grey = self.theme["light_grey"]
373
+		self.dark_grey = self.theme["dark_grey"]
363 374
 		self.blue = self.theme["blue"]
364 375
 		self.pink = self.theme["pink"]
365 376
 		self.olive = self.theme["olive"]
366
-		self.black = self.theme["black"]
367
-		self.dark_blue = self.theme["dark_blue"]
368
-		self.green = self.theme["green"]
369
-		self.red = self.theme["red"]
377
+		#self.black = self.theme["black"]
378
+		#self.dark_blue = self.theme["dark_blue"]
379
+		#self.green = self.theme["green"]
380
+		#self.red = self.theme["red"]
370 381
 
371 382
 	def save_song(self):
372 383
 		base_dir = "/home/pi/zpc_ct/user/songs/"
373
-		#self.sconf = ConfigObj(base_dir + self.sconf['title'] + '.sng')
374
-		#self.sconf['title'] = "default"
375
-		#self.sconf['volume'] = self.volume
376
-		# sounds = []
377
-		# notes = []
378
-		# vols = []
379
-		# pitches = []
380
-
381
-		# outp = []
382
-		# for x in self.soundSlots:
383
-		# 	sounds.append(x.file)
384
-		# 	notes.append(x.notes)
385
-		# 	vols.append(x.volume)
386
-		# 	pitches.append(x.pitch)
387
-		# 	outp.append([x.id, x.file, x.volume, x.pitch, x.notes])
388
-		# self.sconf['sounds'] = sounds
389
-		# self.sconf['notes'] = notes
390
-		# self.sconf['song'] = self.song
391
-		# self.sconf['volumes'] = vols
392
-		# self.sconf['pitches'] = pitches
393
-		# self.sconf['Sound Slot'] = outp
394
-		# self.sconf.write()
395
-
396
-
397
-		self.sconf = ConfigObj(base_dir + self.sconf['title'] + '.sn2')
384
+		title = self.sconf['title']
385
+		fname = base_dir + self.sconf['title'] + '.sng'
386
+		if os.path.exists(fname):
387
+			os.utime(fname, None)
388
+			print(fname, ' exists')
389
+		else:
390
+			print('make a damn file ', fname)
391
+			open(fname, 'a').close()			
392
+
393
+		self.sconf = ConfigObj(fname)
398 394
 		self.sconf['volume'] = self.volume
399 395
 		self.sconf['song'] = self.song
400
-		self.sconf['bpm'] = self.sconf['bpm']
396
+		self.sconf['bpm'] = self.bpm
397
+		self.sconf['title'] = title
401 398
 		notes = []
402 399
 		for n in self.soundSlots:
403 400
 			notes.append([n.id, n.file, n.volume, n.pitch, n.notes])
404 401
 		self.sconf['sounds'] = notes
405
-
406
-		#tmp
407
-		#for s in self.soundSlots:
408
-		#	self.sconf['sounds'][s.id] = [s.id, s.file, s.volume, s.pitch, s.notes]
409
-
410 402
 		self.sconf.write()
411 403
 
412 404
 	def save_config(self):
413 405
 		base_dir = "/home/pi/zpc_ct/"
414
-		#self.mconf = ConfigObj(base_dir + 'config.txt')
415 406
 		print('before writing')
416 407
 		print(self.mconf['theme'])
417 408
 		self.mconf.write()
@@ -419,16 +410,18 @@ class Prog:
419 410
 	def load_config(self):
420 411
 		base_dir = "/home/pi/zpc_ct/"
421 412
 		self.sconf = ConfigObj(base_dir + 'config.txt')
422
-		self.theme = ConfigObj("/home/pi/zpc_ct/themes/" + self.mconf['theme'] + ".thm")
413
+		self.theme = ConfigObj("/home/pi/zpc_ct/user/themes/" + self.mconf['theme'] + ".thm")
423 414
 
424 415
 	def load_song(self):
416
+		#self.stop_playback()
417
+		self.quit_mixer()
418
+		self.start_mixer()
425 419
 		base_dir = "/home/pi/zpc_ct/user/songs/"
426
-		self.sconf = ConfigObj(base_dir + self.mconf['default_song'] + '.sn2')
427
-		print(base_dir + self.mconf['default_song'] + '.sn2')
428
-		#one = self.sconf['song']
429
-		#one = self.sconf['title']
430
-		#print('song ', one)
431
-		
420
+		self.sconf = ConfigObj(base_dir + self.mconf['default_song'] + '.sng')
421
+		print(base_dir + self.mconf['default_song'] + '.sng')
422
+		self.last_load_sound_id = None
423
+		print('song bpm is ', self.sconf['bpm'])
424
+		self.bpm = self.sconf.as_int('bpm')
432 425
 		song = []
433 426
 		for i in self.sconf['song']:
434 427
 			song.append(int(i))
@@ -453,102 +446,22 @@ class Prog:
453 446
 			p1 = self.SoundSlot(filename, obj_id, self)
454 447
 			p1.volume = volume
455 448
 			p1.pitch = pitch
456
-			#p1.notes = ast.literal_eval(notes)
449
+			if pitch != 0:
450
+				p1.set_pitch()
457 451
 			self.soundSlots.append(p1)
458
-			# if (len(self.sconf.as_list('volumes')) - 1) > obj_id:
459
-			# 	p1.volume = int(self.sconf.as_list('volumes')[obj_id])
460
-			# else:
461
-			# 	p1.volume = 12
462
-			# if (len(self.sconf.as_list('pitches')) - 1) > obj_id:
463
-			# 	p1.pitch = int(self.sconf.as_list('pitches')[obj_id])
464
-			# 	p1.set_pitch()
465
-			# else:
466
-			# 	p1.pitch = 0
467
-			# print('adding ', s)
468
-			# obj_id += 1
469 452
 			p1.notes = notes
470
-			# _iter2 = 0
471
-			# while _iter2 < 64:
472
-
473
-			# 	_iter2 += 1
474
-		#print(self.soundSlots)
475 453
 
476 454
 		_iter = 0
477
-
478
-		#lst = ast.literal_eval(self.sconf['notes'][0])
479
-		#print('length ', len(lst))
480
-
481
-		# for n in self.soundSlots:
482
-		# 	m = []
483
-		# 	#if (len(notes) - 1) > _iter:
484
-		# 	#lst = ast.literal_eval(notes)[_iter]
485
-		# 	lst = notes
486
-		# 	new_notes = []
487
-		# 	for i in lst:
488
-		# 		new_notes.append(i)
489
-		# 	n.notes = new_notes
490
-		# 	if _iter == 0:
491
-		# 		print(new_notes)
492
-		# 	_iter += 1
493
-
455
+		
494 456
 		self.song = song
495 457
 
496 458
 		self.songCycle = cycle(self.song)
497 459
 		self.curPattern = next(self.songCycle)
498 460
 		self.songStart = self.curPattern
499
-
500
-	
501
-# def load_song(self):
502
-# 		base_dir = "/home/pi/zpc_ct/user/songs/"
503
-# 		self.sconf = ConfigObj(base_dir + self.mconf['default_song'] + '.sng')
504
-# 		print(base_dir + self.mconf['default_song'] + '.sng')
505
-# 		#one = self.sconf['song']
506
-# 		one = self.sconf['title']
507
-# 		print('song ', one)
508
-		
509
-# 		song = []
510
-# 		for i in self.sconf['song']:
511
-# 			song.append(int(i))
512
-
513
-# 		obj_id = 0
514
-# 		self.soundSlots = []
515
-# 		for s in self.sconf['sounds']:
516
-# 			p1 = self.SoundSlot(s, obj_id, self)
517
-# 			self.soundSlots.append(p1)
518
-# 			if (len(self.sconf.as_list('volumes')) - 1) > obj_id:
519
-# 				p1.volume = int(self.sconf.as_list('volumes')[obj_id])
520
-# 			else:
521
-# 				p1.volume = 12
522
-# 			if (len(self.sconf.as_list('pitches')) - 1) > obj_id:
523
-# 				p1.pitch = int(self.sconf.as_list('pitches')[obj_id])
524
-# 				p1.set_pitch()
525
-# 			else:
526
-# 				p1.pitch = 0
527
-# 			print('adding ', s)
528
-# 			obj_id += 1
529
-# 		print(self.soundSlots)
530
-
531
-# 		_iter = 0
532
-
533
-# 		lst = ast.literal_eval(self.sconf['notes'][0])
534
-# 		print('length ', len(lst))
535
-
536
-# 		for n in self.soundSlots:
537
-# 			m = []
538
-# 			if (len(self.sconf.as_list('notes')) - 1) > _iter:
539
-# 				lst = ast.literal_eval(self.sconf.as_list('notes')[_iter])
540
-# 				n.notes = lst
541
-# 			_iter += 1
542
-
543
-# 		self.song = song
544
-
545
-# 		self.songCycle = cycle(self.song)
546
-# 		self.curPattern = next(self.songCycle)
547
-# 		self.songStart = self.curPattern
548
-
549
-
550
-
551
-
461
+		self.update_bpm()
462
+		# if self.playing:
463
+		# 	self.stop_playback()
464
+		# 	self.start_playback()
552 465
 
553 466
 	def update_display(self, x):
554 467
 		# if self.display_thread.is_alive():
@@ -559,7 +472,10 @@ class Prog:
559 472
 		
560 473
 		# 	self.display_thread.start()
561 474
 		# 	time.sleep(.001)
562
-		self.disp.image(self.image, self.rotation)
475
+		try:
476
+			self.disp.image(self.image, self.rotation)
477
+		except:
478
+			print('display failed')
563 479
 	def ud(self, x):
564 480
 		self.disp.image(self.image, self.rotation)
565 481
 
@@ -570,6 +486,16 @@ class Prog:
570 486
 			self.notes_on.append(0)
571 487
 			_iter += 1
572 488
 
489
+	def start_mixer(self):
490
+		print('starting mixer')
491
+		mixer.init()
492
+		mixer.set_num_channels(32)
493
+
494
+	def quit_mixer(self):
495
+		if mixer.get_init() != None:
496
+			print('quitting mixer')
497
+			mixer.quit()
498
+
573 499
 p = Prog()
574 500
 
575 501
 #while True:
@@ -588,11 +514,11 @@ while not done:
588 514
 
589 515
 		#blink internal led
590 516
 		if p.playhead  % 8 == 0:
591
-			GPIO.setup(47, GPIO.OUT)
592
-			GPIO.output(47, GPIO.LOW)
517
+			GPIO.setup(29, GPIO.OUT)
518
+			GPIO.output(29, GPIO.LOW)
593 519
 		else:
594
-			GPIO.setup(47, GPIO.OUT)
595
-			GPIO.output(47, GPIO.HIGH)
520
+			GPIO.setup(29, GPIO.OUT)
521
+			GPIO.output(29, GPIO.HIGH)
596 522
 
597 523
 		p.pub.dispatch('beat', [p.curPattern, p.playhead]) 
598 524
 

+ 17
- 0
new_wifi.txt View File

@@ -0,0 +1,17 @@
1
+this
2
+that
3
+the other
4
+
5
+network={
6
+    psk="this_ssid"
7
+    psk="this_pass"
8
+
9
+network={
10
+    psk="this_ssid"
11
+    psk="this_pass"
12
+}
13
+
14
+    psk="this_ssid"
15
+    psk="this_pass"
16
+}
17
+

+ 5
- 0
runner.sh View File

@@ -0,0 +1,5 @@
1
+#until "python3 /home/pi/zpc_ct/main.py"; do
2
+until python3 ./main.py; do
3
+    echo "App 'zpc_ct' crashed with exit code $?.  Respawning.." >&2
4
+    sleep 2
5
+done

+ 9
- 0
scripts/fade_out.sh View File

@@ -0,0 +1,9 @@
1
+#recursivly (from current directory) apply fade out to all wavs
2
+
3
+find . -name "*.wav"|while read w
4
+do 
5
+    echo "$w"
6
+	echo $w
7
+	sox "$w" "${w%.wav}_.wav" fade 0 $(soxi -D "$w") 0.00045
8
+	mv "${w%.wav}_.wav" "$w"
9
+done

+ 25
- 0
set_wifi.sh View File

@@ -0,0 +1,25 @@
1
+FILE=wifi.txt
2
+declare -i _iter=0
3
+declare -i _first=0
4
+if [ -f "$FILE" ]; then
5
+    echo "" >> /etc/wpa_supplicant/wpa_supplicant.conf
6
+    echo "network={" >> /etc/wpa_supplicant/wpa_supplicant.conf
7
+    echo "$FILE exists."
8
+
9
+
10
+	while read line; do
11
+		if [[$_iter==0]];
12
+		then
13
+			#echo "this"
14
+	    		echo "    ssid=\"$line\"" >> /etc/wpa_supplicant/wpa_supplicant.conf
15
+		else
16
+			echo "that"
17
+			echo "    psk=\"$line\"" >> /etc/wpa_supplicant/wpa_supplicant.conf
18
+		fi
19
+		#$_iter += 1
20
+		let "_iter+=1" 
21
+	done < wifi.txt
22
+
23
+    echo "}" >> /etc/wpa_supplicant/wpa_supplicant.conf
24
+    rm wifi.txt
25
+fi

+ 0
- 14
themes/bw.thm View File

@@ -1,14 +0,0 @@
1
-#main text
2
-light_grey = "#D3D3D3"
3
-#main background
4
-blue = "#000000"
5
-#highlight1
6
-pink = "#D52A80"
7
-#highlight2
8
-olive = "#80D52A"
9
-black = "#000000"
10
-dark_grey = "#404040"
11
-grey = "#808080"
12
-dark_blue = "#2A2AD5"
13
-red = "#D52A2A"
14
-green = "#2AD52A"

+ 0
- 14
themes/dark2.thm View File

@@ -1,14 +0,0 @@
1
-#main text
2
-light_grey = "#D3D3D3"
3
-#main background
4
-blue = "#000000"
5
-#highlight1
6
-pink = "#D52A80"
7
-#highlight2
8
-olive = "#80D52A"
9
-black = "#000000"
10
-dark_grey = "#404040"
11
-grey = "#808080"
12
-dark_blue = "#2A2AD5"
13
-red = "#D52A2A"
14
-green = "#2AD52A"

+ 0
- 7
user/songs/Casio_RZ-1.sng
File diff suppressed because it is too large
View File


+ 0
- 9
user/songs/EMU_E-Drum.sng
File diff suppressed because it is too large
View File


+ 0
- 4
user/songs/EMU_SP-12.sn2
File diff suppressed because it is too large
View File


+ 2
- 8
user/songs/EMU_SP-12.sng
File diff suppressed because it is too large
View File


+ 0
- 8
user/songs/EMU_SP-12a.sng
File diff suppressed because it is too large
View File


+ 0
- 4
user/songs/Linn_Linndrum.sn2
File diff suppressed because it is too large
View File


+ 2
- 9
user/songs/Linn_Linndrum.sng
File diff suppressed because it is too large
View File


+ 0
- 8
user/songs/Roland_TR-505.sng
File diff suppressed because it is too large
View File


+ 0
- 4
user/songs/Roland_TR-808.sn2
File diff suppressed because it is too large
View File


+ 3
- 7
user/songs/Roland_TR-808.sng
File diff suppressed because it is too large
View File


+ 0
- 8
user/songs/Roland_TR-808bak.sng
File diff suppressed because it is too large
View File


+ 4
- 6
user/songs/_blank.sng
File diff suppressed because it is too large
View File


+ 0
- 4
user/songs/default.sn2
File diff suppressed because it is too large
View File


+ 2
- 6
user/songs/default.sng
File diff suppressed because it is too large
View File


+ 0
- 7
user/songs/defaultback.sng
File diff suppressed because it is too large
View File


+ 0
- 7
user/songs/r100.sng
File diff suppressed because it is too large
View File


+ 0
- 7
user/songs/tr909.sng
File diff suppressed because it is too large
View File


BIN
user/sounds/drum_machines/Roland_CR-1000/.goutputstream-FH11C1 View File


themes/dark.thm → user/themes/dark.thm View File

@@ -1,14 +1,14 @@
1 1
 #main text
2 2
 light_grey = "#D3D3D3"
3
+
3 4
 #main background
4 5
 blue = "#000000"
6
+
5 7
 #highlight1
6 8
 pink = "#D52A80"
9
+
7 10
 #highlight2
8 11
 olive = "#80D52A"
9
-black = "#000000"
12
+
10 13
 dark_grey = "#404040"
11
-grey = "#808080"
12
-dark_blue = "#2A2AD5"
13
-red = "#D52A2A"
14
-green = "#2AD52A"
14
+grey = "#808080"

themes/default.thm → user/themes/default.thm View File

@@ -1,14 +1,14 @@
1 1
 #main text
2 2
 light_grey = "#D3D3D3"
3
+
3 4
 #main background
4 5
 blue = "#336699"
6
+
5 7
 #highlight1
6 8
 pink = "#D52A80"
9
+
7 10
 #highlight2
8 11
 olive = "#80D52A"
9
-black = "#000000"
12
+
10 13
 dark_grey = "#404040"
11 14
 grey = "#808080"
12
-dark_blue = "#2A2AD5"
13
-red = "#D52A2A"
14
-green = "#2AD52A"

+ 14
- 0
user/themes/green.thm View File

@@ -0,0 +1,14 @@
1
+#main text
2
+light_grey = "#404040" 
3
+
4
+#main background
5
+blue = "#80D52A"
6
+
7
+#highlight1
8
+pink = "#D52A80"
9
+
10
+#highlight2
11
+olive = "#336699"
12
+
13
+dark_grey = "#D3D3D3"
14
+grey = "#808080"

+ 14
- 0
user/themes/green2.thm View File

@@ -0,0 +1,14 @@
1
+#main text
2
+light_grey = "#80D52A" 
3
+
4
+#main background
5
+blue = "#404040"
6
+
7
+#highlight1
8
+pink = "#D52A80"
9
+
10
+#highlight2
11
+olive = "#336699"
12
+
13
+dark_grey = "#242424"
14
+grey = "#565656"

themes/pumpkin.thm → user/themes/pumpkin.thm View File


+ 14
- 0
user/themes/red.thm View File

@@ -0,0 +1,14 @@
1
+#main text
2
+light_grey = "#D3D3D3"
3
+
4
+#main background
5
+blue = "#aa0000"
6
+
7
+#highlight1
8
+pink = "#610000"
9
+
10
+#highlight2
11
+olive = "#ffaa00"
12
+
13
+dark_grey = "#404040"
14
+grey = "#808080"

+ 14
- 0
user/themes/red2.thm View File

@@ -0,0 +1,14 @@
1
+#main text
2
+light_grey = "#aa0000"
3
+
4
+#main background
5
+blue = "#000000"
6
+
7
+#highlight1
8
+pink = "#610000"
9
+
10
+#highlight2
11
+olive = "#ffaa00"
12
+
13
+dark_grey = "#212121"
14
+grey = "#808080"

Loading…
Cancel
Save