-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgui_breathing.py
212 lines (172 loc) · 6.46 KB
/
gui_breathing.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# -*- coding: utf-8 -*-
"""
Created on Fri Oct 02 22:27:03 2015
@author: William Herrera
IMPORTANT: run as administrator
Color breathing gui program for G20aj series PC
"""
import os
import ctypes
import threading
import Tkinter as tki
import ttk
from tkColorChooser import askcolor
import tkFileDialog as tkfd
import tkMessageBox as mbox
import light_acpi as la
import hyperventilate as hv
DLLNAME = 'ACPIWMI.dll'
def correct_dll_path(pathdir):
"""
check that we have the right path to the dll
"""
return os.path.isfile(os.path.join(pathdir, DLLNAME))
def terminate_thread(thread):
"""
Terminates a python thread from another thread.
:param thread: a threading.Thread instance
"""
if not thread.isAlive():
return
exc = ctypes.py_object(SystemExit)
res = ctypes.pythonapi.PyThreadState_SetAsyncExc(
ctypes.c_long(thread.ident), exc)
if res == 0:
raise ValueError("nonexistent thread id")
elif res > 1:
# """if it returns a number greater than one, you're in trouble,
# and you should call it again with exc=NULL to revert the effect"""
ctypes.pythonapi.PyThreadState_SetAsyncExc(thread.ident, None)
raise SystemError("PyThreadState_SetAsyncExc failed")
class BreathingApp(tki.Frame): #pylint: disable-msg=R0902
"""
app for the gui
"""
def __init__(self, root):
self.root = root
tki.Frame.__init__(self, root)
tki.Label(root,
text="ASUS ROG Desktop Breathing Lighting Control",
font="Verdana 15 bold").pack()
ttk.Separator(root, orient=tki.HORIZONTAL).pack(fill=tki.BOTH, expand=1)
# choose colors via radio button
self.leftcolor = 0xff0000
self.rightcolor = 0x0000ff
self.basecolor = 0x00ff00
tki.Label(root,
text="Choose Colors",
font="Verdana 12 bold").pack()
tki.Button(text='Select Left Color', command=self.get_left_color).pack()
tki.Button(text='Select Right Color', command=self.get_right_color).pack()
tki.Button(text='Select Base Color', command=self.get_base_color).pack()
ttk.Separator(root, orient=tki.HORIZONTAL).pack(fill=tki.BOTH, expand=1)
# choose directory to the ACPIWMI.dll
self.path_to_dll = la.DPATH
tki.Label(root,
text="Default Path to ACPIWMI.dll is "+self.path_to_dll,
font="Verdana 10 bold").pack()
self.path_to_dll = la.DPATH
tki.Button(root, text='Change Path to ACPIWMI.dll', command=self.pick_dll_path).pack()
ttk.Separator(root, orient=tki.HORIZONTAL).pack(fill=tki.BOTH, expand=1)
# choose the breathing rate update interval
self.resp_rate = 15
tki.Label(root,
text="Breathing Rate (bpm)",
font="Verdana 12 bold").pack()
self.slider = tki.Scale(root, from_=6, to=24, tickinterval=1,
sliderlength=5, orient=tki.HORIZONTAL)
self.slider.set(15)
self.slider.pack(fill=tki.BOTH, expand=1)
ttk.Separator(root, orient=tki.HORIZONTAL).pack(fill=tki.BOTH, expand=1)
# start app button
tki.Button(root, text="Start", fg="green", font="Verdana 14",
command=self.breathe).pack()
# quit app button
tki.Button(root, text="QUIT", fg="red", font="Verdana 14",
command=self.quit_app).pack(side=tki.BOTTOM)
self.lighting_thread = None
def pick_dll_path(self):
"""
choose path to dll
"""
path_chosen = tkfd.askdirectory(parent=self.root,
initialdir=self.path_to_dll,
title="Path to ACPIWMI.dll")
if correct_dll_path(path_chosen):
self.path_to_dll = path_chosen
else:
mbox.showwarning(path_chosen,
"ACPIWMI.dll not found in this path")
return self.path_to_dll
def optional_choose_dll_path(self):
"""
choose path to dll only if needed, error checked
"""
if not correct_dll_path(self.path_to_dll):
self.path_to_dll = tkfd.askdirectory(parent=self.root,
initialdir=self.path_to_dll,
title="Path to ACPIWMI.dll")
if not correct_dll_path(self.path_to_dll):
mbox.showwarning("Looking for Path to dll",
"ACPIWMI.dll not found in that path")
return self.path_to_dll
def get_left_color(self):
"""
get a color
"""
lst = list(askcolor()[0])
self.leftcolor = hv.make_rgb(lst[0], lst[1], lst[2])
def get_right_color(self):
"""
get a color
"""
lst = list(askcolor()[0])
self.rightcolor = hv.make_rgb(lst[0], lst[1], lst[2])
def get_base_color(self):
"""
get a color
"""
lst = list(askcolor()[0])
self.basecolor = hv.make_rgb(lst[0], lst[1], lst[2])
def get_resp_rate(self):
"""
get breathing rate
"""
self.resp_rate = int(self.slider.get())
return self.resp_rate
def breathe(self):
"""
begin sampling display thread
"""
if not self.lighting_thread == None:
terminate_thread(self.lighting_thread)
# get and set the dll path directory
la.DPATH = self.optional_choose_dll_path()
# get breathing rate sleep/update time interval for frames
tinterval = 2.0 / self.get_resp_rate()
fnum = 30
# the ACPI call takes time, so shrink fnum for faster rates
if self.resp_rate > 8:
fnum -= int(self.resp_rate / 2)
if fnum < 5:
fnum = 5
# get colors
colors = [self.leftcolor, self.rightcolor, self.basecolor]
def callback():
"""
threaded function
"""
hv.all_cycle(colors, frames=fnum, sleepinterval=tinterval)
self.lighting_thread = threading.Thread(target=callback)
self.lighting_thread.start()
def quit_app(self):
"""
End execution of app
"""
if not self.lighting_thread == None:
terminate_thread(self.lighting_thread)
self.root.destroy()
if __name__ == '__main__':
ROOT = tki.Tk()
APP = BreathingApp(ROOT)
ROOT.mainloop()