Erster Commit: nativer Linux-Port aus macOS-Bytecode
Läuft die Voice Acoustic VA-Remotecontrol (AllDSP AllControl) nativ unter Linux auf echtem wxGTK 3.0 — ohne Wine und ohne dekompilierten App-Code. Ausgeführt wird das unveränderte Python-2.7-Bytecode aus dem macOS-.app; C-Extensions (wxGTK/numpy/ scipy/PortAudio) kommen nativ aus Debian stretch. Enthält: va/ (Original-.pyc + pure-Python-Libs + Assets + launch.py mit den drei Linux-Fixes), Dockerfile/run.sh/entrypoint.sh, reference/ (dekompilierter Quellcode zum Debuggen) und README/STATUS. img.cache (378 MB, regenerierbar) ist per .gitignore ausgeschlossen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,451 @@
|
||||
# uncompyle6 version 3.9.3
|
||||
# Python bytecode version base 2.6 (62161)
|
||||
# Decompiled from: Python 3.9.25 (main, Oct 31 2025, 23:16:49)
|
||||
# [GCC 14.2.0]
|
||||
# Embedded file name: select_units.pyc
|
||||
# Compiled at: 2023-01-25 11:38:51
|
||||
import wx, os, data_model, traceback, one_unit, ConfigParser, protocol, wx.lib.mixins.listctrl as listmix, mytime, time, dialog, wx.lib.buttons
|
||||
mac_names = 'posix'
|
||||
if os.name in mac_names:
|
||||
newline = '\n'
|
||||
else:
|
||||
newline = '\r\n'
|
||||
|
||||
class UnitList(wx.Panel, listmix.ColumnSorterMixin):
|
||||
|
||||
def __init__(self, parent, units, size, pos, project=False, isExistingList=False):
|
||||
wx.Panel.__init__(self, parent, -1, style=wx.WANTS_CHARS, size=size, pos=pos)
|
||||
self.parent = parent
|
||||
self.isExistingList = isExistingList
|
||||
self.index = 0
|
||||
self.units = units
|
||||
self.list_ctrl = wx.ListCtrl(self, size=size, style=wx.LC_REPORT | wx.BORDER_SUNKEN | wx.LC_SORT_ASCENDING)
|
||||
self.list_ctrl.InsertColumn(0, 'Reference', width=70)
|
||||
self.list_ctrl.InsertColumn(1, 'MAC Address', width=130)
|
||||
self.list_ctrl.InsertColumn(2, 'Name', width=145)
|
||||
listmix.ColumnSorterMixin.__init__(self, 3)
|
||||
self.selected = None
|
||||
self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnClick, self.list_ctrl)
|
||||
return
|
||||
|
||||
def GetListCtrl(self):
|
||||
return self.list_ctrl
|
||||
|
||||
def RefreshList(self):
|
||||
try:
|
||||
(sortedColumn, ascending) = self.GetSortState()
|
||||
except:
|
||||
sortedColumn = 2
|
||||
ascending = 1
|
||||
print 'su.RL.Default sorting'
|
||||
|
||||
if sortedColumn == -1:
|
||||
sortedColumn = 2
|
||||
ascending = 1
|
||||
self.list_ctrl.DeleteAllItems()
|
||||
self.itemDataMap = {}
|
||||
self.index = 1
|
||||
for MAC in sorted(self.units.keys()):
|
||||
if len(self.units[MAC]) < 2:
|
||||
continue
|
||||
pos = self.units[MAC][2]
|
||||
try:
|
||||
index = int(pos)
|
||||
except:
|
||||
index = self.index
|
||||
|
||||
name = self.units[MAC][0]
|
||||
if MAC[:4] in ('VN::', 'DEMO'):
|
||||
name = name.strip() + ' (Virtual)'
|
||||
elif MAC[:5] == 'Group':
|
||||
name = name.strip()
|
||||
elif MAC not in one_unit.app.server.peers.units or one_unit.app.server.peers.units[MAC].link_status != 'available':
|
||||
name = name.strip() + ' (Offline)'
|
||||
self.itemDataMap[index] = (
|
||||
pos, MAC, name)
|
||||
self.index += 1
|
||||
|
||||
keys = self.itemDataMap.keys()
|
||||
for key in keys:
|
||||
pos = self.list_ctrl.InsertStringItem(key, str(self.itemDataMap[key][0]))
|
||||
self.list_ctrl.SetStringItem(pos, 1, str(self.itemDataMap[key][1]))
|
||||
self.list_ctrl.SetStringItem(pos, 2, str(self.itemDataMap[key][2]))
|
||||
self.list_ctrl.SetItemData(pos, key)
|
||||
|
||||
try:
|
||||
self.SortListItems(sortedColumn, ascending)
|
||||
except:
|
||||
pass
|
||||
|
||||
return
|
||||
|
||||
def GetSelected(self):
|
||||
item = -1
|
||||
selected = []
|
||||
count = 1000
|
||||
while count > 0:
|
||||
count -= 1
|
||||
item = self.list_ctrl.GetNextItem(item, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED)
|
||||
if item == -1:
|
||||
break
|
||||
selected.append(self.itemDataMap[self.list_ctrl.GetItemData(item)][1])
|
||||
|
||||
return selected
|
||||
|
||||
def OnClick(self, e):
|
||||
item = e.m_itemIndex
|
||||
col = e.m_col
|
||||
(pos, mac, name) = self.itemDataMap[self.list_ctrl.GetItemData(item)]
|
||||
if pos == '' and self.isExistingList == True:
|
||||
pos = 'Reference'
|
||||
else:
|
||||
pos = ''
|
||||
self.itemDataMap[item] = (
|
||||
pos, mac, name)
|
||||
if self.isExistingList == True:
|
||||
for tmpMac in self.parent.result:
|
||||
self.parent.result[tmpMac] = (
|
||||
self.parent.result[tmpMac][0], self.parent.result[tmpMac][1], '')
|
||||
self.units[tmpMac] = (self.units[tmpMac][0], self.units[tmpMac][1], '')
|
||||
|
||||
self.units[mac] = (
|
||||
self.units[mac][0], self.units[mac][1], pos)
|
||||
self.parent.result[mac] = self.units[mac]
|
||||
self.RefreshList()
|
||||
return
|
||||
|
||||
|
||||
class Dialog(wx.Dialog):
|
||||
|
||||
def __init__(self, parent, id, title, infotext='', unit_type=None, existing_members={}, bg=None, size=(800, 385), bgcolour=(220, 220, 220), fgcolour=(70, 70, 70), add_virtual=False, allocate=False, groupID=None, group_type=None):
|
||||
wx.Dialog.__init__(self, None, wx.ID_ANY, title, size=size, style=wx.STAY_ON_TOP | wx.DEFAULT_DIALOG_STYLE)
|
||||
self.allocate = allocate
|
||||
self.parent = parent
|
||||
self.groupID = groupID
|
||||
self.group_type = group_type
|
||||
self.result = {}
|
||||
if self.group_type in one_unit.app.group_membership_filter:
|
||||
if 'virtual unit' not in one_unit.app.group_membership_filter[self.group_type]:
|
||||
add_virtual = False
|
||||
self.vn_nr = 0
|
||||
self.virtualUnits = {}
|
||||
for MAC in existing_members:
|
||||
if existing_members[MAC][2] in (0, '0', 'Master', 'Reference'):
|
||||
self.result[MAC] = (
|
||||
existing_members[MAC][0], existing_members[MAC][1], 'Reference')
|
||||
else:
|
||||
self.result[MAC] = (
|
||||
existing_members[MAC][0], existing_members[MAC][1], '')
|
||||
if MAC[:4] == 'VN::':
|
||||
self.vn_nr += 1
|
||||
self.virtualUnits[MAC] = ('Virtual Unit ' + ('00' + str(self.vn_nr))[-2:], one_unit.app.main_frame.supported_unit_ids[0], '')
|
||||
|
||||
if bg != None:
|
||||
self.bg = bg
|
||||
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
|
||||
self.frame_height = 2 * wx.SystemSettings.GetMetric(wx.SYS_CAPTION_Y) + wx.SystemSettings.GetMetric(wx.SYS_BORDER_Y)
|
||||
if os.name in mac_names:
|
||||
self.frame_height = 24
|
||||
self.infotext = None
|
||||
if infotext != '':
|
||||
textstring = wx.StaticText(self, -1, infotext, style=wx.ALIGN_LEFT, pos=(25,
|
||||
10))
|
||||
textstring.SetForegroundColour(fgcolour)
|
||||
self.infotext = textstring
|
||||
self.infostring = infotext
|
||||
if os.name in mac_names:
|
||||
textstring.SetFont(wx.Font(11, wx.SWISS, wx.NORMAL, wx.NORMAL))
|
||||
textstring.Wrap(350)
|
||||
style = wx.TE_READONLY
|
||||
existinglabel = wx.StaticText(self, -1, 'Group Members (double click to select reference):', style=wx.ALIGN_LEFT, pos=(440,
|
||||
15))
|
||||
availablelabel = wx.StaticText(self, -1, 'Available Units:', style=wx.ALIGN_LEFT, pos=(10,
|
||||
15))
|
||||
self.existing = UnitList(self, self.result, (350, 280), pos=(440, 40), project=add_virtual | allocate, isExistingList=True)
|
||||
self.getAllUnits()
|
||||
self.available = UnitList(self, self.all_units, (350, 280), pos=(10, 40), project=add_virtual | allocate)
|
||||
if allocate == True:
|
||||
link_button = wx.lib.buttons.GenButton(self, 13, 'Link', pos=(370, 76), size=(60,
|
||||
40))
|
||||
link_button = wx.lib.buttons.GenButton(self, 14, 'Unlink', pos=(370, 132), size=(60,
|
||||
40))
|
||||
self.Bind(wx.EVT_BUTTON, self.OnLink, id=13)
|
||||
self.Bind(wx.EVT_BUTTON, self.OnUnlink, id=14)
|
||||
else:
|
||||
self.add_all_button = wx.lib.buttons.GenButton(self, 3, '>>', pos=(380,
|
||||
76), size=(40,
|
||||
40))
|
||||
self.add_button = wx.lib.buttons.GenButton(self, 4, '>', pos=(380, 132), size=(40,
|
||||
40))
|
||||
self.remove_button = wx.lib.buttons.GenButton(self, 5, '<', pos=(380, 188), size=(40,
|
||||
40))
|
||||
self.remove_all_button = wx.lib.buttons.GenButton(self, 6, '<<', pos=(380,
|
||||
244), size=(40,
|
||||
40))
|
||||
self.Bind(wx.EVT_BUTTON, self.OnAddAll, id=3)
|
||||
self.Bind(wx.EVT_BUTTON, self.OnAdd, id=4)
|
||||
self.Bind(wx.EVT_BUTTON, self.OnRemove, id=5)
|
||||
self.Bind(wx.EVT_BUTTON, self.OnRemoveAll, id=6)
|
||||
if add_virtual == True:
|
||||
self.add_virtual_button = wx.lib.buttons.GenButton(self, 7, 'Add Virtual Unit', pos=(240,
|
||||
15), size=(120,
|
||||
20))
|
||||
ok_button = wx.Button(self, 1, 'Ok', pos=(615, 330), size=(70, 20))
|
||||
cancel_button = wx.Button(self, 2, 'Cancel', pos=(705, 330), size=(70, 20))
|
||||
self.Centre()
|
||||
self.parent = parent
|
||||
self.vn_nr = len(self.result) + len(self.all_units)
|
||||
self.SetBackgroundColour(bgcolour)
|
||||
self.Bind(wx.EVT_BUTTON, self.OnOK, id=1)
|
||||
self.Bind(wx.EVT_BUTTON, self.OnCancel, id=2)
|
||||
self.Bind(wx.EVT_BUTTON, self.OnVirtualUnit, id=7)
|
||||
self.CenterOnScreen()
|
||||
self.response = None
|
||||
self.last_struct_id = -1
|
||||
self.refresh_timer = wx.Timer(self)
|
||||
self.Bind(wx.EVT_TIMER, self.on_timer, self.refresh_timer)
|
||||
self.refresh_timer.Start(500)
|
||||
self.available.RefreshList()
|
||||
self.existing.RefreshList()
|
||||
return
|
||||
|
||||
def getAllUnits(self):
|
||||
all_units = {}
|
||||
listUnits = False
|
||||
if self.group_type in one_unit.app.group_membership_filter:
|
||||
if 'unit' in one_unit.app.group_membership_filter[self.group_type]:
|
||||
listUnits = True
|
||||
else:
|
||||
listUnits = True
|
||||
unitsAreExclusive = False
|
||||
if self.group_type in one_unit.app.group_membership_filter and 'exclusiveUnits' in one_unit.app.group_membership_filter[self.group_type]:
|
||||
unitsAreExclusive = True
|
||||
if listUnits:
|
||||
for MAC in self.parent.parent.parent.parent.parent.peers.units.keys():
|
||||
if MAC[:4] in 'DEMO' and self.parent.parent.parent.parent.demo_mode == False:
|
||||
continue
|
||||
if MAC[:4] in ('Choo', 'Star', 'GRP_'):
|
||||
continue
|
||||
if MAC[:4] == 'VN::' and self.allocate == True:
|
||||
continue
|
||||
if MAC in self.result.keys() and self.allocate == False:
|
||||
continue
|
||||
priority = ''
|
||||
if MAC in self.result:
|
||||
priority = self.result[MAC][2]
|
||||
if unitsAreExclusive:
|
||||
add = True
|
||||
for groupMembers in one_unit.app.groups.values():
|
||||
if MAC in groupMembers:
|
||||
add = False
|
||||
break
|
||||
|
||||
if add == False:
|
||||
continue
|
||||
all_units[MAC] = (
|
||||
self.parent.parent.parent.parent.parent.peers.units[MAC].name, self.parent.parent.parent.parent.parent.peers.units[MAC].type, '')
|
||||
|
||||
listVirtualUnits = False
|
||||
if self.group_type in one_unit.app.group_membership_filter:
|
||||
if 'virtual unit' in one_unit.app.group_membership_filter[self.group_type]:
|
||||
listVirtualUnits = True
|
||||
else:
|
||||
listVirtualUnits = True
|
||||
if listVirtualUnits:
|
||||
for MAC in self.virtualUnits:
|
||||
all_units[MAC] = self.virtualUnits[MAC]
|
||||
|
||||
for groupID in one_unit.app.group_names:
|
||||
if self.group_type in one_unit.app.group_membership_filter and one_unit.app.group_type[groupID] not in one_unit.app.group_membership_filter[self.group_type]:
|
||||
continue
|
||||
if self.findOwnGroupMembership(groupID) == True:
|
||||
continue
|
||||
all_units['Group ' + str(groupID)] = (
|
||||
one_unit.app.group_names[groupID], one_unit.app.group_type[groupID], str(groupID))
|
||||
|
||||
self.all_units = all_units
|
||||
return
|
||||
|
||||
def OnLink(self, e):
|
||||
try:
|
||||
selected_unit = self.available.GetSelected()[0]
|
||||
selected_member = self.existing.GetSelected()[0]
|
||||
except:
|
||||
dial = dialog.Dialog(self, -1, 'Link Unit', 'Select a unit and a project member first.', Set=False, OK_Only=True)
|
||||
dial.ShowModal()
|
||||
dial.Destroy()
|
||||
return
|
||||
|
||||
if selected_unit in self.result.keys():
|
||||
dial = dialog.Dialog(self, -1, 'Link Unit', 'This unit is already a project member. To re-allocate it, unlink it from the existing member first.', Set=False, OK_Only=True)
|
||||
dial.ShowModal()
|
||||
dial.Destroy()
|
||||
return
|
||||
print mytime.displayTime() + ' Linking', selected_unit, 'to', selected_member
|
||||
priority = self.result[selected_member][2]
|
||||
self.all_units[selected_unit] = (self.all_units[selected_unit][0], self.all_units[selected_unit][1], '')
|
||||
self.result[selected_unit] = (self.all_units[selected_unit][0], self.all_units[selected_unit][1], '')
|
||||
del self.result[selected_member]
|
||||
self.available.units = self.all_units
|
||||
self.available.RefreshList()
|
||||
self.existing.RefreshList()
|
||||
return
|
||||
|
||||
def OnUnlink(self, e):
|
||||
print 'su.OnUnlink'
|
||||
selected_units = self.available.GetSelected()
|
||||
if selected_units == None:
|
||||
selected_units = []
|
||||
existing_units = self.existing.GetSelected()
|
||||
if existing_units == None:
|
||||
existing_units = []
|
||||
selected_units.extend(existing_units)
|
||||
if len(selected_units) == 0:
|
||||
dial = dialog.Dialog(self, -1, 'Unlink Unit', 'Select a unit and / or a project member first.', Set=False, OK_Only=True)
|
||||
dial.ShowModal()
|
||||
dial.Destroy()
|
||||
return
|
||||
else:
|
||||
for unit in selected_units:
|
||||
if unit not in self.result or unit not in self.all_units:
|
||||
continue
|
||||
priority = self.result[unit][2]
|
||||
type = self.result[unit][1]
|
||||
releasetime = time.localtime()
|
||||
timestring = 'VN::' + str(releasetime.tm_year)[-2:] + ':' + ('00' + str(releasetime.tm_mon))[-2:] + ':' + ('00' + str(releasetime.tm_mday))[-2:] + ':' + ('00' + str(releasetime.tm_hour))[-2:] + ':' + ('00' + str(releasetime.tm_min))[-2:] + ':' + ('00' + str(releasetime.tm_sec))[-2:]
|
||||
self.result[timestring] = ('Virtual Unit', type, '')
|
||||
del self.result[unit]
|
||||
self.all_units[unit] = (self.all_units[unit][0], self.all_units[unit][1], '')
|
||||
|
||||
self.available.units = self.all_units
|
||||
self.existing.RefreshList()
|
||||
self.rebuildAvailableList()
|
||||
return
|
||||
|
||||
def OnVirtualUnit(self, e):
|
||||
releasetime = time.localtime()
|
||||
self.vn_nr += 1
|
||||
timestring = 'VN::' + str(releasetime.tm_sec)[-2:] + ':' + ('00' + str(releasetime.tm_min))[-2:] + ':' + ('00' + str(releasetime.tm_hour))[-2:] + ':' + ('00' + str(releasetime.tm_mday))[-2:] + ':' + ('00' + str(releasetime.tm_mon))[-2:] + ':' + ('00' + str(releasetime.tm_year + self.vn_nr))[-2:]
|
||||
self.virtualUnits[timestring] = ('Virtual Unit ' + ('00' + str(self.vn_nr))[-2:], one_unit.app.main_frame.supported_unit_ids[0], '')
|
||||
self.rebuildAvailableList()
|
||||
return
|
||||
|
||||
def OnAddAll(self, e):
|
||||
for MAC in sorted(self.all_units.keys()):
|
||||
if MAC in self.result.keys():
|
||||
continue
|
||||
free_priority = 0
|
||||
for testMAC in self.result:
|
||||
try:
|
||||
if int(self.result[testMAC][2]) > free_priority:
|
||||
free_priority = int(self.result[testMAC][2])
|
||||
except:
|
||||
continue
|
||||
|
||||
self.result[MAC] = (
|
||||
self.all_units[MAC][0], self.all_units[MAC][1], '')
|
||||
|
||||
self.existing.RefreshList()
|
||||
self.rebuildAvailableList()
|
||||
return
|
||||
|
||||
def OnRemoveAll(self, e):
|
||||
for MAC in self.result.keys():
|
||||
del self.result[MAC]
|
||||
|
||||
self.existing.RefreshList()
|
||||
self.rebuildAvailableList()
|
||||
return
|
||||
|
||||
def OnAdd(self, e):
|
||||
selected = self.available.GetSelected()
|
||||
for MAC in selected:
|
||||
free_priority = 0
|
||||
for testMAC in self.result:
|
||||
try:
|
||||
if int(self.result[testMAC][2]) > free_priority:
|
||||
free_priority = int(self.result[testMAC][2])
|
||||
except:
|
||||
continue
|
||||
|
||||
try:
|
||||
self.result[MAC] = (
|
||||
self.all_units[MAC][0], self.all_units[MAC][1], '')
|
||||
except:
|
||||
pass
|
||||
|
||||
self.existing.RefreshList()
|
||||
self.rebuildAvailableList()
|
||||
return
|
||||
|
||||
def OnRemove(self, e):
|
||||
selected = self.existing.GetSelected()
|
||||
for MAC in selected:
|
||||
if MAC in self.result.keys():
|
||||
print 'su.Removed', MAC
|
||||
del self.result[MAC]
|
||||
|
||||
self.existing.RefreshList()
|
||||
self.rebuildAvailableList()
|
||||
return
|
||||
|
||||
def on_timer(self, e):
|
||||
self.rebuildAvailableList()
|
||||
return
|
||||
|
||||
def findOwnGroupMembership(self, groupID):
|
||||
if groupID == self.groupID:
|
||||
return True
|
||||
for member in one_unit.app.groups[groupID].keys():
|
||||
if member.replace('Group ', '') == self.groupID:
|
||||
return True
|
||||
if member.startswith('Group '):
|
||||
return self.findOwnGroupMembership(member.replace('Group ', ''))
|
||||
|
||||
return False
|
||||
|
||||
def rebuildAvailableList(self):
|
||||
self.getAllUnits()
|
||||
tmpUnits = {}
|
||||
for unit in self.all_units:
|
||||
if unit not in self.existing.units:
|
||||
tmpUnits[unit] = self.all_units[unit]
|
||||
|
||||
if self.available.units.items() != tmpUnits.items():
|
||||
self.available.units = tmpUnits
|
||||
self.available.RefreshList()
|
||||
return
|
||||
|
||||
def OnEraseBackground(self, evt):
|
||||
"""
|
||||
Add a picture to the background
|
||||
"""
|
||||
dc = evt.GetDC()
|
||||
if not dc:
|
||||
dc = wx.ClientDC(self)
|
||||
rect = self.GetUpdateRegion().GetBox()
|
||||
dc.SetClippingRect(rect)
|
||||
dc.Clear()
|
||||
bmp = wx.Bitmap(self.bg)
|
||||
dc.DrawBitmap(bmp, 0, 0)
|
||||
return
|
||||
|
||||
def OnOK(self, evt):
|
||||
self.response = 'OK'
|
||||
if self.IsModal() == False:
|
||||
self.Destroy()
|
||||
else:
|
||||
self.Close()
|
||||
return
|
||||
|
||||
def OnCancel(self, evt):
|
||||
self.response = 'Cancel'
|
||||
if self.IsModal == False:
|
||||
self.Destroy()
|
||||
else:
|
||||
self.Close()
|
||||
return
|
||||
|
||||
|
||||
|
||||
# okay decompiling pycode/select_units.pyc
|
||||
Reference in New Issue
Block a user