diff --git a/gui.py b/gui.py
index a486968..fcba6fe 100755
--- a/gui.py
+++ b/gui.py
@@ -1,5 +1,6 @@
#!/usr/bin/env python3
+from dis import findlinestarts
import lib27gn950
import hid
@@ -13,175 +14,206 @@
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
-class Gui(QWidget):
- def __init__(self):
- super().__init__()
- self.init_ui()
-
-
- def init_ui(self):
- self.setWindowTitle('27g950controller')
-
- mainLayout = QVBoxLayout(self)
-
- self.selectionbuttonslayout = QHBoxLayout(self)
- self.selectionbuttonslayout.addWidget(QLabel('Select monitors: '))
- mainLayout.addLayout(self.selectionbuttonslayout)
-
- mainLayout.addWidget(QLabel(''))
-
- powerbuttonslayout = QGridLayout(self)
- powerbuttonslayout.addWidget(QLabel('Power'), 0, 0, 1, 2)
- x = QPushButton('Turn off')
- x.clicked.connect(self.turn_off)
- powerbuttonslayout.addWidget(x, 1, 0)
- x = QPushButton('Turn on')
- x.clicked.connect(self.turn_on)
- powerbuttonslayout.addWidget(x, 1, 1)
- mainLayout.addLayout(powerbuttonslayout)
-
- mainLayout.addWidget(QLabel(''))
-
- brightnessbuttonslayout = QGridLayout(self)
- brightnessbuttonslayout.addWidget(QLabel('Brightness'), 0, 0, 1, 6)
- for i in range(1, 13):
- x = QPushButton(str(i))
- x.clicked.connect(lambda _, i=i: self.set_brightness(i))
- row = 1 + i//7
- col = i - 1 - (6 if i > 6 else 0)
- brightnessbuttonslayout.addWidget(x, row, col)
- mainLayout.addLayout(brightnessbuttonslayout)
-
- mainLayout.addWidget(QLabel(''))
-
- configbuttonslayout = QGridLayout(self)
- configbuttonslayout.addWidget(QLabel('Lighting mode'), 0, 0, 1, 4)
- for i in range(4):
- x = QPushButton(f'Color {i+1}')
- x.clicked.connect(lambda _, i=i: self.set_static_color(i+1))
- configbuttonslayout.addWidget(x, 1, i)
- x = QPushButton('Peaceful')
- x.clicked.connect(self.set_peaceful_color)
- configbuttonslayout.addWidget(x, 2, 0, 1, 2)
- x = QPushButton('Dynamic')
- x.clicked.connect(self.set_dynamic_color)
- configbuttonslayout.addWidget(x, 2, 2, 1, 2)
- mainLayout.addLayout(configbuttonslayout)
-
- mainLayout.addWidget(QLabel(''))
-
- editbuttonsentrylayout = QHBoxLayout(self)
- editbuttonsbuttonslayout = QHBoxLayout(self)
- x = QLabel('Enter new color: ')
- editbuttonsentrylayout.addWidget(x)
- self.colorInputBox = QLineEdit('27e5ff')
- self.colorInputBox.setFixedWidth(150)
- self.colorInputBox.setAlignment(Qt.AlignCenter)
- font = QFont()
- font.setFamily('Monospace')
- font.setStyleHint(QFont.TypeWriter)
- self.colorInputBox.setFont(font)
- self.colorInputBox.textChanged.connect(self.validate_new_color)
- editbuttonsentrylayout.addWidget(self.colorInputBox)
- self.colorValidationOutputBox = QLabel('valid')
- self.colorValidationOutputBox.setAlignment(Qt.AlignRight)
- editbuttonsentrylayout.addWidget(self.colorValidationOutputBox)
- for i in range(4):
- x = QPushButton(f'Set {i+1}')
- x.clicked.connect(lambda _, i=i: self.set_color(i+1))
- editbuttonsbuttonslayout.addWidget(x)
- editbuttonslayout = QVBoxLayout(self)
-
- editbuttonslayout.addWidget(QLabel('Edit static colors'))
- editbuttonslayout.addLayout(editbuttonsentrylayout)
- editbuttonslayout.addLayout(editbuttonsbuttonslayout)
- mainLayout.addLayout(editbuttonslayout)
-
-
- def init_monitors(self):
- monitors = lib27gn950.find_monitors()
- if not monitors:
- for item in self.layout().children():
- self.layout().removeItem(item)
- self.layout().addWidget(QLabel('No monitors found'))
- return
-
- self.devs = []
- for monitor in monitors:
- self.devs.append(hid.Device(path=monitor['path']))
-
- self.selection = list(range(len(self.devs)))
-
- for i in self.selection:
- x = QCheckBox(str(i+1))
- x.setCheckState(2)
- x.stateChanged.connect(lambda checked, i=i: self.update_selection(i, checked))
- self.selectionbuttonslayout.addWidget(x)
-
-
- def cleanup(self):
- if hasattr(self, 'devs'):
- for dev in self.devs:
- dev.close()
-
-
- def is_valid_color(self, color):
- return re.match('^[0-9a-f]{6}$', color)
-
- def validate_new_color(self, text):
- s = 'valid' if self.is_valid_color(text.lower()) else 'invalid'
- self.colorValidationOutputBox.setText(s)
-
-
- def update_selection(self, monitor_num, checked):
- if checked == 0:
- self.selection.remove(monitor_num)
- elif checked == 2:
- self.selection.append(monitor_num)
-
-
- def send_command(self, cmd):
- devs = []
- for i in self.selection:
- devs.append(self.devs[i])
- lib27gn950.send_command(cmd, devs)
-
-
- def turn_on(self):
- cmd = lib27gn950.control_commands['turn_on']
- self.send_command(cmd)
- def turn_off(self):
- cmd = lib27gn950.control_commands['turn_off']
- self.send_command(cmd)
-
- def set_static_color(self, color):
- cmd = lib27gn950.control_commands['color' + str(color)]
- self.send_command(cmd)
- def set_peaceful_color(self):
- cmd = lib27gn950.control_commands['color_peaceful']
- self.send_command(cmd)
- def set_dynamic_color(self):
- cmd = lib27gn950.control_commands['color_dynamic']
- self.send_command(cmd)
-
- def set_brightness(self, brt):
- cmd = lib27gn950.brightness_commands[brt]
- self.send_command(cmd)
-
- def set_color(self, slot):
- color = self.colorInputBox.text().lower()
- if not self.is_valid_color(color):
- return
- cmd = lib27gn950.get_set_color_command(slot, color)
- self.send_command(cmd)
+from threading import Thread
+from lightsync import LightsyncPrismatic
+class Gui(QWidget):
+ def __init__(self):
+ super().__init__()
+ self.init_ui()
+
+
+ def init_ui(self):
+ self.setWindowTitle('lg-x-g950-controller')
+
+ mainLayout = QVBoxLayout(self)
+
+ self.selectionbuttonslayout = QHBoxLayout(self)
+ self.selectionbuttonslayout.addWidget(QLabel('Select monitors: '))
+ mainLayout.addLayout(self.selectionbuttonslayout)
+
+ mainLayout.addWidget(QLabel(''))
+
+ powerbuttonslayout = QGridLayout(self)
+ powerbuttonslayout.addWidget(QLabel('Power'), 0, 0, 1, 2)
+ x = QPushButton('Turn off')
+ x.clicked.connect(self.turn_off)
+ powerbuttonslayout.addWidget(x, 1, 0)
+ x = QPushButton('Turn on')
+ x.clicked.connect(self.turn_on)
+ powerbuttonslayout.addWidget(x, 1, 1)
+ mainLayout.addLayout(powerbuttonslayout)
+
+ mainLayout.addWidget(QLabel(''))
+
+ brightnessbuttonslayout = QGridLayout(self)
+ brightnessbuttonslayout.addWidget(QLabel('Brightness'), 0, 0, 1, 6)
+ for i in range(1, 13):
+ x = QPushButton(str(i))
+ x.clicked.connect(lambda _, i=i: self.set_brightness(i))
+ row = 1 + i//7
+ col = i - 1 - (6 if i > 6 else 0)
+ brightnessbuttonslayout.addWidget(x, row, col)
+ mainLayout.addLayout(brightnessbuttonslayout)
+
+ mainLayout.addWidget(QLabel(''))
+
+ configbuttonslayout = QGridLayout(self)
+ configbuttonslayout.addWidget(QLabel('Lighting mode'), 0, 0, 1, 4)
+ for i in range(4):
+ x = QPushButton(f'Color {i+1}')
+ x.clicked.connect(lambda _, i =i: self.set_static_color(i+1))
+ configbuttonslayout.addWidget(x, 1, i)
+ x = QPushButton('Peaceful')
+ x.clicked.connect(self.set_peaceful_color)
+ configbuttonslayout.addWidget(x, 2, 0, 1, 2)
+ x = QPushButton('Dynamic')
+ x.clicked.connect(self.set_dynamic_color)
+ configbuttonslayout.addWidget(x, 2, 2, 1, 2)
+ mainLayout.addLayout(configbuttonslayout)
+ self.syncButton = QPushButton(self)
+ self.syncButton.setText('▶️ Lightsync (Prismatic)')
+ self.syncButton.clicked.connect(self.run_lightsync_prismatic)
+ configbuttonslayout.addWidget(self.syncButton, 3, 0, 1, 4)
+ mainLayout.addLayout(configbuttonslayout)
+
+ mainLayout.addWidget(QLabel(''))
+
+ editbuttonsentrylayout = QHBoxLayout(self)
+ editbuttonsbuttonslayout = QHBoxLayout(self)
+ x = QLabel('Enter new color: ')
+ editbuttonsentrylayout.addWidget(x)
+ self.colorInputBox = QLineEdit('27e5ff')
+ self.colorInputBox.setFixedWidth(150)
+ self.colorInputBox.setAlignment(Qt.AlignCenter)
+ font = QFont()
+ font.setFamily('Monospace')
+ font.setStyleHint(QFont.TypeWriter)
+ self.colorInputBox.setFont(font)
+ self.colorInputBox.textChanged.connect(self.validate_new_color)
+ editbuttonsentrylayout.addWidget(self.colorInputBox)
+ self.colorValidationOutputBox = QLabel('valid')
+ self.colorValidationOutputBox.setAlignment(Qt.AlignRight)
+ editbuttonsentrylayout.addWidget(self.colorValidationOutputBox)
+ for i in range(4):
+ x = QPushButton(f'Set {i+1}')
+ x.clicked.connect(lambda _, i=i: self.set_color(i+1))
+ editbuttonsbuttonslayout.addWidget(x)
+ editbuttonslayout = QVBoxLayout(self)
+
+ editbuttonslayout.addWidget(QLabel('Edit static colors'))
+ editbuttonslayout.addLayout(editbuttonsentrylayout)
+ editbuttonslayout.addLayout(editbuttonsbuttonslayout)
+ mainLayout.addLayout(editbuttonslayout)
+
+
+ def init_monitors(self):
+ monitors = lib27gn950.find_monitors()
+ if not monitors:
+ for item in self.layout().children():
+ self.layout().removeItem(item)
+ self.layout().addWidget(QLabel('No monitors found'))
+ return
+
+ self.devs = []
+ for monitor in monitors:
+ self.devs.append(hid.Device(path=monitor['path']))
+
+ self.selection = list(range(len(self.devs)))
+
+ for i in self.selection:
+ x = QCheckBox(str(i+1))
+ x.setCheckState(2)
+ x.stateChanged.connect(lambda checked, i=i: self.update_selection(i, checked))
+ self.selectionbuttonslayout.addWidget(x)
+
+
+ def cleanup(self):
+ if hasattr(self, 'devs'):
+ for dev in self.devs:
+ dev.close()
+
+
+ def is_valid_color(self, color):
+ return re.match('^[0-9a-f]{6}$', color)
+
+ def validate_new_color(self, text):
+ s = 'valid' if self.is_valid_color(text.lower()) else 'invalid'
+ self.colorValidationOutputBox.setText(s)
+
+
+ def update_selection(self, monitor_num, checked):
+ if checked == 0:
+ self.selection.remove(monitor_num)
+ elif checked == 2:
+ self.selection.append(monitor_num)
+
+
+ def send_command(self, cmd):
+ self.stop_lightsync()
+ devs = []
+ for i in self.selection:
+ devs.append(self.devs[i])
+ lib27gn950.send_command(cmd, devs)
+
+
+ def turn_on(self):
+ cmd = lib27gn950.control_commands['turn_on']
+ self.send_command(cmd)
+ def turn_off(self):
+ cmd = lib27gn950.control_commands['turn_off']
+ self.send_command(cmd)
+
+ def set_static_color(self, color):
+ cmd = lib27gn950.control_commands['color' + str(color)]
+ self.send_command(cmd)
+ def set_peaceful_color(self):
+ cmd = lib27gn950.control_commands['color_peaceful']
+ self.send_command(cmd)
+ def set_dynamic_color(self):
+ cmd = lib27gn950.control_commands['color_dynamic']
+ self.send_command(cmd)
+
+ def set_brightness(self, brt):
+ cmd = lib27gn950.brightness_commands[brt]
+ self.send_command(cmd)
+
+ def set_color(self, slot):
+ color = self.colorInputBox.text().lower()
+ if not self.is_valid_color(color):
+ return
+ cmd = lib27gn950.get_set_color_command(slot, color)
+ self.send_command(cmd)
+
+ def thread_finished(self):
+ self.syncButton.setText('▶️ Lightsync (Prismatic)')
+ print("Sync stopped")
+ self.syncButton.clicked.disconnect()
+ self.syncButton.clicked.connect(self.run_lightsync_prismatic)
+
+ def stop_lightsync(self):
+ if isinstance(self.thread,LightsyncPrismatic) :
+ self.thread.stop()
+ self.thread.wait()
+
+ def run_lightsync_prismatic(self):
+ for i in self.selection:
+ try:
+ self.thread = LightsyncPrismatic(config=dict(),dev=self.devs[i])
+ self.thread.finished.connect(self.thread_finished)
+ self.thread.start()
+ self.syncButton.setText('■ Lightsync (Prismatic)')
+ self.syncButton.clicked.disconnect()
+ self.syncButton.clicked.connect(self.stop_lightsync)
+ except Exception as e:
+ print(e)
app = QApplication(sys.argv)
try:
- x = Gui()
- x.init_monitors()
- x.show()
- sys.exit(app.exec_())
+ x = Gui()
+ x.init_monitors()
+ x.show()
+ sys.exit(app.exec_())
finally:
- if 'x' in locals():
- x.cleanup()
+ if 'x' in locals():
+ x.cleanup()
diff --git a/lightpack.py b/lightpack.py
new file mode 100644
index 0000000..c793d86
--- /dev/null
+++ b/lightpack.py
@@ -0,0 +1,80 @@
+import socket
+import re
+
+class lightpack:
+
+# host = '127.0.0.1' # The remote host
+# port = 3636 # The same port as used by the server
+# apikey = 'key' # Secure API key which generates by Lightpack software on Dev tab
+# ledMap = [1,2,3,4,5,6,7,8,9,10] # Mapped LEDs
+
+ def __init__(self, _host, _port, _ledMap = None, _apikey = None):
+ self.host = _host
+ self.port = _port
+ self.ledMap = _ledMap if _ledMap is not None else []
+ self.apikey = _apikey
+
+ def __readResult(self): # Return last-command API answer (call in every local method)
+ total_data = []
+ data = self.connection.recv(8192)
+ total_data.append(data)
+ return b"".join(total_data).decode()
+
+ def getProfiles(self):
+ self.connection.send(b"getprofiles\n")
+ profiles = self.__readResult()
+ return profiles.split(':')[1].rstrip(';\n\r').split(';')
+
+ def getProfile(self):
+ self.connection.send(b"getprofile\n")
+ profile = self.__readResult()
+ profile = profile.split(':')[1]
+ return profile
+
+ def getStatus(self):
+ self.connection.send(b"getstatus\n")
+ status = self.__readResult()
+ status = status.split(':')[1]
+ return status
+
+ def getCountLeds(self):
+ self.connection.send(b"getcountleds\n")
+ count = self.__readResult()
+ count = count.split(':')[1]
+ return int(count)
+
+ def getAPIStatus(self):
+ self.connection.send(b"getstatusapi\n")
+ status = self.__readResult()
+ status = status.split(':')[1]
+ return status
+
+ def connect(self):
+ try: # Try to connect to the server API
+ self.connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ self.connection.connect((self.host, self.port))
+ self.__readResult()
+ if self.apikey is not None:
+ cmd = 'apikey:' + self.apikey + '\n'
+ self.connection.send(str.encode(cmd))
+ self.__readResult()
+ self.getLedMap()
+ return 0
+ except:
+ print('Lightpack API server is missing')
+ return -1
+
+ def disconnect(self):
+ self.unlock()
+ self.connection.close()
+
+ def getColors(self):
+ try:
+ self.connection.send(b"getcolors\n")
+ status = self.__readResult()
+ #print(status)
+ pixels = status.split(':')[1]
+ rgb = re.findall(r"(\d+)-(\d+),(\d+),(\d+);", pixels or "")
+ return rgb if rgb else None
+ finally:
+ quit()
\ No newline at end of file