1import re
2import subprocess
3import traceback
4
5from fsgs import Option
6from fsgs.amiga.fsuaedevicehelper import FSUAEDeviceHelper
7from launcher.devicemanager import DeviceManager
8from .device import Device
9
10
11class EnumerateHelper(object):
12    def __init__(self):
13        self.devices = []
14        self.joystick_devices = []
15        self.keyboard_devices = []
16        self.joystick_like_devices = []
17        self.initialized = False
18
19    def update(self):
20        # if cls.initialized:
21        #     return
22        # init can be called more than once (by setting initialized to
23        # false, used by refresh function, so we need to clear the lists...
24        self.devices = []
25        self.joystick_devices = []
26        self.keyboard_devices = []
27        self.joystick_like_devices = []
28        self.init_fsuae()
29
30    def init(self):
31        if self.initialized:
32            return
33        self.init_fsuae()
34        self.initialized = True
35
36    def init_fsuae(self):
37        print("[INPUT] EnumerateHelper: Finding connected joysticks")
38        try:
39            p = FSUAEDeviceHelper.start_with_args(
40                ["--list"], stdout=subprocess.PIPE
41            )
42            joysticks = p.stdout.read()
43            p.wait()
44        except Exception:
45            print("[INPUT] Exception while listing joysticks and devices")
46            traceback.print_exc()
47            return
48        print("[INPUT]", repr(joysticks))
49        # If the character conversion fails, replace will ensure that
50        # as much as possible succeeds. The joystick in question will
51        # not be pre-selectable in the launcher, but the other ones will
52        # work at least.
53        joysticks = joysticks.decode("UTF-8", "replace")
54        joysticks = [x.strip() for x in joysticks.split("\n") if x.strip()]
55
56        # joysticks.append("J: controller xbox 360 for windows")
57        # joysticks.append("Buttons: 10 Hats: 1 Axes: 5 Balls: 0")
58
59        device_name_count = {}
60        last_joystick = None
61
62        for line in joysticks:
63            if line.startswith("#"):
64                continue
65            elif line.startswith("Buttons:"):
66                parts = line.split(" ")
67                last_joystick.buttons = int(parts[1])
68                last_joystick.hats = int(parts[3])
69                last_joystick.axes = int(parts[5])
70                last_joystick.balls = int(parts[7])
71                continue
72            elif line.startswith("SDLName:"):
73                value = line.split(" ", 1)[1]
74                # Strip quotes
75                last_joystick.sdl_name = value[1:-1]
76                continue
77
78            device = Device()
79            device_type, name = line.split(" ", 1)
80
81            name_count = device_name_count.get((device_type, name), 0) + 1
82            device_name_count[(device_type, name)] = name_count
83            if name_count > 1:
84                name = name + " #" + str(name_count)
85            device.id = name
86            name = re.sub("[ ]+", " ", name)
87            device.name = name
88            if device_type == "J:":
89                device.type = "joystick"
90                last_joystick = device
91                self.joystick_devices.append(device)
92            elif device_type == "M:":
93                device.type = "mouse"
94            elif device_type == "K:":
95                # works as an emulated joystick...
96                # device_type = "joystick"
97                device.type = "keyboard"
98                self.keyboard_devices.append(device)
99            # self.device_types.append(device_type)
100            self.devices.append(device)
101        for i, device in enumerate(self.joystick_devices):
102            device.index = i
103        for i, device in enumerate(self.keyboard_devices):
104            device.index = i
105
106        self.joystick_like_devices.extend(self.joystick_devices)
107        self.joystick_like_devices.extend(self.keyboard_devices)
108
109    def default_port_selection(self, ports, options):
110        print("[INPUT] Default port selection (EnumerateHelper)")
111        self.init()
112        # for device in self.devices:
113        #     print(" #", device.id)
114        #     device.configure("megadrive")
115
116        if len(ports) > 0:
117            if ports[0].type_option:
118                print("[INPUT] New-style port device selection:")
119                # Supports new-style port selection
120                port_devices = DeviceManager.get_non_amiga_devices_for_ports(
121                    options
122                )
123                from fsgs.platform import Platform
124
125                if ports[0].type_option == Option.C64_PORT_2_TYPE:
126                    print("[INPUT] Hack for inverted C64 port order")
127                    temp = port_devices[1]
128                    port_devices[1] = port_devices[2]
129                    port_devices[2] = temp
130                for i, port in enumerate(ports):
131                    for device in self.devices:
132                        if port_devices[i + 1].id == device.id:
133                            port.device = device
134                            print("[INPUT]", port.name, "<-", device.id)
135                            break
136                    else:
137                        print("[INPUT]", port.name, "<- [None]")
138                return
139
140        joystick_like_devices = self.joystick_like_devices[:]
141        print("[INPUT] Old-style port device selection:")
142        for port in ports:
143            for i, device in enumerate(joystick_like_devices):
144                # device.configure()
145                if True:
146                    joystick_like_devices.pop(i)
147                    port.device = device
148                    break
149            print("[INPUT] Old Selection:", port.name, port.device)
150