fleshwounded
12/1/2018 - 4:38 AM

Control things win numpad

Control things/see system stats with a Launchpad (uses launchpad.py)

class Txfnums():
	def __init__(self):
		self.nums = [
			[
				0, 1, 0,
				1, 0, 1,
				1, 0, 1,
				0, 1, 0
			],

			[
				1, 1, 0,
				0, 1, 0,
				0, 1, 0,
				1, 1, 1
			],

			[
				1, 1, 0,
				0, 0, 1,
				0, 1, 0,
				1, 1, 1
			],

			[
				1, 1, 1,
				0, 1, 1,
				0, 0, 1,
				1, 1, 1
			],

			[
				1, 0, 0,
				1, 0, 1,
				1, 1, 1,
				0, 0, 1
			],

			[
				1, 1, 1,
				1, 1, 0, 
				0, 0, 1,
				1, 1, 0
			],

			[
				1, 0, 0,
				1, 1, 1,
				1, 0, 1,
				1, 1, 1
			],

			[
				1, 1, 1,
				0, 0, 1,
				0, 1, 0,
				1, 0, 0
			],

			[
				1, 1, 1,
				0, 1, 0,
				1, 0, 1,
				1, 1, 1
			],

			[
				1, 1, 1,
				1, 0, 1,
				1, 1, 1,
				0, 0, 1
			]
		]

	def __getitem__(self, index):
return self.nums[index]
#!/usr/bin/python2

from __future__ import division
from __future__ import print_function

'''
I apologize in advance for the terrible coding job. It works, at least.
...to an extent, mostly.
'''

'''
REQUIREMENTS
============
* recent version of python 2.x
* python-mpd2
* psutil
* launchpad.py (https://github.com/FMMT666/launchpad.py)
* pygame
'''

from launchpad import Launchpad
from pygame import time
import time as _time
import random
import math
import threading

# settings
import _settings as settings
from _3x4_nums import Txfnums

# custom stuff
import psutil

from mpd import MPDClient
mpd = MPDClient()
mpd.connect(settings.mpd["address"], settings.mpd["port"])
mpd.password(settings.mpd["password"])

print("MPD: {}".format(mpd.mpd_version))

lp = Launchpad()

lp.Open()
lp.Reset()

def clamp(n, smallest, largest):
	return max(smallest, min(n, largest))

class StoppableThread(threading.Thread):
	"""Thread class with a stop() method. The thread itself has to check
	regularly for the stopped() condition."""

	def __init__(self):
		super(StoppableThread, self).__init__()
		self._stop = threading.Event()

	def stop(self):
		self._stop.set()

	def stopped(self):
		return self._stop.isSet()
		

class PageError(Exception):
	def __init__(self, value):
		self.value = value
	def __str__(self):
		return repr(self.value)

class LaunchpadButtonDefs():
	def __init__(self):
		self.close = 120
		self.page_indicators = [8, 24, 40, 56, 72, 88, 104]
		self.session = 204
		self.page_prev = 202
		self.page_next = 203
		self.row = [
			[0, 1, 2, 3, 4, 5, 6, 7],
			[16, 17, 18, 19, 20, 21, 22, 23],
			[32, 33, 34, 35, 36, 37, 38, 39],
			[48, 49, 50, 51, 52, 53, 54, 55],
			[64, 65, 66, 67, 68, 69, 70, 71],
			[80, 81, 82, 83, 84, 85, 86, 87],
			[96, 97, 98, 99, 100, 101, 102, 103],
			[112, 113, 114, 115, 116, 117, 118, 119]
		]
		self.user_1 = 205
		self.user_2 = 206
		self.user_3 = 207
		self.ctrl_up = 200
		self.ctrl_down = 201

	def getPressed(self, val):
		if self.close == val:
			return "close"

		try:
			page = self.page_indicators.index(val)
		except ValueError:
			pass
		else:
			return "page.{}".format(page)

		if self.session == val:
			return "session"

		if self.page_prev == val:
			return "page_prev"

		if self.page_next == val:
			return "page_next"

		if self.user_1 == val:
			return "user_1"

		if self.user_2 == val:
			return "user_2"

		if self.user_3 == val:
			return "user_3"

		if self.ctrl_up == val:
			return "ctrl_up"

		if self.ctrl_down == val:
			return "ctrl_down"

		row = int((val - (val % 16))/16)
		col = int(val % 16)

		try:
			if val == self.row[row][col]:
				return "grid.{}.{}".format(row, col)
		except IndexError:
			pass

		return "undf.{}".format(val)

def reset_grid():
	lp.LedCtrlRaw(button_defs.user_1, 0, 0)
	lp.LedCtrlRaw(button_defs.user_2, 0, 0)
	lp.LedCtrlRaw(button_defs.user_3, 0, 0)
	lp.LedCtrlRaw(button_defs.ctrl_up, 0, 0)
	lp.LedCtrlRaw(button_defs.ctrl_down, 0, 0)
	lp.LedCtrlRaw(button_defs.page_next, 3, 2)
	lp.LedCtrlRaw(button_defs.page_prev, 3, 2)

	for x in range(0, 8):
		for y in range(0, 8):
			lp.LedCtrlRaw(button_defs.row[x][y], 0, 0)

def get_color_gradient(val, _min, _max):
	'''
	red (highest): [3, 0]
	yellow (mid): [3, 3]
	green(lowest): [0, 3]
	[0, 3], [1, 3], [2, 3], [3, 3], [3, 2], [3, 1], [3, 0]
	'''

	actual_max = _max - _min
	actual_val = val - _min

	if actual_val == actual_max:
		return [3, 0]

	x = clamp(int((actual_val/actual_max)*7), 0, 7)
	return [clamp(x, 0, 3), clamp(math.fabs(x-6), 0, 3)]

class LaunchpadPage1():
	'''
	Some paint crap
	'''
	def __init__(self, parent):
		self.parent = parent
		self.color = [random.randint(1, 3), random.randint(0, 3)]

		self.session_status = True

		self.button_states = []
		for x in range(0, 8):
			col = [0, 0, 0, 0, 0, 0, 0, 0]
			self.button_states.append(col)

	def on_page_activated(self):
		self.refresh()

	def on_page_deactivated(self):
		return


	def on_button(self, button):
		if button[0:4] == "grid":
			row = int(button[5])
			col = int(button[7])
			state = self.button_states[row][col]

			if not state:
				lp.LedCtrlRaw(button_defs.row[row][col], self.color[0], self.color[1])
				state = 1
			else:
				lp.LedCtrlRaw(button_defs.row[row][col], 0, 0)
				state = 0

			self.button_states[row][col] = state

			if row == 7 and col == 7:
				raise ValueError

		elif button in ["user_1", "user_2"]:
			new_col = self.color[int(button[5])-1] + 1

			if new_col > 3:
				new_col = 0

			self.color[int(button[5])-1] = new_col

			self.refresh()

	def refresh(self):
		lp.LedCtrlRaw(button_defs.user_1, self.color[0], 0)
		lp.LedCtrlRaw(button_defs.user_2, 0, self.color[1])
		lp.LedCtrlRaw(button_defs.user_3, self.color[0], self.color[1])

		for x in range(0, 8):
			for y in range(0, 8):
				state = self.button_states[x][y]

				if state:
					lp.LedCtrlRaw(button_defs.row[x][y], self.color[0], self.color[1])
				else:
					lp.LedCtrlRaw(button_defs.row[x][y], 0, 0)


class LaunchpadPage2():
	'''
	CPU Usage
	'''
	def __init__(self, parent):
		self.parent = parent
		self.session_status = True

		self.thread = threading.Thread(target=self.loop)
		self.thread.daemon = True
		self.thread.start()

	def draw(self):
		if self.parent.active_page != 1:
			return

		try:
			lp.LedCtrlRaw(button_defs.session, 3, 3)
			cpu = psutil.cpu_percent(interval=1, percpu=True)
		except:
			self.session_status = False
			return

		self.session_status = True
		lp.LedCtrlRaw(button_defs.session, 0, 3)
		reset_grid()

		print(cpu)

		for x in range(0, clamp(len(cpu), 0, 8)):
			print(x)
			cols = int(math.floor((cpu[x]/100)*8))

			if cols > 3:
				green = clamp(math.fabs(cols-6), 0, 3)
				red = clamp(cols-3, 0, 3)
			else:
				green = clamp(cols, 1, 3)
				red = 0
			
			for y in range(0, cols):
				lp.LedCtrlRaw(button_defs.row[x][y], red, green)

	def loop(self):
		while True:
			_time.sleep(1)
			if self.parent.active_page == 1:
				print("drawing cpu...")
				self.draw()

	def on_page_activated(self):
		return

	def on_page_deactivated(self):
		return

class LaunchpadPage3():
	'''
	MPD elapsed
	'''
	def __init__(self, parent):
		self.parent = parent
		self.session_status = True

		self.button_states = []
		for x in range(0, 8):
			col = [0, 0, 0, 0, 0, 0, 0, 0]
			self.button_states.append(col)

		self.thread = threading.Thread(target=self.loop)
		self.thread.daemon = True
		self.thread.start()

		status = mpd.status()
		self.old_id = status["songid"]
		self.vol = int(status["volume"])

	def reset_state(self):
		for x in range(0, 8):
			for y in range(0, 8):
				self.button_states[x][y] = 0

	def draw(self):
		status = mpd.status()

		time = status["time"]
		cur_id = status["songid"]

		elapsed = int(time.split(":")[0])
		duration = int(time.split(":")[1])

		if self.old_id != cur_id:
			self.old_id = cur_id
			self.reset_state()

		'''
		row = int((val - (val % 16))/16)
		col = int(val % 16)
		'''

		squares = int(math.ceil((elapsed/duration)*64))

		for x in range(0, squares):
			self.button_states[int(math.floor(x / 8))][x % 8] = 1

		if self.parent.active_page == 2:
			for x in range(0, 8):
				for y in range(0, 8):
					lp.LedCtrlRaw(button_defs.row[x][y], 0, 3*self.button_states[x][y])

	def draw_vol(self):
		col = get_color_gradient(self.vol, 0, 100)
		lp.LedCtrlRaw(button_defs.user_3, col[0], col[1])

	def loop(self):
		while True:
			_time.sleep(1)
			if self.parent.active_page == 2:
				print("drawing mpd...")
				self.draw()

	def on_button(self, button):
		if button[0:4] == "grid":
			row = int(button[5])
			col = int(button[7])

			status = mpd.status()
			time = status["time"]

			duration = int(time.split(":")[1])
			squares = (row*8) + col

			for x in range(0, squares):
				self.button_states[int(math.floor(x / 8))][x % 8] = 1
			for x in reversed(range(squares, 64)):
				self.button_states[int(math.floor(x / 8))][x % 8] = 0

			mpd.seekcur((squares/64)*duration)
			self.draw()

		elif button in ["ctrl_up", "ctrl_down"]:
			if button == "ctrl_up":
				offset = 5
			if button == "ctrl_down":
				offset = -5

			self.vol = clamp(self.vol+offset, 0, 100)
			mpd.setvol(self.vol)
			self.draw_vol()

		elif button == "user_1":
			if int(mpd.status()["time"]) > 5:
				mpd.seekcur(0)
			else:
				mpd.previous()

		elif button == "user_2":
			mpd.next()

		elif button == "user_3":
			mpd.pause()

	def on_page_activated(self):
		lp.LedCtrlRaw(button_defs.ctrl_up, 0, 1)
		lp.LedCtrlRaw(button_defs.ctrl_down, 0, 1)
		lp.LedCtrlRaw(button_defs.user_1, 1, 1)
		lp.LedCtrlRaw(button_defs.user_2, 1, 1)

		for x in range(0, 8):
			for y in range(0, 8):
				lp.LedCtrlRaw(button_defs.row[x][y], 0, 3*self.button_states[x][y])

		self.draw_vol()


	def on_page_deactivated(self):
		return

class LaunchpadPage4():
	'''
	debug
	'''
	def __init__(self, parent):
		self.parent = parent
		self.session_status = True

	def draw(self):
		for x in range(0, 8):
			for y in range(0, 8):
				color = get_color_gradient((x*8)+y, 0, 63)

				lp.LedCtrlRaw(button_defs.row[x][y], color[0], color[1])

	def on_page_activated(self):
		self.draw()

	def on_page_deactivated(self):
		return

class LaunchpadPage5():
	'''
	Clock
	'''
	def __init__(self, parent):
		self.parent = parent
		self.session_status = True

		self.thread = threading.Thread(target=self.loop)
		self.thread.daemon = True
		self.thread.start()

		self.button_states = []
		for x in range(0, 8):
			col = [0, 0, 0, 0, 0, 0, 0, 0]
			self.button_states.append(col)

		self.nums = Txfnums()

		self.old_min = int(_time.strftime("%M", _time.localtime()))

	def update_states(self):
		self.time = _time.strftime("%H.%M", _time.localtime()).split(".")

		hr_1 = str(self.time[0])[0]
		hr_2 = str(self.time[0])[1]
		mn_1 = str(self.time[1])[0]
		mn_2 = str(self.time[1])[1]

		print("{}{}:{}{}".format(hr_1, hr_2, mn_1, mn_2))

		for y in range(0, 3):
			for x in range(0, 4):
				self.button_states[x][y] = self.nums[int(hr_1)][(x*3)+y]
				self.button_states[x][y+4] = self.nums[int(hr_2)][(x*3)+y]
				self.button_states[x+4][y] = self.nums[int(mn_1)][(x*3)+y]
				self.button_states[x+4][y+4] = self.nums[int(mn_2)][(x*3)+y]

	def draw(self):
		for y in range(0, 8):
			for x in range(0, 4):
				lp.LedCtrlRaw(button_defs.row[x][y], self.button_states[x][y]*3, 0)

		for y in range(0, 8):
			for x in range(4, 8):
				lp.LedCtrlRaw(button_defs.row[x][y], self.button_states[x][y]*3, self.button_states[x][y]*3)

	def on_page_activated(self):
		self.update_states()
		self.draw()

	def on_page_deactivated(self):
		return

	def loop(self):
		while True:
			_time.sleep(1)

			new_min = int(_time.strftime("%M", _time.localtime()))

			if self.old_min != new_min:
				self.update_states()
				self.old_min = new_min
				if self.parent.active_page == 4:
					print("drawing clock...")
					self.draw()


class LaunchpadPages():
	def __init__(self):
		lp.LedCtrlRaw(button_defs.session, 3, 3)

		self.pages = [
			LaunchpadPage1(self),
			LaunchpadPage2(self),
			LaunchpadPage3(self),
			LaunchpadPage4(self),
			LaunchpadPage5(self)
		]
		self.switch_page("init")

	def switch_page(self, button):
		lp.LedCtrlRaw(button_defs.session, 3, 3)
		print(button)

		try:
			old_page = self.active_page
		except:
			old_page = 0

		if button == "init":
			new_page = 0
			self.active_page = 0
		elif button == "page_next":
			new_page = self.active_page + 1
		elif button == "page_prev":
			new_page = self.active_page - 1
		else:
			if button[0:5] == "page.":
				new_page = int(button[5])
			else:
				return

		if old_page != new_page:
			reset_grid()

			try:
				self.active_page = clamp(new_page, 0, len(self.pages)-1)
				self.pages[old_page].on_page_deactivated()
				self.pages[self.active_page].on_page_activated()
			except:
				raise
		elif button == "init":
			try:
				self.pages[self.active_page].on_page_activated()
			except:
				raise

		for x in range(0, len(self.pages)):
			strength = 1
			
			if x == self.active_page:
				strength = 3

			lp.LedCtrlRaw(button_defs.page_indicators[x], 0, strength)

		if self.pages[self.active_page].session_status:
			lp.LedCtrlRaw(button_defs.session, 0, 3)
		else:
			lp.LedCtrlRaw(button_defs.session, 3, 0)


	def on_button(self, button):
		if button[0:4] == "page":
			self.switch_page(button)
			return

		#self.pages[self.active_page].on_button(button)
		
		try:
			self.pages[self.active_page].on_button(button)
		except:
			lp.LedCtrlRaw(button_defs.session, 3, 0)
			#pass
		else:
			lp.LedCtrlRaw(button_defs.session, 0, 3)


button_defs = LaunchpadButtonDefs()
pages = LaunchpadPages()

lp.LedCtrlRaw(button_defs.close, 3, 0)
lp.LedCtrlRaw(button_defs.page_next, 3, 2)
lp.LedCtrlRaw(button_defs.page_prev, 3, 2)

def shutdown():
	lp.Reset()
	lp.Close()

	mpd.close()
	mpd.disconnect()

while 1:
	time.wait(10)

	raw = lp.ButtonStateRaw()
	
	if raw != []:
		print(raw)

		if raw[1]:
			button = button_defs.getPressed(raw[0])
			print(button);
			
			if raw[0] == button_defs.close:
				shutdown()
			else:
				pages.on_button(button)

shutdown()
mpd = {
	"address": "localhost",
	"port": 6600,
	"password": None
}