1
|
|
|
""" |
2
|
|
|
* PyDMXControl: A Python 3 module to control DMX using uDMX. |
3
|
|
|
* Featuring fixture profiles, built-in effects and a web control panel. |
4
|
|
|
* <https://github.com/MattIPv4/PyDMXControl/> |
5
|
|
|
* Copyright (C) 2018 Matt Cowley (MattIPv4) ([email protected]) |
6
|
|
|
* |
7
|
|
|
* This program is free software: you can redistribute it and/or modify |
8
|
|
|
* it under the terms of the GNU General Public License as published |
9
|
|
|
* by the Free Software Foundation, either version 3 of the License, or |
10
|
|
|
* (at your option) any later version. |
11
|
|
|
* This program is distributed in the hope that it will be useful, |
12
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14
|
|
|
* GNU General Public License for more details. |
15
|
|
|
* You should have received a copy of the GNU General Public License |
16
|
|
|
* along with this program. If not, please see |
17
|
|
|
* <https://github.com/MattIPv4/PyDMXControl/blob/master/LICENSE> or <http://www.gnu.org/licenses/>. |
18
|
|
|
""" |
19
|
|
|
|
20
|
|
|
import glob |
21
|
|
|
import os.path |
22
|
|
|
from importlib.machinery import SourceFileLoader |
23
|
|
|
from typing import Union, Tuple, List |
24
|
|
|
|
25
|
|
|
dir_path = os.path.dirname(os.path.realpath(__file__)) |
26
|
|
|
|
27
|
|
|
|
28
|
|
|
def load(name: str) -> Union[Tuple[str, str, List[List[int]]], None]: |
29
|
|
|
full = "{}/{}.data.py".format(dir_path, name) |
30
|
|
|
if not os.path.isfile(full): |
31
|
|
|
return None |
32
|
|
|
try: |
33
|
|
|
module = SourceFileLoader(name, full).load_module() |
34
|
|
|
except: |
35
|
|
|
return None |
36
|
|
|
return module.name1, module.name2, module.points |
37
|
|
|
|
38
|
|
|
|
39
|
|
|
def generate(): |
40
|
|
|
import xml.etree.ElementTree as ET |
41
|
|
|
import string |
42
|
|
|
|
43
|
|
|
printable = set(string.printable) |
44
|
|
|
files = glob.glob("/Applications/LXSeries/LXFree.app/Contents/Resources/keys/*.lxkey") |
45
|
|
|
|
46
|
|
|
for file in files: |
47
|
|
|
tree = ET.parse(file) |
48
|
|
|
root = tree.getroot() |
49
|
|
|
for fixture in root.findall("kentry"): |
50
|
|
|
try: |
51
|
|
|
# Get names |
52
|
|
|
name = fixture.find("fname").text |
53
|
|
|
full_name = fixture.find("name").text |
54
|
|
|
|
55
|
|
|
# Get points to numbers |
56
|
|
|
raw_points = fixture.find("custom").find("symbol").find("points") |
57
|
|
|
parsed_points = [] |
58
|
|
|
for point in raw_points: |
59
|
|
|
parsed_points.append([ |
60
|
|
|
float(point.find("x").text), |
61
|
|
|
float(point.find("y").text), |
62
|
|
|
int(point.find("op").text) |
63
|
|
|
]) |
64
|
|
|
|
65
|
|
|
# Find the smallest x/y (often negative) |
66
|
|
|
minx = min([f[0] for f in parsed_points]) |
67
|
|
|
minx = minx * -1 if minx < 0 else 0 |
68
|
|
|
miny = min([f[1] for f in parsed_points]) |
69
|
|
|
miny = miny * -1 if miny < 0 else 0 |
70
|
|
|
|
71
|
|
|
# Force all points to be positive |
72
|
|
|
parsed_points = [[f[0] + minx, f[1] + miny, f[2]] for f in parsed_points] |
73
|
|
|
|
74
|
|
|
# Scale to reduce likelihood of decimal point and then make int |
75
|
|
|
parsed_points = [[f[0] * 4, f[1] * 4, f[2]] for f in parsed_points] |
76
|
|
|
parsed_points = [[int(f[0]), int(f[1]), f[2]] for f in parsed_points] |
77
|
|
|
|
78
|
|
|
# Output |
79
|
|
|
lines = [ |
80
|
|
|
"name1 = \"{}\"".format(name), |
81
|
|
|
"name2 = \"{}\"".format(full_name), |
82
|
|
|
"points = {}".format(parsed_points) |
83
|
|
|
] |
84
|
|
|
file = name.replace(" ", "_").replace(".", "").replace("/", "") \ |
85
|
|
|
+ "_" + full_name.replace(" ", "_").replace(".", "").replace("/", "") |
86
|
|
|
file = ''.join(filter(lambda x: x in printable, file)) |
87
|
|
|
with open("{}/{}.data.py".format(dir_path, file), "w") as f: |
88
|
|
|
f.write("\n".join(lines)) |
89
|
|
|
except: |
90
|
|
|
pass |
91
|
|
|
|