From b66ba6ae345714ed29d9eeb567b22e5536e208d6 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 21 Jan 2017 12:50:46 -0500 Subject: [PATCH 001/104] + scripts/sc-configurable.py: An exact copy of scripts/sc-desktop.py, for now --- scripts/sc-configurable.py | 104 +++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100755 scripts/sc-configurable.py diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py new file mode 100755 index 0000000..9eff430 --- /dev/null +++ b/scripts/sc-configurable.py @@ -0,0 +1,104 @@ +#!/usr/bin/env python + +# The MIT License (MIT) +# +# Copyright (c) 2015 Stany MARCEL +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +"""Steam Controller Mouse, Keyboard mode""" + +from steamcontroller import SteamController, SCButtons +from steamcontroller.events import EventMapper, Pos +from steamcontroller.uinput import Keys + +from steamcontroller.daemon import Daemon + +import gc + +def evminit(): + evm = EventMapper() + evm.setPadMouse(Pos.RIGHT) + evm.setPadScroll(Pos.LEFT) + evm.setStickButtons([Keys.KEY_UP, + Keys.KEY_LEFT, + Keys.KEY_DOWN, + Keys.KEY_RIGHT]) + + evm.setTrigButton(Pos.LEFT, Keys.BTN_RIGHT) + evm.setTrigButton(Pos.RIGHT, Keys.BTN_LEFT) + + evm.setButtonAction(SCButtons.LB, Keys.KEY_VOLUMEDOWN) + evm.setButtonAction(SCButtons.RB, Keys.KEY_VOLUMEUP) + + evm.setButtonAction(SCButtons.STEAM, Keys.KEY_HOMEPAGE) + + evm.setButtonAction(SCButtons.A, Keys.KEY_ENTER) + evm.setButtonAction(SCButtons.B, Keys.KEY_BACKSPACE) + evm.setButtonAction(SCButtons.X, Keys.KEY_ESC) + evm.setButtonAction(SCButtons.Y, Keys.KEY_PLAYPAUSE) + + evm.setButtonAction(SCButtons.START, Keys.KEY_NEXTSONG) + evm.setButtonAction(SCButtons.BACK, Keys.KEY_PREVIOUSSONG) + + evm.setButtonAction(SCButtons.LGRIP, Keys.KEY_BACK) + evm.setButtonAction(SCButtons.RGRIP, Keys.KEY_FORWARD) + + evm.setButtonAction(SCButtons.LPAD, Keys.BTN_MIDDLE) + evm.setButtonAction(SCButtons.RPAD, Keys.KEY_SPACE) + + return evm + +class SCDaemon(Daemon): + def run(self): + evm = evminit() + sc = SteamController(callback=evm.process) + sc.run() + del sc + del evm + gc.collect() + +if __name__ == '__main__': + import argparse + + def _main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('command', type=str, choices=['start', 'stop', 'restart', 'debug']) + parser.add_argument('-i', '--index', type=int, choices=[0,1,2,3], default=None) + args = parser.parse_args() + if args.index != None: + daemon = SCDaemon('/tmp/steamcontroller{:d}.pid'.format(args.index)) + else: + daemon = SCDaemon('/tmp/steamcontroller.pid') + + if 'start' == args.command: + daemon.start() + elif 'stop' == args.command: + daemon.stop() + elif 'restart' == args.command: + daemon.restart() + elif 'debug' == args.command: + try: + evm = evminit() + sc = SteamController(callback=evm.process) + sc.run() + except KeyboardInterrupt: + return + + _main() From e4b015d0a120db941cc72c17e0a438908e041448 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 21 Jan 2017 12:54:10 -0500 Subject: [PATCH 002/104] scripts/sc-configurable.py: Changed copyright line and description comment --- scripts/sc-configurable.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 9eff430..92febe4 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -2,7 +2,8 @@ # The MIT License (MIT) # -# Copyright (c) 2015 Stany MARCEL +# Copyright (c) 2016 Mike Cronce +# Stany MARCEL # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,7 +23,7 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -"""Steam Controller Mouse, Keyboard mode""" +"""Steam Controller VDF-configurable mode""" from steamcontroller import SteamController, SCButtons from steamcontroller.events import EventMapper, Pos From 1570cb1350aae66a12dd145533240aef3a6eb8f8 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 21 Jan 2017 12:57:13 -0500 Subject: [PATCH 003/104] scripts/sc-configurable.py: Tabs and whitespace! --- scripts/sc-configurable.py | 116 +++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 57 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 92febe4..ee7f246 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -34,72 +34,74 @@ import gc def evminit(): - evm = EventMapper() - evm.setPadMouse(Pos.RIGHT) - evm.setPadScroll(Pos.LEFT) - evm.setStickButtons([Keys.KEY_UP, - Keys.KEY_LEFT, - Keys.KEY_DOWN, - Keys.KEY_RIGHT]) + evm = EventMapper() + evm.setPadMouse(Pos.RIGHT) + evm.setPadScroll(Pos.LEFT) + evm.setStickButtons([ + Keys.KEY_UP, + Keys.KEY_LEFT, + Keys.KEY_DOWN, + Keys.KEY_RIGHT + ]) - evm.setTrigButton(Pos.LEFT, Keys.BTN_RIGHT) - evm.setTrigButton(Pos.RIGHT, Keys.BTN_LEFT) + evm.setTrigButton(Pos.LEFT, Keys.BTN_RIGHT) + evm.setTrigButton(Pos.RIGHT, Keys.BTN_LEFT) - evm.setButtonAction(SCButtons.LB, Keys.KEY_VOLUMEDOWN) - evm.setButtonAction(SCButtons.RB, Keys.KEY_VOLUMEUP) + evm.setButtonAction(SCButtons.LB, Keys.KEY_VOLUMEDOWN) + evm.setButtonAction(SCButtons.RB, Keys.KEY_VOLUMEUP) - evm.setButtonAction(SCButtons.STEAM, Keys.KEY_HOMEPAGE) + evm.setButtonAction(SCButtons.STEAM, Keys.KEY_HOMEPAGE) - evm.setButtonAction(SCButtons.A, Keys.KEY_ENTER) - evm.setButtonAction(SCButtons.B, Keys.KEY_BACKSPACE) - evm.setButtonAction(SCButtons.X, Keys.KEY_ESC) - evm.setButtonAction(SCButtons.Y, Keys.KEY_PLAYPAUSE) + evm.setButtonAction(SCButtons.A, Keys.KEY_ENTER) + evm.setButtonAction(SCButtons.B, Keys.KEY_BACKSPACE) + evm.setButtonAction(SCButtons.X, Keys.KEY_ESC) + evm.setButtonAction(SCButtons.Y, Keys.KEY_PLAYPAUSE) - evm.setButtonAction(SCButtons.START, Keys.KEY_NEXTSONG) - evm.setButtonAction(SCButtons.BACK, Keys.KEY_PREVIOUSSONG) + evm.setButtonAction(SCButtons.START, Keys.KEY_NEXTSONG) + evm.setButtonAction(SCButtons.BACK, Keys.KEY_PREVIOUSSONG) - evm.setButtonAction(SCButtons.LGRIP, Keys.KEY_BACK) - evm.setButtonAction(SCButtons.RGRIP, Keys.KEY_FORWARD) + evm.setButtonAction(SCButtons.LGRIP, Keys.KEY_BACK) + evm.setButtonAction(SCButtons.RGRIP, Keys.KEY_FORWARD) - evm.setButtonAction(SCButtons.LPAD, Keys.BTN_MIDDLE) - evm.setButtonAction(SCButtons.RPAD, Keys.KEY_SPACE) + evm.setButtonAction(SCButtons.LPAD, Keys.BTN_MIDDLE) + evm.setButtonAction(SCButtons.RPAD, Keys.KEY_SPACE) - return evm + return evm class SCDaemon(Daemon): - def run(self): - evm = evminit() - sc = SteamController(callback=evm.process) - sc.run() - del sc - del evm - gc.collect() + def run(self): + evm = evminit() + sc = SteamController(callback=evm.process) + sc.run() + del sc + del evm + gc.collect() if __name__ == '__main__': - import argparse - - def _main(): - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument('command', type=str, choices=['start', 'stop', 'restart', 'debug']) - parser.add_argument('-i', '--index', type=int, choices=[0,1,2,3], default=None) - args = parser.parse_args() - if args.index != None: - daemon = SCDaemon('/tmp/steamcontroller{:d}.pid'.format(args.index)) - else: - daemon = SCDaemon('/tmp/steamcontroller.pid') - - if 'start' == args.command: - daemon.start() - elif 'stop' == args.command: - daemon.stop() - elif 'restart' == args.command: - daemon.restart() - elif 'debug' == args.command: - try: - evm = evminit() - sc = SteamController(callback=evm.process) - sc.run() - except KeyboardInterrupt: - return - - _main() + import argparse + + def _main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('command', type=str, choices=['start', 'stop', 'restart', 'debug']) + parser.add_argument('-i', '--index', type=int, choices=[0,1,2,3], default=None) + args = parser.parse_args() + if args.index != None: + daemon = SCDaemon('/tmp/steamcontroller{:d}.pid'.format(args.index)) + else: + daemon = SCDaemon('/tmp/steamcontroller.pid') + + if 'start' == args.command: + daemon.start() + elif 'stop' == args.command: + daemon.stop() + elif 'restart' == args.command: + daemon.restart() + elif 'debug' == args.command: + try: + evm = evminit() + sc = SteamController(callback=evm.process) + sc.run() + except KeyboardInterrupt: + return + + _main() From f681c730bc869f2fee2e2e7de64a913adc0a6327 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 21 Jan 2017 14:06:55 -0500 Subject: [PATCH 004/104] scripts/vdf2json.py: Added "json" package import, join_duplicate_keys() function, and vdf2sensible_json() function --- scripts/vdf2json.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/scripts/vdf2json.py b/scripts/vdf2json.py index 9ccff6d..94f74e9 100755 --- a/scripts/vdf2json.py +++ b/scripts/vdf2json.py @@ -22,8 +22,25 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. +import json from shlex import shlex +def join_duplicate_keys(ordered_pairs): # {{{ + d = {} + for k, v in ordered_pairs: + if k in d: + if(type(d[k]) == list): + d[k].append(v) + else: + newlist = [] + newlist.append(d[k]) + newlist.append(v) + d[k] = newlist + else: + d[k] = v + return d +# }}} + def vdf2json(stream): """ @@ -61,6 +78,18 @@ def _istr(ident, string): if ntok != '}': jbuf += ',' jbuf += '\n' + +def vdf2sensible_json(stream): + # Since /controller_mappings/group is a key duplicated numerous times, it + # makes it cumbersome to use. This changes /controller_mappings/group + # to be a single-use key with a dict in it; each object in the dict is a + # one of these separate "group" objects, and the keys to the dict are + # the "id" fields of these objects. + + obj = json.loads(vdf2json(stream), object_pairs_hook = join_duplicate_keys) + obj['controller_mappings']['group'] = {group['id'] : group for group in obj['controller_mappings']['group']} + return json.dumps(obj) + def main(): """ Read Steam vdf and write json compatible conversion From fe0b289b096c68d8cb6022d0e7a824e9b0c676ea Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 21 Jan 2017 14:19:20 -0500 Subject: [PATCH 005/104] Revert "scripts/vdf2json.py: Added "json" package import, join_duplicate_keys() function, and vdf2sensible_json() function" This reverts commit f681c730bc869f2fee2e2e7de64a913adc0a6327. --- scripts/vdf2json.py | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/scripts/vdf2json.py b/scripts/vdf2json.py index 94f74e9..9ccff6d 100755 --- a/scripts/vdf2json.py +++ b/scripts/vdf2json.py @@ -22,25 +22,8 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -import json from shlex import shlex -def join_duplicate_keys(ordered_pairs): # {{{ - d = {} - for k, v in ordered_pairs: - if k in d: - if(type(d[k]) == list): - d[k].append(v) - else: - newlist = [] - newlist.append(d[k]) - newlist.append(v) - d[k] = newlist - else: - d[k] = v - return d -# }}} - def vdf2json(stream): """ @@ -78,18 +61,6 @@ def _istr(ident, string): if ntok != '}': jbuf += ',' jbuf += '\n' - -def vdf2sensible_json(stream): - # Since /controller_mappings/group is a key duplicated numerous times, it - # makes it cumbersome to use. This changes /controller_mappings/group - # to be a single-use key with a dict in it; each object in the dict is a - # one of these separate "group" objects, and the keys to the dict are - # the "id" fields of these objects. - - obj = json.loads(vdf2json(stream), object_pairs_hook = join_duplicate_keys) - obj['controller_mappings']['group'] = {group['id'] : group for group in obj['controller_mappings']['group']} - return json.dumps(obj) - def main(): """ Read Steam vdf and write json compatible conversion From a4c43f6866370e387afa7724d5e2d9e14625e1b3 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 21 Jan 2017 14:20:25 -0500 Subject: [PATCH 006/104] scripts/sc-configurable.py: Added json and vdf2json imports, along with join_duplicate_keys() and load_vdf() functions --- scripts/sc-configurable.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index ee7f246..5d6d784 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -32,6 +32,39 @@ from steamcontroller.daemon import Daemon import gc +import json + +import vdf2json + +def join_duplicate_keys(ordered_pairs): # {{{ + d = {} + for k, v in ordered_pairs: + if k in d: + if(type(d[k]) == list): + d[k].append(v) + else: + newlist = [] + newlist.append(d[k]) + newlist.append(v) + d[k] = newlist + else: + d[k] = v + return d +# }}} + +def load_vdf(path): # {{{ + f = open(path, 'r') + obj = json.loads(vdf2json.vdf2json(f), object_pairs_hook = join_duplicate_keys) + + # Since /controller_mappings/group is a key duplicated numerous times, it + # makes it cumbersome to use. This changes /controller_mappings/group + # to be a single-use key with a dict in it; each object in the dict is a + # one of these separate "group" objects, and the keys to the dict are + # the "id" fields of these objects. + obj['controller_mappings']['group'] = {group['id'] : group for group in obj['controller_mappings']['group']} + + return obj +# }}} def evminit(): evm = EventMapper() From 558619324592f13535d3d80de039f00590d71295 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 21 Jan 2017 14:24:11 -0500 Subject: [PATCH 007/104] scripts/sc-configurable.py: Added -c/--config-file argument (required), which specifies the .vdf file to load --- scripts/sc-configurable.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 5d6d784..0464dfd 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -116,8 +116,12 @@ def run(self): def _main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('command', type=str, choices=['start', 'stop', 'restart', 'debug']) + parser.add_argument('-c', '--config-file', type = str, required = True) parser.add_argument('-i', '--index', type=int, choices=[0,1,2,3], default=None) args = parser.parse_args() + + config = load_vdf(args.config_file) + if args.index != None: daemon = SCDaemon('/tmp/steamcontroller{:d}.pid'.format(args.index)) else: From 0bf9d02e7dd54cd24354af32411959f21009ee70 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 21 Jan 2017 14:27:28 -0500 Subject: [PATCH 008/104] scripts/sc-configurable.py: More spaces! --- scripts/sc-configurable.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 0464dfd..e272212 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -114,10 +114,10 @@ def run(self): import argparse def _main(): - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument('command', type=str, choices=['start', 'stop', 'restart', 'debug']) + parser = argparse.ArgumentParser(description = __doc__) + parser.add_argument('command', type = str, choices = ['start', 'stop', 'restart', 'debug']) parser.add_argument('-c', '--config-file', type = str, required = True) - parser.add_argument('-i', '--index', type=int, choices=[0,1,2,3], default=None) + parser.add_argument('-i', '--index', type = int, choices = [0,1,2,3], default = None) args = parser.parse_args() config = load_vdf(args.config_file) From 2f2e42fbbcfe5a92be670902793dcce2ed0f5309 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 21 Jan 2017 14:32:18 -0500 Subject: [PATCH 009/104] scripts/sc-configurable.py: Moved load_vdf() call into evminit() --- scripts/sc-configurable.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index e272212..c072a2d 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -66,8 +66,10 @@ def load_vdf(path): # {{{ return obj # }}} -def evminit(): +def evminit(config_file_path): evm = EventMapper() + config = load_vdf(config_file_path) + evm.setPadMouse(Pos.RIGHT) evm.setPadScroll(Pos.LEFT) evm.setStickButtons([ @@ -102,8 +104,12 @@ def evminit(): return evm class SCDaemon(Daemon): + def __init__(self, pidfile, config_file): + self.pidfile = pidfile + self.config_file = config_file + def run(self): - evm = evminit() + evm = evminit(self.config_file) sc = SteamController(callback=evm.process) sc.run() del sc @@ -120,12 +126,10 @@ def _main(): parser.add_argument('-i', '--index', type = int, choices = [0,1,2,3], default = None) args = parser.parse_args() - config = load_vdf(args.config_file) - if args.index != None: - daemon = SCDaemon('/tmp/steamcontroller{:d}.pid'.format(args.index)) + daemon = SCDaemon('/tmp/steamcontroller{:d}.pid'.format(args.index), args.config_file) else: - daemon = SCDaemon('/tmp/steamcontroller.pid') + daemon = SCDaemon('/tmp/steamcontroller.pid', args.config_file) if 'start' == args.command: daemon.start() @@ -135,7 +139,7 @@ def _main(): daemon.restart() elif 'debug' == args.command: try: - evm = evminit() + evm = evminit(args.config_file) sc = SteamController(callback=evm.process) sc.run() except KeyboardInterrupt: From f5f3c6638925f6d39e6b4663f34b8c95d9b85d14 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 21 Jan 2017 14:32:37 -0500 Subject: [PATCH 010/104] scripts/sc-configurable.py: Use python3 instead of python --- scripts/sc-configurable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index c072a2d..f72d7c5 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # The MIT License (MIT) # From 47c24809ea72d2242db93a8f02b11da71200180c Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 21 Jan 2017 17:11:22 -0500 Subject: [PATCH 011/104] scripts/sc-configurable.py: Flip /controller_mappings/preset/group_source_bindings keys with values in load_vdf() --- scripts/sc-configurable.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index f72d7c5..9cd5d16 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -63,6 +63,9 @@ def load_vdf(path): # {{{ # the "id" fields of these objects. obj['controller_mappings']['group'] = {group['id'] : group for group in obj['controller_mappings']['group']} + # ID -> binding doesn't really do us any good. Flip it. + obj['controller_mappings']['preset']['group_source_bindings'] = {value : key for key, value in obj['controller_mappings']['preset']['group_source_bindings'].items()} + return obj # }}} From 7907cb2a3635cc37bbf7f17acb22dea7421dae7e Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 11:17:52 -0500 Subject: [PATCH 012/104] scripts/sc-configurable.py: Added get_binding() --- scripts/sc-configurable.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 9cd5d16..a845f96 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -69,6 +69,10 @@ def load_vdf(path): # {{{ return obj # }}} +def get_binding(group_inputs, input_name, activator): # {{{ + return group_inputs[input_name]['activators'][activator]['bindings']['binding'] +# }}} + def evminit(config_file_path): evm = EventMapper() config = load_vdf(config_file_path) From 30caa9b830f8130bb3568cfff9f011d990892c37 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 11:35:51 -0500 Subject: [PATCH 013/104] scripts/sc-configurable.py: get_binding() now returns the correct enum item, rather than just the binding dict entry --- scripts/sc-configurable.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index a845f96..5135b78 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -70,7 +70,11 @@ def load_vdf(path): # {{{ # }}} def get_binding(group_inputs, input_name, activator): # {{{ - return group_inputs[input_name]['activators'][activator]['bindings']['binding'] + binding = group_inputs[input_name]['activators'][activator]['bindings']['binding'].split() + + # TODO: mouse_wheel, mouse_button, mode_shift ... more? + if(binding[0] == 'key_press'): + return Keys.getattr('KEY_' + binding[1]) # }}} def evminit(config_file_path): From 44273b38fb223ceb8f803f616de67fb686702152 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 12:00:08 -0500 Subject: [PATCH 014/104] scripts/sc-configurable.py: evminit(): Added config support for button diamond --- scripts/sc-configurable.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 5135b78..4c311a0 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -81,6 +81,11 @@ def evminit(config_file_path): evm = EventMapper() config = load_vdf(config_file_path) + groups = config['controller_mappings']['group'] + bindings = config['controller_mappings']['preset']['group_source_bindings'] + + # TODO: Check/respect "mode" entry in each group + evm.setPadMouse(Pos.RIGHT) evm.setPadScroll(Pos.LEFT) evm.setStickButtons([ @@ -98,10 +103,13 @@ def evminit(config_file_path): evm.setButtonAction(SCButtons.STEAM, Keys.KEY_HOMEPAGE) - evm.setButtonAction(SCButtons.A, Keys.KEY_ENTER) - evm.setButtonAction(SCButtons.B, Keys.KEY_BACKSPACE) - evm.setButtonAction(SCButtons.X, Keys.KEY_ESC) - evm.setButtonAction(SCButtons.Y, Keys.KEY_PLAYPAUSE) + if('button_diamond active' in bindings): + group_id = bindings['button_diamond active'] + inputs = groups[group_id]['inputs'] + evm.setButtonAction(SCButtons.A, get_binding(inputs, 'button_a', 'Full_Press')) + evm.setButtonAction(SCButtons.B, get_binding(inputs, 'button_b', 'Full_Press')) + evm.setButtonAction(SCButtons.X, get_binding(inputs, 'button_x', 'Full_Press')) + evm.setButtonAction(SCButtons.Y, get_binding(inputs, 'button_y', 'Full_Press')) evm.setButtonAction(SCButtons.START, Keys.KEY_NEXTSONG) evm.setButtonAction(SCButtons.BACK, Keys.KEY_PREVIOUSSONG) From b155a22630dcad99adc5bc6d5ff4a92cced5d4a8 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 12:13:02 -0500 Subject: [PATCH 015/104] scripts/sc-configurable.py: evminit(): Added config support for joystick --- scripts/sc-configurable.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 4c311a0..a3bc508 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -84,16 +84,22 @@ def evminit(config_file_path): groups = config['controller_mappings']['group'] bindings = config['controller_mappings']['preset']['group_source_bindings'] - # TODO: Check/respect "mode" entry in each group + # TODO: Check/respect all possible "mode" entries in each group evm.setPadMouse(Pos.RIGHT) evm.setPadScroll(Pos.LEFT) - evm.setStickButtons([ - Keys.KEY_UP, - Keys.KEY_LEFT, - Keys.KEY_DOWN, - Keys.KEY_RIGHT - ]) + + if('joystick active' in bindings): + group_id = bindings['joystick active'] + group = groups[group_id] + inputs = group['inputs'] + if(group['mode'] == 'dpad'): + evm.setStickButtons([ + get_binding(inputs, 'dpad_north', 'Full_Press'), + get_binding(inputs, 'dpad_west', 'Full_Press'), + get_binding(inputs, 'dpad_south', 'Full_Press'), + get_binding(inputs, 'dpad_east', 'Full_Press') + ]) evm.setTrigButton(Pos.LEFT, Keys.BTN_RIGHT) evm.setTrigButton(Pos.RIGHT, Keys.BTN_LEFT) From 8b1783dcdfa9c1bf0daf3dc7d56cb4a43159e57c Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 12:47:36 -0500 Subject: [PATCH 016/104] scripts/sc-configurable.py: evminit(): Added config support for right trackpad (in mouse mode only) --- scripts/sc-configurable.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index a3bc508..803aea7 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -86,7 +86,19 @@ def evminit(config_file_path): # TODO: Check/respect all possible "mode" entries in each group - evm.setPadMouse(Pos.RIGHT) + if('right_trackpad active' in bindings): + group_id = bindings['right_trackpad active'] + group = groups[group_id] + # TODO: scrollwheel, dpad modes + if(group['mode'] == 'absolute_mouse'): + evm.setPadMouse(Pos.RIGHT) + try: + # TODO: Validate + evm.setButtonAction(SCbuttons.RPAD, get_binding(group['inputs'], 'click', 'Full_Press') + except: + # No click action set + pass + evm.setPadScroll(Pos.LEFT) if('joystick active' in bindings): From d4fa64697822d921ba6b74768d5a9585a25b872d Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 13:00:11 -0500 Subject: [PATCH 017/104] scripts/sc-configurable.py: Moved trackpad setup to its own function, set_trackpad_config() --- scripts/sc-configurable.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 803aea7..346239e 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -77,6 +77,18 @@ def get_binding(group_inputs, input_name, activator): # {{{ return Keys.getattr('KEY_' + binding[1]) # }}} +def set_trackpad_config(evm, pos, group): # {{{ + button = SCButtons.RPAD if pos == Pos.RIGHT else SCButtons.LPAD + if(group['mode'] == 'absolute_mouse'): + evm.setPadMouse(pos) + try: + # TODO: Validate + evm.setButtonAction(button, get_binding(group['inputs'], 'click', 'Full_Press') + except: + # No click action set + pass +# }}} + def evminit(config_file_path): evm = EventMapper() config = load_vdf(config_file_path) @@ -88,16 +100,7 @@ def evminit(config_file_path): if('right_trackpad active' in bindings): group_id = bindings['right_trackpad active'] - group = groups[group_id] - # TODO: scrollwheel, dpad modes - if(group['mode'] == 'absolute_mouse'): - evm.setPadMouse(Pos.RIGHT) - try: - # TODO: Validate - evm.setButtonAction(SCbuttons.RPAD, get_binding(group['inputs'], 'click', 'Full_Press') - except: - # No click action set - pass + set_trackpad_config(evm, Pos.RIGHT, groups[group_id]) evm.setPadScroll(Pos.LEFT) From c4644f538689b0d3ce2f5883c7404b01f834ff66 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 13:01:53 -0500 Subject: [PATCH 018/104] scripts/sc-configurable.py: set_trackpad_config(): Fixed syntax --- scripts/sc-configurable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 346239e..f1e7cf7 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -83,7 +83,7 @@ def set_trackpad_config(evm, pos, group): # {{{ evm.setPadMouse(pos) try: # TODO: Validate - evm.setButtonAction(button, get_binding(group['inputs'], 'click', 'Full_Press') + evm.setButtonAction(button, get_binding(group['inputs'], 'click', 'Full_Press')) except: # No click action set pass From 5b7dee3e0ee9b40e0df4d6e9ec072ec5c2c1d005 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 13:02:25 -0500 Subject: [PATCH 019/104] scripts/sc-configurable.py: get_binding(): getattr() -> __getattr__() --- scripts/sc-configurable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index f1e7cf7..8de70fe 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -74,7 +74,7 @@ def get_binding(group_inputs, input_name, activator): # {{{ # TODO: mouse_wheel, mouse_button, mode_shift ... more? if(binding[0] == 'key_press'): - return Keys.getattr('KEY_' + binding[1]) + return Keys.__getattr__('KEY_' + binding[1]) # }}} def set_trackpad_config(evm, pos, group): # {{{ From 0c7e415e8a38792af5913018525d5f86436c8fed Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 13:03:46 -0500 Subject: [PATCH 020/104] scripts/sc-configurable.py: set_trackpad_config(): Put back missing TODO --- scripts/sc-configurable.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 8de70fe..c445bb3 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -79,6 +79,7 @@ def get_binding(group_inputs, input_name, activator): # {{{ def set_trackpad_config(evm, pos, group): # {{{ button = SCButtons.RPAD if pos == Pos.RIGHT else SCButtons.LPAD + # TODO: scrollwheel, dpad modes if(group['mode'] == 'absolute_mouse'): evm.setPadMouse(pos) try: From 9024cfa02a544543a90ad0c93ec1ec150b9a38a2 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 13:21:42 -0500 Subject: [PATCH 021/104] scripts/sc-configurable.py: set_trackpad_config(): Added mostly-complete scrollwheel support --- scripts/sc-configurable.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index c445bb3..caa992c 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -79,7 +79,7 @@ def get_binding(group_inputs, input_name, activator): # {{{ def set_trackpad_config(evm, pos, group): # {{{ button = SCButtons.RPAD if pos == Pos.RIGHT else SCButtons.LPAD - # TODO: scrollwheel, dpad modes + # TODO: dpad modes if(group['mode'] == 'absolute_mouse'): evm.setPadMouse(pos) try: @@ -88,6 +88,15 @@ def set_trackpad_config(evm, pos, group): # {{{ except: # No click action set pass + elif(group['mode'] == 'scrollwheel'): + # TODO: Support configuration for scroll directions + evm.setPadScroll(pos) + try: + # TODO: Validate + evm.setButtonAction(button, get_binding(group['inputs'], 'click', 'Full_Press')) + except: + # No click action set + pass # }}} def evminit(config_file_path): From 3ac8d86b6984cb66f9a4ce3c4738f4e44cbffffa Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 13:23:46 -0500 Subject: [PATCH 022/104] scripts/sc-configurable.py: get_binding(): Added try/except block --- scripts/sc-configurable.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index caa992c..6f7da3c 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -70,7 +70,10 @@ def load_vdf(path): # {{{ # }}} def get_binding(group_inputs, input_name, activator): # {{{ - binding = group_inputs[input_name]['activators'][activator]['bindings']['binding'].split() + try: + binding = group_inputs[input_name]['activators'][activator]['bindings']['binding'].split() + except KeyError: + return None # TODO: mouse_wheel, mouse_button, mode_shift ... more? if(binding[0] == 'key_press'): From debe38cbee48e0adb9183bfade7a618f5d3ee98a Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 13:24:22 -0500 Subject: [PATCH 023/104] scripts/sc-configurable.py: get_binding(): Added fallback return None --- scripts/sc-configurable.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 6f7da3c..ac56287 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -78,6 +78,8 @@ def get_binding(group_inputs, input_name, activator): # {{{ # TODO: mouse_wheel, mouse_button, mode_shift ... more? if(binding[0] == 'key_press'): return Keys.__getattr__('KEY_' + binding[1]) + + return None # }}} def set_trackpad_config(evm, pos, group): # {{{ From 68882614892db44a3080b71dad72868cee104db3 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 13:25:43 -0500 Subject: [PATCH 024/104] scripts/sc-configurable.py: set_trackpad_config(): Now that get_binding() will return null on failure, took out try/except blocks --- scripts/sc-configurable.py | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index ac56287..b3f082d 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -87,21 +87,11 @@ def set_trackpad_config(evm, pos, group): # {{{ # TODO: dpad modes if(group['mode'] == 'absolute_mouse'): evm.setPadMouse(pos) - try: - # TODO: Validate - evm.setButtonAction(button, get_binding(group['inputs'], 'click', 'Full_Press')) - except: - # No click action set - pass + evm.setButtonAction(button, get_binding(group['inputs'], 'click', 'Full_Press')) elif(group['mode'] == 'scrollwheel'): # TODO: Support configuration for scroll directions evm.setPadScroll(pos) - try: - # TODO: Validate - evm.setButtonAction(button, get_binding(group['inputs'], 'click', 'Full_Press')) - except: - # No click action set - pass + evm.setButtonAction(button, get_binding(group['inputs'], 'click', 'Full_Press')) # }}} def evminit(config_file_path): From f3a020419e2193e5a14be7775035acf8e6afbe3b Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 13:52:26 -0500 Subject: [PATCH 025/104] scripts/sc-configurable.py: set_trackpad_config(): Added support for dpad mode --- scripts/sc-configurable.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index b3f082d..34c8c63 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -84,7 +84,6 @@ def get_binding(group_inputs, input_name, activator): # {{{ def set_trackpad_config(evm, pos, group): # {{{ button = SCButtons.RPAD if pos == Pos.RIGHT else SCButtons.LPAD - # TODO: dpad modes if(group['mode'] == 'absolute_mouse'): evm.setPadMouse(pos) evm.setButtonAction(button, get_binding(group['inputs'], 'click', 'Full_Press')) @@ -92,6 +91,15 @@ def set_trackpad_config(evm, pos, group): # {{{ # TODO: Support configuration for scroll directions evm.setPadScroll(pos) evm.setButtonAction(button, get_binding(group['inputs'], 'click', 'Full_Press')) + elif(group['mode'] == 'dpad'): + inputs = group['inputs'] + # TODO: Configurable whether or not click is required? + evm.setPadButtons(pos, [ + get_binding(inputs, 'dpad_north', 'Full_Press'), + get_binding(inputs, 'dpad_west', 'Full_Press'), + get_binding(inputs, 'dpad_south', 'Full_Press'), + get_binding(inputs, 'dpad_east', 'Full_Press') + ], clicked = True) # }}} def evminit(config_file_path): From 9099deb41e100e5fb83339038ca0dea04d75b912 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 13:56:14 -0500 Subject: [PATCH 026/104] scripts/sc-configurable.py: evminit(): Added config support for left trackpad --- scripts/sc-configurable.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 34c8c63..20c1161 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -115,7 +115,9 @@ def evminit(config_file_path): group_id = bindings['right_trackpad active'] set_trackpad_config(evm, Pos.RIGHT, groups[group_id]) - evm.setPadScroll(Pos.LEFT) + if('left_trackpad active' in bindings): + group_id = bindings['left_trackpad active'] + set_trackpad_config(evm, Pos.LEFT, groups[group_id]) if('joystick active' in bindings): group_id = bindings['joystick active'] From d0922a85f1d9c0571ed6fa3439021ffc4445b7ba Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 14:02:15 -0500 Subject: [PATCH 027/104] scripts/sc-configurable.py: get_binding(): Added translation for arrow key key_press bindings --- scripts/sc-configurable.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 20c1161..f7e519a 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -77,6 +77,8 @@ def get_binding(group_inputs, input_name, activator): # {{{ # TODO: mouse_wheel, mouse_button, mode_shift ... more? if(binding[0] == 'key_press'): + # Ugly + binding[1] = binding[1].replace('_ARROW', '') return Keys.__getattr__('KEY_' + binding[1]) return None From 38ad47692ff866353ff5481806abb17619967e14 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 14:02:59 -0500 Subject: [PATCH 028/104] scripts/sc-configurable.py: get_binding(): Added translation which simply removes underscores from key_press bindings; this fixes shift keys, may fix other things --- scripts/sc-configurable.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index f7e519a..33b7596 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -79,6 +79,7 @@ def get_binding(group_inputs, input_name, activator): # {{{ if(binding[0] == 'key_press'): # Ugly binding[1] = binding[1].replace('_ARROW', '') + binding[1] = binding[1].replace('_', '') return Keys.__getattr__('KEY_' + binding[1]) return None From d607f07759411e5b0723076eac3cc6217e67bfce Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 14:10:57 -0500 Subject: [PATCH 029/104] scripts/sc-configurable.py: get_binding(): Fixed comma issues --- scripts/sc-configurable.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 33b7596..788f6a5 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -80,6 +80,7 @@ def get_binding(group_inputs, input_name, activator): # {{{ # Ugly binding[1] = binding[1].replace('_ARROW', '') binding[1] = binding[1].replace('_', '') + binding[1] = binding[1].replace(',', '') # Items such as "key_press W, w"; everything after the comma is already trimmed by split() above, ignore trailing items for now' return Keys.__getattr__('KEY_' + binding[1]) return None From 2ca7001fa0c75f8482295b3d1b76812afb76bd90 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 14:13:48 -0500 Subject: [PATCH 030/104] scripts/sc-configurable.py: get_binding(): Added mouse_wheel stub entry --- scripts/sc-configurable.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 788f6a5..810423f 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -75,13 +75,16 @@ def get_binding(group_inputs, input_name, activator): # {{{ except KeyError: return None - # TODO: mouse_wheel, mouse_button, mode_shift ... more? + # TODO: mouse_button, mode_shift ... more? if(binding[0] == 'key_press'): # Ugly binding[1] = binding[1].replace('_ARROW', '') binding[1] = binding[1].replace('_', '') binding[1] = binding[1].replace(',', '') # Items such as "key_press W, w"; everything after the comma is already trimmed by split() above, ignore trailing items for now' return Keys.__getattr__('KEY_' + binding[1]) + elif(binding[0] == 'mouse_wheel'): + # TODO: Figure out if we actually need this; if so, add support + return None return None # }}} From da3b39da21fa134e639eede6db819d299caef2de Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 14:15:08 -0500 Subject: [PATCH 031/104] scripts/sc-configurable.py: get_binding(): Added mouse_button support --- scripts/sc-configurable.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 810423f..6b21b44 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -75,7 +75,7 @@ def get_binding(group_inputs, input_name, activator): # {{{ except KeyError: return None - # TODO: mouse_button, mode_shift ... more? + # TODO: mode_shift ... maybe more? if(binding[0] == 'key_press'): # Ugly binding[1] = binding[1].replace('_ARROW', '') @@ -85,6 +85,8 @@ def get_binding(group_inputs, input_name, activator): # {{{ elif(binding[0] == 'mouse_wheel'): # TODO: Figure out if we actually need this; if so, add support return None + elif(binding[0] == 'mouse_button'): + return Keys.__getattr__('BTN_' + binding[1]) return None # }}} From b6b1796e1c85278509a8ca99910b6f8cd16f2c4b Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 14:18:41 -0500 Subject: [PATCH 032/104] scripts/sc-configurable.py: evminit(): Added config support for left and right triggers buttons --- scripts/sc-configurable.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 6b21b44..a0adcf7 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -140,8 +140,17 @@ def evminit(config_file_path): get_binding(inputs, 'dpad_east', 'Full_Press') ]) - evm.setTrigButton(Pos.LEFT, Keys.BTN_RIGHT) - evm.setTrigButton(Pos.RIGHT, Keys.BTN_LEFT) + if('left_trigger active' in bindings): + group_id = bindings['left_trigger active'] + group = groups[group_id] + if(group['mode'] == 'trigger'): + evm.setTrigButton(Pos.LEFT, get_binding(group['inputs'], 'click', 'Full_Press')) + + if('right_trigger active' in bindings): + group_id = bindings['right_trigger active'] + group = groups[group_id] + if(group['mode'] == 'trigger'): + evm.setTrigButton(Pos.RIGHT, get_binding(group['inputs'], 'click', 'Full_Press')) evm.setButtonAction(SCButtons.LB, Keys.KEY_VOLUMEDOWN) evm.setButtonAction(SCButtons.RB, Keys.KEY_VOLUMEUP) From 292ce294c75615056a258ca600a3d80d0b593d45 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 14:25:17 -0500 Subject: [PATCH 033/104] scripts/sc-configurable.py: evminit(): Added config support for bumpers, start/select, and grips --- scripts/sc-configurable.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index a0adcf7..9d05ed0 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -152,10 +152,17 @@ def evminit(config_file_path): if(group['mode'] == 'trigger'): evm.setTrigButton(Pos.RIGHT, get_binding(group['inputs'], 'click', 'Full_Press')) - evm.setButtonAction(SCButtons.LB, Keys.KEY_VOLUMEDOWN) - evm.setButtonAction(SCButtons.RB, Keys.KEY_VOLUMEUP) - - evm.setButtonAction(SCButtons.STEAM, Keys.KEY_HOMEPAGE) + if('switch active' in bindings): + group_id = bindings['switch active'] + group = groups[group_id] + if(group['mode'] == 'switches'): + inputs = group['inputs'] + evm.setButtonAction(SCButtons.LB, get_binding(inputs, 'left_bumper', 'Full_Press')) + evm.setButtonAction(SCButtons.RB, get_binding(inputs, 'right_bumper', 'Full_Press')) + evm.setButtonAction(SCButtons.START, get_binding(inputs, 'button_escape', 'Full_Press')) + evm.setButtonAction(SCButtons.BACK, get_binding(inputs, 'button_menu', 'Full_Press')) + evm.setButtonAction(SCButtons.LGRIP, get_binding(inputs, 'button_back_left', 'Full_Press')) + evm.setButtonAction(SCButtons.RGRIP, get_binding(inputs, 'button_back_right', 'Full_Press')) if('button_diamond active' in bindings): group_id = bindings['button_diamond active'] @@ -165,15 +172,11 @@ def evminit(config_file_path): evm.setButtonAction(SCButtons.X, get_binding(inputs, 'button_x', 'Full_Press')) evm.setButtonAction(SCButtons.Y, get_binding(inputs, 'button_y', 'Full_Press')) - evm.setButtonAction(SCButtons.START, Keys.KEY_NEXTSONG) - evm.setButtonAction(SCButtons.BACK, Keys.KEY_PREVIOUSSONG) - - evm.setButtonAction(SCButtons.LGRIP, Keys.KEY_BACK) - evm.setButtonAction(SCButtons.RGRIP, Keys.KEY_FORWARD) - evm.setButtonAction(SCButtons.LPAD, Keys.BTN_MIDDLE) evm.setButtonAction(SCButtons.RPAD, Keys.KEY_SPACE) + evm.setButtonAction(SCButtons.STEAM, Keys.KEY_HOMEPAGE) + return evm class SCDaemon(Daemon): From 0539397730629f644df4e650ef1c63138b079e12 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 14:25:59 -0500 Subject: [PATCH 034/104] scripts/sc-configurable.py: evminit(): Took out LPAD/RPAD lines, they were superseded by set_trackpad_config() --- scripts/sc-configurable.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 9d05ed0..bb6dee5 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -172,9 +172,6 @@ def evminit(config_file_path): evm.setButtonAction(SCButtons.X, get_binding(inputs, 'button_x', 'Full_Press')) evm.setButtonAction(SCButtons.Y, get_binding(inputs, 'button_y', 'Full_Press')) - evm.setButtonAction(SCButtons.LPAD, Keys.BTN_MIDDLE) - evm.setButtonAction(SCButtons.RPAD, Keys.KEY_SPACE) - evm.setButtonAction(SCButtons.STEAM, Keys.KEY_HOMEPAGE) return evm From a7fc654302e7d6daadcfadab62acf3c5ccbd0d7b Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 14:27:36 -0500 Subject: [PATCH 035/104] scripts/sc-configurable.py: evminit(): Moved assignments around --- scripts/sc-configurable.py | 44 +++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index bb6dee5..df0be31 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -120,14 +120,14 @@ def evminit(config_file_path): # TODO: Check/respect all possible "mode" entries in each group - if('right_trackpad active' in bindings): - group_id = bindings['right_trackpad active'] - set_trackpad_config(evm, Pos.RIGHT, groups[group_id]) - if('left_trackpad active' in bindings): group_id = bindings['left_trackpad active'] set_trackpad_config(evm, Pos.LEFT, groups[group_id]) + if('right_trackpad active' in bindings): + group_id = bindings['right_trackpad active'] + set_trackpad_config(evm, Pos.RIGHT, groups[group_id]) + if('joystick active' in bindings): group_id = bindings['joystick active'] group = groups[group_id] @@ -140,17 +140,13 @@ def evminit(config_file_path): get_binding(inputs, 'dpad_east', 'Full_Press') ]) - if('left_trigger active' in bindings): - group_id = bindings['left_trigger active'] - group = groups[group_id] - if(group['mode'] == 'trigger'): - evm.setTrigButton(Pos.LEFT, get_binding(group['inputs'], 'click', 'Full_Press')) - - if('right_trigger active' in bindings): - group_id = bindings['right_trigger active'] - group = groups[group_id] - if(group['mode'] == 'trigger'): - evm.setTrigButton(Pos.RIGHT, get_binding(group['inputs'], 'click', 'Full_Press')) + if('button_diamond active' in bindings): + group_id = bindings['button_diamond active'] + inputs = groups[group_id]['inputs'] + evm.setButtonAction(SCButtons.A, get_binding(inputs, 'button_a', 'Full_Press')) + evm.setButtonAction(SCButtons.B, get_binding(inputs, 'button_b', 'Full_Press')) + evm.setButtonAction(SCButtons.X, get_binding(inputs, 'button_x', 'Full_Press')) + evm.setButtonAction(SCButtons.Y, get_binding(inputs, 'button_y', 'Full_Press')) if('switch active' in bindings): group_id = bindings['switch active'] @@ -164,13 +160,17 @@ def evminit(config_file_path): evm.setButtonAction(SCButtons.LGRIP, get_binding(inputs, 'button_back_left', 'Full_Press')) evm.setButtonAction(SCButtons.RGRIP, get_binding(inputs, 'button_back_right', 'Full_Press')) - if('button_diamond active' in bindings): - group_id = bindings['button_diamond active'] - inputs = groups[group_id]['inputs'] - evm.setButtonAction(SCButtons.A, get_binding(inputs, 'button_a', 'Full_Press')) - evm.setButtonAction(SCButtons.B, get_binding(inputs, 'button_b', 'Full_Press')) - evm.setButtonAction(SCButtons.X, get_binding(inputs, 'button_x', 'Full_Press')) - evm.setButtonAction(SCButtons.Y, get_binding(inputs, 'button_y', 'Full_Press')) + if('left_trigger active' in bindings): + group_id = bindings['left_trigger active'] + group = groups[group_id] + if(group['mode'] == 'trigger'): + evm.setTrigButton(Pos.LEFT, get_binding(group['inputs'], 'click', 'Full_Press')) + + if('right_trigger active' in bindings): + group_id = bindings['right_trigger active'] + group = groups[group_id] + if(group['mode'] == 'trigger'): + evm.setTrigButton(Pos.RIGHT, get_binding(group['inputs'], 'click', 'Full_Press')) evm.setButtonAction(SCButtons.STEAM, Keys.KEY_HOMEPAGE) From 1c7d5471841ecfdde090298f74b0de2ad9d97e68 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 14:29:30 -0500 Subject: [PATCH 036/104] scripts/sc-configurable.py: evminit(): Added comment on steam button assignment --- scripts/sc-configurable.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index df0be31..a4354d5 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -172,6 +172,8 @@ def evminit(config_file_path): if(group['mode'] == 'trigger'): evm.setTrigButton(Pos.RIGHT, get_binding(group['inputs'], 'click', 'Full_Press')) + # This cannot be configured from the Steam UI. Should we extend that file + # to support configuring it? evm.setButtonAction(SCButtons.STEAM, Keys.KEY_HOMEPAGE) return evm From 75acc251b86e28e4a6cde3aaca080e3f7c8593e6 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 14:54:19 -0500 Subject: [PATCH 037/104] scripts/sc-configurable.py: evminit(): Added some basic logging --- scripts/sc-configurable.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index a4354d5..4e54a88 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -123,10 +123,12 @@ def evminit(config_file_path): if('left_trackpad active' in bindings): group_id = bindings['left_trackpad active'] set_trackpad_config(evm, Pos.LEFT, groups[group_id]) + print('--- Left trackpad loaded') if('right_trackpad active' in bindings): group_id = bindings['right_trackpad active'] set_trackpad_config(evm, Pos.RIGHT, groups[group_id]) + print('--- Right trackpad loaded') if('joystick active' in bindings): group_id = bindings['joystick active'] @@ -139,6 +141,7 @@ def evminit(config_file_path): get_binding(inputs, 'dpad_south', 'Full_Press'), get_binding(inputs, 'dpad_east', 'Full_Press') ]) + print('--- Joystick loaded') if('button_diamond active' in bindings): group_id = bindings['button_diamond active'] @@ -147,6 +150,7 @@ def evminit(config_file_path): evm.setButtonAction(SCButtons.B, get_binding(inputs, 'button_b', 'Full_Press')) evm.setButtonAction(SCButtons.X, get_binding(inputs, 'button_x', 'Full_Press')) evm.setButtonAction(SCButtons.Y, get_binding(inputs, 'button_y', 'Full_Press')) + print('--- Button diamond loaded') if('switch active' in bindings): group_id = bindings['switch active'] @@ -159,18 +163,21 @@ def evminit(config_file_path): evm.setButtonAction(SCButtons.BACK, get_binding(inputs, 'button_menu', 'Full_Press')) evm.setButtonAction(SCButtons.LGRIP, get_binding(inputs, 'button_back_left', 'Full_Press')) evm.setButtonAction(SCButtons.RGRIP, get_binding(inputs, 'button_back_right', 'Full_Press')) + print('--- Switches loaded') if('left_trigger active' in bindings): group_id = bindings['left_trigger active'] group = groups[group_id] if(group['mode'] == 'trigger'): evm.setTrigButton(Pos.LEFT, get_binding(group['inputs'], 'click', 'Full_Press')) + print('--- Left trigger loaded') if('right_trigger active' in bindings): group_id = bindings['right_trigger active'] group = groups[group_id] if(group['mode'] == 'trigger'): evm.setTrigButton(Pos.RIGHT, get_binding(group['inputs'], 'click', 'Full_Press')) + print('--- Right trigger loaded') # This cannot be configured from the Steam UI. Should we extend that file # to support configuring it? From 54bf61d03a54e4785c9e75a2f9d6927c0759d5d3 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 14:54:33 -0500 Subject: [PATCH 038/104] scripts/sc-configurable.py: get_binding(): Added hack around PERIOD key --- scripts/sc-configurable.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 4e54a88..71de7f3 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -81,6 +81,10 @@ def get_binding(group_inputs, input_name, activator): # {{{ binding[1] = binding[1].replace('_ARROW', '') binding[1] = binding[1].replace('_', '') binding[1] = binding[1].replace(',', '') # Items such as "key_press W, w"; everything after the comma is already trimmed by split() above, ignore trailing items for now' + + if(binding[1] == 'PERIOD'): + binding[1] = 'DOT' + return Keys.__getattr__('KEY_' + binding[1]) elif(binding[0] == 'mouse_wheel'): # TODO: Figure out if we actually need this; if so, add support From be77bd04d7f31942f524814275dc27962391457b Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 14:58:57 -0500 Subject: [PATCH 039/104] scripts/sc-configurable.py: get_binding(): Added hack for when there are duplicates of the same activator --- scripts/sc-configurable.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 71de7f3..9c3d23b 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -71,7 +71,11 @@ def load_vdf(path): # {{{ def get_binding(group_inputs, input_name, activator): # {{{ try: - binding = group_inputs[input_name]['activators'][activator]['bindings']['binding'].split() + activator = group_inputs[input_name]['activators'][activator] + if(type(activator) == list): + # TODO: Support multiples + activator = activator[0] + binding = activator['bindings']['binding'].split() except KeyError: return None From dd9e38614749ba6db6b048f4b6b795af76c174a9 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 16:50:30 -0500 Subject: [PATCH 040/104] src/events.py: setButtonAction() will clear the event if None is passed as the event, and if the button is already mapped --- src/events.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/events.py b/src/events.py index ecfdb89..b813083 100644 --- a/src/events.py +++ b/src/events.py @@ -488,6 +488,10 @@ def _keyreleased(mode, ev): def setButtonAction(self, btn, key_event): + if(key_event == None and btn in self._btn_map): + del self._btn_map[btn] + return + for mode in Modes: if self._uip[mode].keyManaged(key_event): self._btn_map[btn] = (mode, key_event) From fb81610fb3997395b5b16e671ad0f72a3263cf80 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 17:40:33 -0500 Subject: [PATCH 041/104] src/uinput.py: Added optional gamepad_definition parameter - this defaults to all the original 360 stuff, but allows us to override it --- src/uinput.py | 59 +++++++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/src/uinput.py b/src/uinput.py index 684a018..292d2be 100644 --- a/src/uinput.py +++ b/src/uinput.py @@ -366,31 +366,40 @@ class Gamepad(UInput): Gamepad uinput class, create a Xbox360 gamepad device """ - def __init__(self): - super(Gamepad, self).__init__(vendor=0x045e, - product=0x028e, - version=0x110, - name=b"Microsoft X-Box 360 pad", - keys=[Keys.BTN_START, - Keys.BTN_MODE, - Keys.BTN_SELECT, - Keys.BTN_A, - Keys.BTN_B, - Keys.BTN_X, - Keys.BTN_Y, - Keys.BTN_TL, - Keys.BTN_TR, - Keys.BTN_THUMBL, - Keys.BTN_THUMBR], - axes=[(Axes.ABS_X, -32768, 32767, 16, 128), - (Axes.ABS_Y, -32768, 32767, 16, 128), - (Axes.ABS_RX, -32768, 32767, 16, 128), - (Axes.ABS_RY, -32768, 32767, 16, 128), - (Axes.ABS_Z, 0, 255, 0, 0), - (Axes.ABS_RZ, 0, 255, 0, 0), - (Axes.ABS_HAT0X, -1, 1, 0, 0), - (Axes.ABS_HAT0Y, -1, 1, 0, 0)], - rels=[]) + def __init__(self, gamepad_definition = None): + if(gamepad_definition == None): + gamepad_definition = { + 'vendor' : 0x045e, + 'product' : 0x028e, + 'version' : 0x110, + 'name' : b"Microsoft X-Box 360 pad", + 'keys' : [ + Keys.BTN_START, + Keys.BTN_MODE, + Keys.BTN_SELECT, + Keys.BTN_A, + Keys.BTN_B, + Keys.BTN_X, + Keys.BTN_Y, + Keys.BTN_TL, + Keys.BTN_TR, + Keys.BTN_THUMBL, + Keys.BTN_THUMBR + ], + 'axes' : [ + (Axes.ABS_X, -32768, 32767, 16, 128), + (Axes.ABS_Y, -32768, 32767, 16, 128), + (Axes.ABS_RX, -32768, 32767, 16, 128), + (Axes.ABS_RY, -32768, 32767, 16, 128), + (Axes.ABS_Z, 0, 255, 0, 0), + (Axes.ABS_RZ, 0, 255, 0, 0), + (Axes.ABS_HAT0X, -1, 1, 0, 0), + (Axes.ABS_HAT0Y, -1, 1, 0, 0) + ], + 'rels' : [] + } + + super(Gamepad, self).__init__(**gamepad_definition) class Mouse(UInput): From aed1b206ef41caf01daa32e5aa69cced9b58da87 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 17:41:14 -0500 Subject: [PATCH 042/104] src/events.py: Exposed gamepad_definition parameter to Gamepad.__init__() up through EventMapper.__init__() --- src/events.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/events.py b/src/events.py index b813083..e6ea02a 100644 --- a/src/events.py +++ b/src/events.py @@ -82,9 +82,8 @@ class EventMapper(object): callback to be registered to a SteamController instance """ - def __init__(self): - - self._uip = (sui.Gamepad(), + def __init__(self, gamepad_definition = None): + self._uip = (sui.Gamepad(gamepad_defintion), sui.Keyboard(), sui.Mouse()) From 21cb84d534379ba873e135383de4a40418934df2 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 17:51:44 -0500 Subject: [PATCH 043/104] scripts/sc-configurable.py: Added thumb stick press support --- scripts/sc-configurable.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 9c3d23b..da885df 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -149,6 +149,7 @@ def evminit(config_file_path): get_binding(inputs, 'dpad_south', 'Full_Press'), get_binding(inputs, 'dpad_east', 'Full_Press') ]) + evm.setButtonAction(SCButtons.LPAD, get_binding(inputs, 'click', 'Full_Press')) print('--- Joystick loaded') if('button_diamond active' in bindings): From f1dc9e38c2e066ff4e8eaf6ebbdb1f5fff892e50 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 17:57:24 -0500 Subject: [PATCH 044/104] scripts/sc-configurable.py: Added gamepad_definition for Steam Controller, defining the buttons and axes we have available --- scripts/sc-configurable.py | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index da885df..dc05957 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -120,7 +120,39 @@ def set_trackpad_config(evm, pos, group): # {{{ # }}} def evminit(config_file_path): - evm = EventMapper() + evm = EventMapper(gamepad_definition = { + 'vendor' : 0x28de, + 'product' : 0x1142, + 'version' : 0x1, + 'name' : b"Steam Controller", + 'keys' : [ + Keys.BTN_START, + Keys.BTN_MODE, + Keys.BTN_SELECT, + Keys.BTN_A, + Keys.BTN_B, + Keys.BTN_X, + Keys.BTN_Y, + Keys.BTN_TL, + Keys.BTN_TR, + Keys.BTN_TL2, + Keys.BTN_TR2, + Keys.BTN_THUMBL, + Keys.BTN_THUMBR, + Keys.BTN_JOYSTICK + ], + 'axes' : [ + (Axes.ABS_X, -32768, 32767, 16, 128), + (Axes.ABS_Y, -32768, 32767, 16, 128), + (Axes.ABS_Z, 0, 255, 0, 0), + (Axes.ABS_RZ, 0, 255, 0, 0), + (Axes.ABS_HAT0X, -1, 1, 0, 0), + (Axes.ABS_HAT0Y, -1, 1, 0, 0) + (Axes.ABS_HAT1X, -1, 1, 0, 0), + (Axes.ABS_HAT1Y, -1, 1, 0, 0) + ], + 'rels' : [] + }) config = load_vdf(config_file_path) groups = config['controller_mappings']['group'] From a927b981692b0034371b63aa51e0e5af31f73431 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 18:00:13 -0500 Subject: [PATCH 045/104] scripts/sc-configurable.py: evminit() Added TODO --- scripts/sc-configurable.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index dc05957..3b88d17 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -120,6 +120,7 @@ def set_trackpad_config(evm, pos, group): # {{{ # }}} def evminit(config_file_path): + # TODO: Dynamic gamepad definition for keys/axes based on config evm = EventMapper(gamepad_definition = { 'vendor' : 0x28de, 'product' : 0x1142, From 3f9d6609efeb7fa5a249d7af0e0533e8ee303e53 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 18:07:15 -0500 Subject: [PATCH 046/104] scripts/sc-configurable.py: Added Axes import --- scripts/sc-configurable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 3b88d17..e2de8ee 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -27,7 +27,7 @@ from steamcontroller import SteamController, SCButtons from steamcontroller.events import EventMapper, Pos -from steamcontroller.uinput import Keys +from steamcontroller.uinput import Axes, Keys from steamcontroller.daemon import Daemon From 4497f5cbc4cd48a205aa84af34d2dc75902b62f4 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 18:08:43 -0500 Subject: [PATCH 047/104] scripts/sc-configurable.py: evminit(): Add missing comma --- scripts/sc-configurable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index e2de8ee..6cc1066 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -148,7 +148,7 @@ def evminit(config_file_path): (Axes.ABS_Z, 0, 255, 0, 0), (Axes.ABS_RZ, 0, 255, 0, 0), (Axes.ABS_HAT0X, -1, 1, 0, 0), - (Axes.ABS_HAT0Y, -1, 1, 0, 0) + (Axes.ABS_HAT0Y, -1, 1, 0, 0), (Axes.ABS_HAT1X, -1, 1, 0, 0), (Axes.ABS_HAT1Y, -1, 1, 0, 0) ], From e75831fa4a81a34de1dc335ab3d209af2e917be6 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 18:09:37 -0500 Subject: [PATCH 048/104] src/events.py: EventMapper.__init__(): Fixed typo in gamepad_definition --- src/events.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/events.py b/src/events.py index e6ea02a..efffeff 100644 --- a/src/events.py +++ b/src/events.py @@ -83,7 +83,7 @@ class EventMapper(object): """ def __init__(self, gamepad_definition = None): - self._uip = (sui.Gamepad(gamepad_defintion), + self._uip = (sui.Gamepad(gamepad_definition), sui.Keyboard(), sui.Mouse()) From 84020be851dbb3cee5b675bb49ac05558bc1300b Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 22 Jan 2017 22:52:26 -0500 Subject: [PATCH 049/104] scripts/sc-configurable.py: evminit(): Switched "keys" in gamepad_definition to Scans.keys(); no reason to limit ourselves --- scripts/sc-configurable.py | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 6cc1066..3db9054 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -27,7 +27,7 @@ from steamcontroller import SteamController, SCButtons from steamcontroller.events import EventMapper, Pos -from steamcontroller.uinput import Axes, Keys +from steamcontroller.uinput import Axes, Keys, Scans from steamcontroller.daemon import Daemon @@ -126,22 +126,7 @@ def evminit(config_file_path): 'product' : 0x1142, 'version' : 0x1, 'name' : b"Steam Controller", - 'keys' : [ - Keys.BTN_START, - Keys.BTN_MODE, - Keys.BTN_SELECT, - Keys.BTN_A, - Keys.BTN_B, - Keys.BTN_X, - Keys.BTN_Y, - Keys.BTN_TL, - Keys.BTN_TR, - Keys.BTN_TL2, - Keys.BTN_TR2, - Keys.BTN_THUMBL, - Keys.BTN_THUMBR, - Keys.BTN_JOYSTICK - ], + 'keys' : Scans.keys(), 'axes' : [ (Axes.ABS_X, -32768, 32767, 16, 128), (Axes.ABS_Y, -32768, 32767, 16, 128), From 4b2330b65bcf50286727c82659934ca35109def4 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Fri, 27 Jan 2017 23:21:57 -0500 Subject: [PATCH 050/104] scripts/sc-configurable.py: Refactored to separate reading the VDF from configuring the buttons; aside from being more maintainable, this will enable modeshifting --- scripts/sc-configurable.py | 228 ++++++++++++++++++++++++------------- 1 file changed, 148 insertions(+), 80 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 3db9054..62dd590 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -26,7 +26,7 @@ """Steam Controller VDF-configurable mode""" from steamcontroller import SteamController, SCButtons -from steamcontroller.events import EventMapper, Pos +from steamcontroller.events import EventMapper, PadModes, Pos, TrigModes from steamcontroller.uinput import Axes, Keys, Scans from steamcontroller.daemon import Daemon @@ -99,24 +99,114 @@ def get_binding(group_inputs, input_name, activator): # {{{ return None # }}} -def set_trackpad_config(evm, pos, group): # {{{ - button = SCButtons.RPAD if pos == Pos.RIGHT else SCButtons.LPAD +def parse_analog_config(group): # {{{ + config = {} if(group['mode'] == 'absolute_mouse'): - evm.setPadMouse(pos) - evm.setButtonAction(button, get_binding(group['inputs'], 'click', 'Full_Press')) + config['mode'] = PadModes.MOUSE + config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} elif(group['mode'] == 'scrollwheel'): + config['mode'] = PadModes.MOUSESCROLL + config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} + elif(group['mode'] == 'dpad'): + config['mode'] = PadModes.BUTTONCLICK + config['buttons'] = { + 'north' : get_binding(group['inputs'], 'dpad_north', 'Full_Press'), + 'west' : get_binding(group['inputs'], 'dpad_west', 'Full_Press'), + 'south' : get_binding(group['inputs'], 'dpad_south', 'Full_Press'), + 'east' : get_binding(group['inputs'], 'dpad_east', 'Full_Press') + } + return config +# }}} + +def parse_trigger_config(group): # {{{ + config = {} + if(group['mode'] == 'trigger'): + config['mode'] = TrigModes.BUTTON + config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} + return config +# }}} + +def parse_config(config): # {{{ + groups = config['controller_mappings']['group'] + bindings = config['controller_mappings']['preset']['group_source_bindings'] + + # TODO: Check/respect all possible "mode" entries in each group + + output_config = { + 'left_trackpad' : {}, + 'right_trackpad' : {}, + 'joystick' : {}, + 'button_diamond' : {}, + 'switch' : {}, + 'left_trigger' : {}, + 'right_trigger' : {} + } + + if('left_trackpad active' in bindings): + output_config['left_trackpad']['active'] = parse_analog_config(groups[bindings['left_trackpad active']]) + print('--- Left trackpad (active) loaded') + + if('right_trackpad active' in bindings): + output_config['right_trackpad']['active'] = parse_analog_config(groups[bindings['right_trackpad active']]) + print('--- Right trackpad (active) loaded') + + if('joystick active' in bindings): + output_config['joystick']['active'] = parse_analog_config(groups[bindings['joystick active']]) + print('--- Joystick (active) loaded') + + if('button_diamond active' in bindings): + inputs = groups[bindings['button_diamond active']] + output_config['button_diamond']['active'] = {'buttons' : { + 'a' : get_binding(inputs, 'button_a', 'Full_Press'), + 'b' : get_binding(inputs, 'button_b', 'Full_Press'), + 'x' : get_binding(inputs, 'button_x', 'Full_Press'), + 'y' : get_binding(inputs, 'button_y', 'Full_Press') + }} + print('--- Button diamond (active) loaded') + + if('switch active' in bindings): + inputs = groups[bindings['switch active']] + output_config['switch']['active'] = {'buttons' : { + 'left_bumper' : get_binding(inputs, 'left_bumper', 'Full_Press'), + 'right_bumper' : get_binding(inputs, 'right_bumper', 'Full_Press'), + 'start' : get_binding(inputs, 'button_escape', 'Full_Press'), + 'back' : get_binding(inputs, 'button_menu', 'Full_Press'), + 'left_grip' : get_binding(inputs, 'button_back_left', 'Full_Press'), + 'right_grip' : get_binding(inputs, 'button_back_right', 'Full_Press') + }} + print('--- Switches (active) loaded') + + if('left_trigger active' in bindings): + group_id = bindings['left_trigger active'] + output_config['left_trigger']['active'] = parse_trigger_config(groups[bindings['left_trigger active']]) + print('--- Left trigger (active) loaded') + + if('right_trigger active' in bindings): + group_id = bindings['right_trigger active'] + output_config['right_trigger']['active'] = parse_trigger_config(groups[bindings['right_trigger active']]) + print('--- Right trigger (active) loaded') + + return output_config +# }}} + +def set_trackpad_config(evm, pos, config): # {{{ + button = SCButtons.RPAD if pos == Pos.RIGHT else SCButtons.LPAD + if(config['mode'] == PadModes.MOUSE): + evm.setPadMouse(pos) + evm.setButtonAction(button, config['buttons']['click']) + elif(config['mode'] == PadModes.MOUSESCROLL): # TODO: Support configuration for scroll directions evm.setPadScroll(pos) - evm.setButtonAction(button, get_binding(group['inputs'], 'click', 'Full_Press')) - elif(group['mode'] == 'dpad'): - inputs = group['inputs'] + evm.setButtonAction(button, config['buttons']['click']) + elif(config['mode'] == PadModes.BUTTONCLICK): # TODO: Configurable whether or not click is required? - evm.setPadButtons(pos, [ - get_binding(inputs, 'dpad_north', 'Full_Press'), - get_binding(inputs, 'dpad_west', 'Full_Press'), - get_binding(inputs, 'dpad_south', 'Full_Press'), - get_binding(inputs, 'dpad_east', 'Full_Press') - ], clicked = True) + buttons = config['buttons'] + evm.setPadButtons(pos, [buttons['north'], buttons['west'], buttons['south'], buttons['east']], clicked = True) +# }}} + +def set_trigger_config(evm, pos, config): # {{{ + if(config['mode'] == TrigModes.BUTTON): + evm.setTrigButton(pos, config['buttons']['click']) # }}} def evminit(config_file_path): @@ -139,72 +229,50 @@ def evminit(config_file_path): ], 'rels' : [] }) - config = load_vdf(config_file_path) - - groups = config['controller_mappings']['group'] - bindings = config['controller_mappings']['preset']['group_source_bindings'] - - # TODO: Check/respect all possible "mode" entries in each group - - if('left_trackpad active' in bindings): - group_id = bindings['left_trackpad active'] - set_trackpad_config(evm, Pos.LEFT, groups[group_id]) - print('--- Left trackpad loaded') - - if('right_trackpad active' in bindings): - group_id = bindings['right_trackpad active'] - set_trackpad_config(evm, Pos.RIGHT, groups[group_id]) - print('--- Right trackpad loaded') - - if('joystick active' in bindings): - group_id = bindings['joystick active'] - group = groups[group_id] - inputs = group['inputs'] - if(group['mode'] == 'dpad'): - evm.setStickButtons([ - get_binding(inputs, 'dpad_north', 'Full_Press'), - get_binding(inputs, 'dpad_west', 'Full_Press'), - get_binding(inputs, 'dpad_south', 'Full_Press'), - get_binding(inputs, 'dpad_east', 'Full_Press') - ]) - evm.setButtonAction(SCButtons.LPAD, get_binding(inputs, 'click', 'Full_Press')) - print('--- Joystick loaded') - - if('button_diamond active' in bindings): - group_id = bindings['button_diamond active'] - inputs = groups[group_id]['inputs'] - evm.setButtonAction(SCButtons.A, get_binding(inputs, 'button_a', 'Full_Press')) - evm.setButtonAction(SCButtons.B, get_binding(inputs, 'button_b', 'Full_Press')) - evm.setButtonAction(SCButtons.X, get_binding(inputs, 'button_x', 'Full_Press')) - evm.setButtonAction(SCButtons.Y, get_binding(inputs, 'button_y', 'Full_Press')) - print('--- Button diamond loaded') - - if('switch active' in bindings): - group_id = bindings['switch active'] - group = groups[group_id] - if(group['mode'] == 'switches'): - inputs = group['inputs'] - evm.setButtonAction(SCButtons.LB, get_binding(inputs, 'left_bumper', 'Full_Press')) - evm.setButtonAction(SCButtons.RB, get_binding(inputs, 'right_bumper', 'Full_Press')) - evm.setButtonAction(SCButtons.START, get_binding(inputs, 'button_escape', 'Full_Press')) - evm.setButtonAction(SCButtons.BACK, get_binding(inputs, 'button_menu', 'Full_Press')) - evm.setButtonAction(SCButtons.LGRIP, get_binding(inputs, 'button_back_left', 'Full_Press')) - evm.setButtonAction(SCButtons.RGRIP, get_binding(inputs, 'button_back_right', 'Full_Press')) - print('--- Switches loaded') - - if('left_trigger active' in bindings): - group_id = bindings['left_trigger active'] - group = groups[group_id] - if(group['mode'] == 'trigger'): - evm.setTrigButton(Pos.LEFT, get_binding(group['inputs'], 'click', 'Full_Press')) - print('--- Left trigger loaded') - - if('right_trigger active' in bindings): - group_id = bindings['right_trigger active'] - group = groups[group_id] - if(group['mode'] == 'trigger'): - evm.setTrigButton(Pos.RIGHT, get_binding(group['inputs'], 'click', 'Full_Press')) - print('--- Right trigger loaded') + vdf = load_vdf(config_file_path) + config = parse_config(vdf) + + if('active' in config['left_trackpad']): + set_trackpad_config(evm, Pos.LEFT, config['left_trackpad']['active']) + print('--- Left trackpad configured') + + if('active' in config['right_trackpad']): + set_trackpad_config(evm, Pos.RIGHT, config['right_trackpad']['active']) + print('--- Right trackpad configured') + + if('active' in config['joystick']): + group = config['joystick']['active'] + if(group['mode'] == PadModes.BUTTONCLICK): + evm.setStickButtons([group['buttons']['north'], group['buttons']['west'], group['buttons']['south'], group['buttons']['east']]) + if('click' in group['buttons'] and group['buttons']['click'] != None): + evm.setActionButton(SCButtons.LPAD, group['buttons']['click']) + print('--- Joystick configured') + + if('active' in config['button_diamond']): + group = config['button_diamond']['active'] + evm.setButtonAction(SCButtons.A, group['buttons']['a']) + evm.setButtonAction(SCButtons.B, group['buttons']['b']) + evm.setButtonAction(SCButtons.X, group['buttons']['x']) + evm.setButtonAction(SCButtons.Y, group['buttons']['y']) + print('--- Button diamond configured') + + if('active' in config['switch']): + group = config['switch']['active'] + evm.setButtonAction(SCButtons.LB, group['buttons']['left_bumper']) + evm.setButtonAction(SCButtons.RB, group['buttons']['right_bumper']) + evm.setButtonAction(SCButtons.START, group['buttons']['start']) + evm.setButtonAction(SCButtons.BACK, group['buttons']['back']) + evm.setButtonAction(SCButtons.LGRIP, group['buttons']['left_grip']) + evm.setButtonAction(SCButtons.RGRIP, group['buttons']['right_grip']) + print('--- Switches configured') + + if('active' in config['left_trigger']): + set_trigger_config(evm, Pos.LEFT, config['left_trigger']['active']) + print('--- Left trigger configured') + + if('active' in config['right_trigger']): + set_trigger_config(evm, Pos.RIGHT, config['right_trigger']['active']) + print('--- Right trigger configured') # This cannot be configured from the Steam UI. Should we extend that file # to support configuring it? From 0a7073fa75f4db91504c268c0053d1d4a0209105 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 28 Jan 2017 13:02:34 -0500 Subject: [PATCH 051/104] src/events.py: Added some fold markers to EventMapper.process() to improve readability a bit --- src/events.py | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/events.py b/src/events.py index efffeff..0ee2a34 100644 --- a/src/events.py +++ b/src/events.py @@ -203,7 +203,7 @@ def _keyreleased(mode, ev): time() - self._steam_pressed_time > EXIT_PRESS_DURATION): sc.addExit() - # Manage buttons + # Manage buttons {{{ for btn, (mode, ev) in self._btn_map.items(): if mode is None: @@ -220,7 +220,9 @@ def _keyreleased(mode, ev): ev(self, btn, False) else: _keyreleased(mode, ev) - # Manage pads + # }}} + + # Manage pads {{{ for pos in [Pos.LEFT, Pos.RIGHT]: if pos == Pos.LEFT: @@ -262,7 +264,7 @@ def _keyreleased(mode, ev): xm_p, ym_p = xm, ym - # Mouse and mouse scroll modes + # Mouse and mouse scroll modes {{{ if self._pad_modes[pos] in (PadModes.MOUSE, PadModes.MOUSESCROLL): _free = True _dx = 0 @@ -286,9 +288,9 @@ def _keyreleased(mode, ev): # FIXME: make haptic configurable if not _free: sc.addFeedback(pos, amplitude=256) + # }}} - - # Axis mode + # Axis mode {{{ elif self._pad_modes[pos] == PadModes.AXIS: revert = self._pad_revs[pos] (xmode, xev), (ymode, yev) = self._pad_evts[pos] @@ -307,8 +309,9 @@ def _keyreleased(mode, ev): if y != y_p: self._uip[ymode].axisEvent(yev, y if not revert else -y) syn.add(ymode) + # }}} - # Button touch mode + # Button touch mode {{{ elif (self._pad_modes[pos] == PadModes.BUTTONTOUCH or self._pad_modes[pos] == PadModes.BUTTONCLICK): @@ -388,14 +391,15 @@ def _keyreleased(mode, ev): if haptic and self._pad_modes[pos] == PadModes.BUTTONTOUCH: sc.addFeedback(pos, amplitude=300) + # }}} if sci.buttons & touch != touch: xm_p, ym_p, xm, ym = 0, 0, 0, 0 self._xdq[pos].clear() self._ydq[pos].clear() + # }}} - - # Manage Trig + # Manage Trig {{{ for pos in [Pos.LEFT, Pos.RIGHT]: trigval = sci.ltrig if pos == Pos.LEFT else sci.rtrig trigval_prev = sci_p.ltrig if pos == Pos.LEFT else sci_p.rtrig @@ -413,9 +417,9 @@ def _keyreleased(mode, ev): elif self._trig_s[pos] is not None and trigval <= self._trig_s[pos]: self._trig_s[pos] = None _keyreleased(mode, ev) + # }}} - - # Manage Stick + # Manage Stick {{{ if sci.buttons & SCButtons.LPADTOUCH != SCButtons.LPADTOUCH: x, y = sci.lpad_x, sci.lpad_y x_p, y_p = sci_p.lpad_x, sci_p.lpad_y @@ -474,7 +478,7 @@ def _keyreleased(mode, ev): if sci.buttons & SCButtons.LPAD == SCButtons.LPAD: if self._stick_pressed_callback is not None: self._stick_pressed_callback(self) - + # }}} if len(_pressed): self._uip[Modes.KEYBOARD].pressEvent(_pressed) From 6ee77fc07004ae9e2fefeb4ef426adeff9c1019d Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 28 Jan 2017 13:03:42 -0500 Subject: [PATCH 052/104] src/events.py: Added optional "mode" parameter to setButtonAction(); if specified, set self._btn_map[btn] for _exactly_ that mode and exit --- src/events.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/events.py b/src/events.py index 0ee2a34..f2eae01 100644 --- a/src/events.py +++ b/src/events.py @@ -490,11 +490,15 @@ def _keyreleased(mode, ev): self._uip[i].synEvent() - def setButtonAction(self, btn, key_event): + def setButtonAction(self, btn, key_event, mode = None): if(key_event == None and btn in self._btn_map): del self._btn_map[btn] return + if(mode != None): + self._btn_map[btn] = (mode, key_event) + return + for mode in Modes: if self._uip[mode].keyManaged(key_event): self._btn_map[btn] = (mode, key_event) From 2b5409ae08b55a0a070cf7194735e50479d61345 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 28 Jan 2017 23:32:06 -0500 Subject: [PATCH 053/104] scripts/sc-configurable.py: parse_config(): Fixed button_diamond and switch calls to get_binding() --- scripts/sc-configurable.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 62dd590..65e72e0 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -155,7 +155,7 @@ def parse_config(config): # {{{ print('--- Joystick (active) loaded') if('button_diamond active' in bindings): - inputs = groups[bindings['button_diamond active']] + inputs = groups[bindings['button_diamond active']]['inputs'] output_config['button_diamond']['active'] = {'buttons' : { 'a' : get_binding(inputs, 'button_a', 'Full_Press'), 'b' : get_binding(inputs, 'button_b', 'Full_Press'), @@ -165,7 +165,7 @@ def parse_config(config): # {{{ print('--- Button diamond (active) loaded') if('switch active' in bindings): - inputs = groups[bindings['switch active']] + inputs = groups[bindings['switch active']]['inputs'] output_config['switch']['active'] = {'buttons' : { 'left_bumper' : get_binding(inputs, 'left_bumper', 'Full_Press'), 'right_bumper' : get_binding(inputs, 'right_bumper', 'Full_Press'), From eb93af1077493a69d8412971f59b16d2b7585982 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 29 Jan 2017 13:15:14 -0500 Subject: [PATCH 054/104] src/events.py: EventMapper.process(): Removed a few strategic blank lines and cleaned up a conditional for readability --- src/events.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/events.py b/src/events.py index f2eae01..1f5689b 100644 --- a/src/events.py +++ b/src/events.py @@ -205,7 +205,6 @@ def _keyreleased(mode, ev): # Manage buttons {{{ for btn, (mode, ev) in self._btn_map.items(): - if mode is None: continue @@ -215,7 +214,6 @@ def _keyreleased(mode, ev): else: _keypressed(mode, ev) elif btn & btn_rem: - if mode is Modes.CALLBACK: ev(self, btn, False) else: @@ -224,7 +222,6 @@ def _keyreleased(mode, ev): # Manage pads {{{ for pos in [Pos.LEFT, Pos.RIGHT]: - if pos == Pos.LEFT: x, y = sci.lpad_x, sci.lpad_y x_p, y_p = sci_p.lpad_x, sci_p.lpad_y @@ -263,7 +260,6 @@ def _keyreleased(mode, ev): if not sci_p.buttons & touch == touch: xm_p, ym_p = xm, ym - # Mouse and mouse scroll modes {{{ if self._pad_modes[pos] in (PadModes.MOUSE, PadModes.MOUSESCROLL): _free = True @@ -295,7 +291,6 @@ def _keyreleased(mode, ev): revert = self._pad_revs[pos] (xmode, xev), (ymode, yev) = self._pad_evts[pos] if xmode is not None: - # FIXME: make haptic configurable if sci.buttons & touch == touch: self._moved[pos] += sqrt((xm - xm_p)**2 + (ym - ym_p)**2) @@ -312,9 +307,7 @@ def _keyreleased(mode, ev): # }}} # Button touch mode {{{ - elif (self._pad_modes[pos] == PadModes.BUTTONTOUCH or - self._pad_modes[pos] == PadModes.BUTTONCLICK): - + elif (self._pad_modes[pos] == PadModes.BUTTONTOUCH or self._pad_modes[pos] == PadModes.BUTTONCLICK): if self._pad_modes[pos] == PadModes.BUTTONTOUCH: on_test = touch off_test = touch @@ -438,7 +431,6 @@ def _keyreleased(mode, ev): self._uip[ymode].axisEvent(yev, y if not revert else -y) elif self._stick_mode == StickModes.BUTTON: - tmode, tev = self._stick_evts[0] lmode, lev = self._stick_evts[1] bmode, bev = self._stick_evts[2] From e7690663eb4a1fad3cf44579edfae57e3209f937 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Mon, 30 Jan 2017 21:11:52 -0500 Subject: [PATCH 055/104] src/events.py: Cleaned up an if statement --- src/events.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/events.py b/src/events.py index 1f5689b..265baec 100644 --- a/src/events.py +++ b/src/events.py @@ -373,8 +373,7 @@ def _keyreleased(mode, ev): else: haptic |= _absreleased(xev) - if (sci.buttons & off_test != off_test and - sci_p.buttons & on_test == on_test): + if (sci.buttons & off_test != off_test and sci_p.buttons & on_test == on_test): if len(self._pad_evts[pos]) == 4: for mode, ev in self._pad_evts[pos]: haptic |= _keyreleased(mode, ev) From fbf9771ade0800b400e395c283718ac68511799f Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Mon, 30 Jan 2017 22:02:39 -0500 Subject: [PATCH 056/104] src/events.py: Added stick click functionality --- src/events.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/events.py b/src/events.py index 265baec..f2206dd 100644 --- a/src/events.py +++ b/src/events.py @@ -100,6 +100,7 @@ def __init__(self, gamepad_definition = None): self._stick_mode = StickModes.NOACTION self._stick_evts = [(None, 0)]*2 self._stick_rev = False + self._stick_click = (None, 0) self._sci_prev = SCI_NULL @@ -466,9 +467,16 @@ def _keyreleased(mode, ev): elif self._stick_rxs is not None and x <= self._stick_rxs: self._stick_rxs = None _keyreleased(rmode, rev) - if sci.buttons & SCButtons.LPAD == SCButtons.LPAD: - if self._stick_pressed_callback is not None: + if(self._stick_pressed_callback is not None): + if(sci.buttons & SCButtons.LPAD == SCButtons.LPAD): self._stick_pressed_callback(self) + if(self._stick_click[0] != None): + mode, ev = self._stick_click + pad_mask = (SCButtons.LPAD | SCButtons.LPADTOUCH) + if(btn_add & pad_mask == SCButtons.LPAD): + _keypressed(mode, ev) + elif(btn_rem & pad_mask == SCButtons.LPAD): + _keyreleased(mode, ev) # }}} if len(_pressed): From fa539ab0a0ae597d21806fcf5a15d7b760944a5e Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Mon, 30 Jan 2017 22:25:55 -0500 Subject: [PATCH 057/104] Revert "src/events.py: Added stick click functionality" This reverts commit fbf9771ade0800b400e395c283718ac68511799f. --- src/events.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/events.py b/src/events.py index f2206dd..265baec 100644 --- a/src/events.py +++ b/src/events.py @@ -100,7 +100,6 @@ def __init__(self, gamepad_definition = None): self._stick_mode = StickModes.NOACTION self._stick_evts = [(None, 0)]*2 self._stick_rev = False - self._stick_click = (None, 0) self._sci_prev = SCI_NULL @@ -467,16 +466,9 @@ def _keyreleased(mode, ev): elif self._stick_rxs is not None and x <= self._stick_rxs: self._stick_rxs = None _keyreleased(rmode, rev) - if(self._stick_pressed_callback is not None): - if(sci.buttons & SCButtons.LPAD == SCButtons.LPAD): + if sci.buttons & SCButtons.LPAD == SCButtons.LPAD: + if self._stick_pressed_callback is not None: self._stick_pressed_callback(self) - if(self._stick_click[0] != None): - mode, ev = self._stick_click - pad_mask = (SCButtons.LPAD | SCButtons.LPADTOUCH) - if(btn_add & pad_mask == SCButtons.LPAD): - _keypressed(mode, ev) - elif(btn_rem & pad_mask == SCButtons.LPAD): - _keyreleased(mode, ev) # }}} if len(_pressed): From 8d3e0367059b29fa409e69918878bf5bc58f9f16 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Mon, 30 Jan 2017 22:31:28 -0500 Subject: [PATCH 058/104] src/events.py: Added ugly LPAD/LPADTOUCH hack for properly identifying stick presses --- src/events.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/events.py b/src/events.py index 265baec..d36ee2a 100644 --- a/src/events.py +++ b/src/events.py @@ -209,15 +209,19 @@ def _keyreleased(mode, ev): continue if btn & btn_add: - if mode is Modes.CALLBACK: - ev(self, btn, True) - else: - _keypressed(mode, ev) + # This hack makes me want to go take a shower + if(btn != SCButtons.LPAD or not (btn_add | SCButtons.LPADTOUCH)): + if mode is Modes.CALLBACK: + ev(self, btn, True) + else: + _keypressed(mode, ev) elif btn & btn_rem: - if mode is Modes.CALLBACK: - ev(self, btn, False) - else: - _keyreleased(mode, ev) + # This hack still makes me want to go take a shower + if(btn != SCButtons.LPAD or not (btn_add | SCButtons.LPADTOUCH)): + if mode is Modes.CALLBACK: + ev(self, btn, False) + else: + _keyreleased(mode, ev) # }}} # Manage pads {{{ From 688dfaef91adab8a544a5e5d20c53a52390fc9b1 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Mon, 30 Jan 2017 22:32:35 -0500 Subject: [PATCH 059/104] scripts/sc-configurable.py: parse_config(): Added joystick click support --- scripts/sc-configurable.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 65e72e0..0d92ada 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -151,7 +151,9 @@ def parse_config(config): # {{{ print('--- Right trackpad (active) loaded') if('joystick active' in bindings): - output_config['joystick']['active'] = parse_analog_config(groups[bindings['joystick active']]) + group = groups[bindings['joystick active']] + output_config['joystick']['active'] = parse_analog_config(group) + output_config['joystick']['active']['click'] = get_binding(group['inputs'], 'click', 'Full_Press') print('--- Joystick (active) loaded') if('button_diamond active' in bindings): From 61fd6956769a3852f68171f2929a86213fd85cdc Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Mon, 30 Jan 2017 22:33:01 -0500 Subject: [PATCH 060/104] scripts/sc-configurable.py: evminit(): Hurr durr --- scripts/sc-configurable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 0d92ada..83fa3af 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -247,7 +247,7 @@ def evminit(config_file_path): if(group['mode'] == PadModes.BUTTONCLICK): evm.setStickButtons([group['buttons']['north'], group['buttons']['west'], group['buttons']['south'], group['buttons']['east']]) if('click' in group['buttons'] and group['buttons']['click'] != None): - evm.setActionButton(SCButtons.LPAD, group['buttons']['click']) + evm.setButtonAction(SCButtons.LPAD, group['buttons']['click']) print('--- Joystick configured') if('active' in config['button_diamond']): From a0ee8acbb56ace83fed95ff66ae596a6b6d86bbf Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Mon, 30 Jan 2017 22:34:36 -0500 Subject: [PATCH 061/104] src/events.py: EventMapper::setButtonAction(): Fixed action removal --- src/events.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/events.py b/src/events.py index d36ee2a..04064cc 100644 --- a/src/events.py +++ b/src/events.py @@ -487,7 +487,7 @@ def _keyreleased(mode, ev): def setButtonAction(self, btn, key_event, mode = None): if(key_event == None and btn in self._btn_map): - del self._btn_map[btn] + self._btn_map[btn] = (None, 0) return if(mode != None): From 6407242bb8e37e02f61b12bfae1252cb3cf32023 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Mon, 30 Jan 2017 22:47:17 -0500 Subject: [PATCH 062/104] src/events.py: Fixed LPAD/LPADTOUCH hack! --- src/events.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/events.py b/src/events.py index 04064cc..f108877 100644 --- a/src/events.py +++ b/src/events.py @@ -210,14 +210,14 @@ def _keyreleased(mode, ev): if btn & btn_add: # This hack makes me want to go take a shower - if(btn != SCButtons.LPAD or not (btn_add | SCButtons.LPADTOUCH)): + if(not (btn == SCButtons.LPAD and (sci.buttons & SCButtons.LPADTOUCH))): if mode is Modes.CALLBACK: ev(self, btn, True) else: _keypressed(mode, ev) elif btn & btn_rem: # This hack still makes me want to go take a shower - if(btn != SCButtons.LPAD or not (btn_add | SCButtons.LPADTOUCH)): + if(not (btn == SCButtons.LPAD and (sci_p.buttons & SCButtons.LPADTOUCH))): if mode is Modes.CALLBACK: ev(self, btn, False) else: From f48a0fd1a8bb158a498f2550394471ed63abfe92 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Mon, 30 Jan 2017 23:02:09 -0500 Subject: [PATCH 063/104] scripts/sc-configurable.py: parse_config(): Fixed joystick click assignment --- scripts/sc-configurable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 83fa3af..4936eb2 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -153,7 +153,7 @@ def parse_config(config): # {{{ if('joystick active' in bindings): group = groups[bindings['joystick active']] output_config['joystick']['active'] = parse_analog_config(group) - output_config['joystick']['active']['click'] = get_binding(group['inputs'], 'click', 'Full_Press') + output_config['joystick']['active']['buttons']['click'] = get_binding(group['inputs'], 'click', 'Full_Press') print('--- Joystick (active) loaded') if('button_diamond active' in bindings): From cb0d35345538b20be201a248473106386f66d95d Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Tue, 31 Jan 2017 23:30:22 -0500 Subject: [PATCH 064/104] scripts/sc-configurable.py: Dynamic gamepad definition for keys --- scripts/sc-configurable.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 4936eb2..ab0c732 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -211,14 +211,31 @@ def set_trigger_config(evm, pos, config): # {{{ evm.setTrigButton(pos, config['buttons']['click']) # }}} +def get_keys_from_config(config): # {{{ + buttons = [] + for group in config.values(): + for mode in group.values(): + if('buttons' in mode): + for button in mode['buttons'].values(): + if(button != None): + buttons.append(button) + buttons = list(set(buttons)) + return buttons +# }}} + def evminit(config_file_path): - # TODO: Dynamic gamepad definition for keys/axes based on config + vdf = load_vdf(config_file_path) + config = parse_config(vdf) + + keys = get_keys_from_config(config) + + # TODO: Dynamic gamepad definition for axes based on config evm = EventMapper(gamepad_definition = { 'vendor' : 0x28de, 'product' : 0x1142, 'version' : 0x1, 'name' : b"Steam Controller", - 'keys' : Scans.keys(), + 'keys' : keys, 'axes' : [ (Axes.ABS_X, -32768, 32767, 16, 128), (Axes.ABS_Y, -32768, 32767, 16, 128), @@ -231,8 +248,6 @@ def evminit(config_file_path): ], 'rels' : [] }) - vdf = load_vdf(config_file_path) - config = parse_config(vdf) if('active' in config['left_trackpad']): set_trackpad_config(evm, Pos.LEFT, config['left_trackpad']['active']) From ee5be61db36090218bcb42ceef0e5f62d0e78398 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 4 Feb 2017 14:08:59 -0500 Subject: [PATCH 065/104] scripts/sc-configurable.py: Added Modes.GAMEPAD specification to all evm.setButtonAction() calls --- scripts/sc-configurable.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index ab0c732..19847a8 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -26,7 +26,7 @@ """Steam Controller VDF-configurable mode""" from steamcontroller import SteamController, SCButtons -from steamcontroller.events import EventMapper, PadModes, Pos, TrigModes +from steamcontroller.events import EventMapper, Modes, PadModes, Pos, TrigModes from steamcontroller.uinput import Axes, Keys, Scans from steamcontroller.daemon import Daemon @@ -195,11 +195,11 @@ def set_trackpad_config(evm, pos, config): # {{{ button = SCButtons.RPAD if pos == Pos.RIGHT else SCButtons.LPAD if(config['mode'] == PadModes.MOUSE): evm.setPadMouse(pos) - evm.setButtonAction(button, config['buttons']['click']) + evm.setButtonAction(button, config['buttons']['click'], Modes.GAMEPAD) elif(config['mode'] == PadModes.MOUSESCROLL): # TODO: Support configuration for scroll directions evm.setPadScroll(pos) - evm.setButtonAction(button, config['buttons']['click']) + evm.setButtonAction(button, config['buttons']['click'], Modes.GAMEPAD) elif(config['mode'] == PadModes.BUTTONCLICK): # TODO: Configurable whether or not click is required? buttons = config['buttons'] @@ -262,25 +262,25 @@ def evminit(config_file_path): if(group['mode'] == PadModes.BUTTONCLICK): evm.setStickButtons([group['buttons']['north'], group['buttons']['west'], group['buttons']['south'], group['buttons']['east']]) if('click' in group['buttons'] and group['buttons']['click'] != None): - evm.setButtonAction(SCButtons.LPAD, group['buttons']['click']) + evm.setButtonAction(SCButtons.LPAD, group['buttons']['click'], Modes.GAMEPAD) print('--- Joystick configured') if('active' in config['button_diamond']): group = config['button_diamond']['active'] - evm.setButtonAction(SCButtons.A, group['buttons']['a']) - evm.setButtonAction(SCButtons.B, group['buttons']['b']) - evm.setButtonAction(SCButtons.X, group['buttons']['x']) - evm.setButtonAction(SCButtons.Y, group['buttons']['y']) + evm.setButtonAction(SCButtons.A, group['buttons']['a'], Modes.GAMEPAD) + evm.setButtonAction(SCButtons.B, group['buttons']['b'], Modes.GAMEPAD) + evm.setButtonAction(SCButtons.X, group['buttons']['x'], Modes.GAMEPAD) + evm.setButtonAction(SCButtons.Y, group['buttons']['y'], Modes.GAMEPAD) print('--- Button diamond configured') if('active' in config['switch']): group = config['switch']['active'] - evm.setButtonAction(SCButtons.LB, group['buttons']['left_bumper']) - evm.setButtonAction(SCButtons.RB, group['buttons']['right_bumper']) - evm.setButtonAction(SCButtons.START, group['buttons']['start']) - evm.setButtonAction(SCButtons.BACK, group['buttons']['back']) - evm.setButtonAction(SCButtons.LGRIP, group['buttons']['left_grip']) - evm.setButtonAction(SCButtons.RGRIP, group['buttons']['right_grip']) + evm.setButtonAction(SCButtons.LB, group['buttons']['left_bumper'], Modes.GAMEPAD) + evm.setButtonAction(SCButtons.RB, group['buttons']['right_bumper'], Modes.GAMEPAD) + evm.setButtonAction(SCButtons.START, group['buttons']['start'], Modes.GAMEPAD) + evm.setButtonAction(SCButtons.BACK, group['buttons']['back'], Modes.GAMEPAD) + evm.setButtonAction(SCButtons.LGRIP, group['buttons']['left_grip'], Modes.GAMEPAD) + evm.setButtonAction(SCButtons.RGRIP, group['buttons']['right_grip'], Modes.GAMEPAD) print('--- Switches configured') if('active' in config['left_trigger']): @@ -293,7 +293,7 @@ def evminit(config_file_path): # This cannot be configured from the Steam UI. Should we extend that file # to support configuring it? - evm.setButtonAction(SCButtons.STEAM, Keys.KEY_HOMEPAGE) + evm.setButtonAction(SCButtons.STEAM, Keys.KEY_HOMEPAGE, Modes.GAMEPAD) return evm From 7c5fe4f29fa9e5c8218110ddfec2479d31e6bbc6 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 4 Feb 2017 14:35:06 -0500 Subject: [PATCH 066/104] src/events.py: Added mode specification support to setTrigButton() and setStickButtons() --- src/events.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/events.py b/src/events.py index f108877..7e9864b 100644 --- a/src/events.py +++ b/src/events.py @@ -619,8 +619,18 @@ def setPadAxes(self, pos, abs_x_event, abs_y_event, revert=True): (Modes.GAMEPAD, abs_y_event)] self._pad_revs[pos] = revert - def setTrigButton(self, pos, key_event): + def setTrigButton(self, pos, key_event, mode = None): + if(key_event == None): + self._trig_evts[pos] = (None, 0) + self._trig_modes[pos] = TrigModes.NOACTION + return + self._trig_modes[pos] = TrigModes.BUTTON + + if(mode != None): + self._trig_evts[pos] = (mode, key_event) + return + for mode in Modes: if self._uip[mode].keyManaged(key_event): self._trig_evts[pos] = (mode, key_event) @@ -650,7 +660,7 @@ def setStickAxesCallback(self, callback): self._stick_axes_callback = callback - def setStickButtons(self, key_events): + def setStickButtons(self, key_events, mode = None): """ Set stick as buttons @@ -663,10 +673,13 @@ def setStickButtons(self, key_events): self._stick_evts = [] for ev in key_events: - for mode in Modes: - if self._uip[mode].keyManaged(ev): - self._stick_evts.append((mode, ev)) - break + if(mode != None): + self._stick_evts.append((mode, ev)) + else: + for mode in Modes: + if self._uip[mode].keyManaged(ev): + self._stick_evts.append((mode, ev)) + break def setStickPressedCallback(self, callback): """ From 6fe5de5aa6673a4e2acdc81d65f890a95a10b656 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 4 Feb 2017 14:36:14 -0500 Subject: [PATCH 067/104] scripts/sc-configurable.py: Added Modes.GAMEPAD specification to evm.setStickButtons() and evm.setTrigButton() calls --- scripts/sc-configurable.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 19847a8..7f12755 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -208,7 +208,7 @@ def set_trackpad_config(evm, pos, config): # {{{ def set_trigger_config(evm, pos, config): # {{{ if(config['mode'] == TrigModes.BUTTON): - evm.setTrigButton(pos, config['buttons']['click']) + evm.setTrigButton(pos, config['buttons']['click'], Modes.GAMEPAD) # }}} def get_keys_from_config(config): # {{{ @@ -260,7 +260,7 @@ def evminit(config_file_path): if('active' in config['joystick']): group = config['joystick']['active'] if(group['mode'] == PadModes.BUTTONCLICK): - evm.setStickButtons([group['buttons']['north'], group['buttons']['west'], group['buttons']['south'], group['buttons']['east']]) + evm.setStickButtons([group['buttons']['north'], group['buttons']['west'], group['buttons']['south'], group['buttons']['east']], Modes.GAMEPAD) if('click' in group['buttons'] and group['buttons']['click'] != None): evm.setButtonAction(SCButtons.LPAD, group['buttons']['click'], Modes.GAMEPAD) print('--- Joystick configured') From 2497241d641eb0f0554c4e0b110a1a7c8ecc9b9d Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 4 Feb 2017 14:40:59 -0500 Subject: [PATCH 068/104] src/events.py: Added mode specification support to setPadButtons() --- src/events.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/events.py b/src/events.py index 7e9864b..e5766dc 100644 --- a/src/events.py +++ b/src/events.py @@ -512,7 +512,7 @@ def setButtonCallback(self, btn, callback): self._btn_map[btn] = (Modes.CALLBACK, callback) - def setPadButtons(self, pos, key_events, deadzone=0.6, clicked=False): + def setPadButtons(self, pos, key_events, deadzone=0.6, clicked=False, mode = None): """ Set pad as buttons @@ -529,10 +529,13 @@ def setPadButtons(self, pos, key_events, deadzone=0.6, clicked=False): self._pad_evts[pos] = [] for ev in key_events: - for mode in Modes: - if self._uip[mode].keyManaged(ev): - self._pad_evts[pos].append((mode, ev)) - break + if(mode != None): + self._pad_evts[pos].append((mode, ev)) + else: + for mode in self._uip.keys(): + if self._uip[mode].keyManaged(ev): + self._pad_evts[pos].append((mode, ev)) + break self._pad_dzones[pos] = 32768 * deadzone From 3e4c4b0221b2048cc197e7956a7888fd8aeb4c31 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 4 Feb 2017 14:41:12 -0500 Subject: [PATCH 069/104] scripts/sc-configurable.py: Added Modes.GAMEPAD specification to evm.setPadButtons() call --- scripts/sc-configurable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 7f12755..7c1ccd4 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -203,7 +203,7 @@ def set_trackpad_config(evm, pos, config): # {{{ elif(config['mode'] == PadModes.BUTTONCLICK): # TODO: Configurable whether or not click is required? buttons = config['buttons'] - evm.setPadButtons(pos, [buttons['north'], buttons['west'], buttons['south'], buttons['east']], clicked = True) + evm.setPadButtons(pos, [buttons['north'], buttons['west'], buttons['south'], buttons['east']], clicked = True, mode = Modes.GAMEPAD) # }}} def set_trigger_config(evm, pos, config): # {{{ From d1340c9462bbb17cc56010f0a4e40d885d326719 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 4 Feb 2017 14:58:10 -0500 Subject: [PATCH 070/104] src/events.py: EventMapper::_uip is no longer hardcoded to (sui.Gamepad(), sui.Keyboard(), sui.Mouse()); rather, it is a dictionary which is dynamically generated based on the new "modes" parameter to EventMapper::__init__() --- src/events.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/events.py b/src/events.py index e5766dc..f6cf9d0 100644 --- a/src/events.py +++ b/src/events.py @@ -82,10 +82,14 @@ class EventMapper(object): callback to be registered to a SteamController instance """ - def __init__(self, gamepad_definition = None): - self._uip = (sui.Gamepad(gamepad_definition), - sui.Keyboard(), - sui.Mouse()) + def __init__(self, gamepad_definition = None, modes = [Modes.GAMEPAD, Modes.MOUSE, Modes.KEYBOARD]): + self._uip = {} + if(Modes.GAMEPAD in modes): + self._uip[Modes.GAMEPAD] = sui.Gamepad(gamepad_definition) + if(Modes.KEYBOARD in modes): + self._uip[Modes.KEYBOARD] = sui.Keyboard() + if(Modes.MOUSE in modes): + self._uip[Modes.MOUSE] = sui.Mouse() self._btn_map = {x : (None, 0) for x in list(SCButtons)} @@ -494,7 +498,7 @@ def setButtonAction(self, btn, key_event, mode = None): self._btn_map[btn] = (mode, key_event) return - for mode in Modes: + for mode in self._uip.keys(): if self._uip[mode].keyManaged(key_event): self._btn_map[btn] = (mode, key_event) return @@ -634,7 +638,7 @@ def setTrigButton(self, pos, key_event, mode = None): self._trig_evts[pos] = (mode, key_event) return - for mode in Modes: + for mode in self._uip.keys(): if self._uip[mode].keyManaged(key_event): self._trig_evts[pos] = (mode, key_event) return @@ -679,7 +683,7 @@ def setStickButtons(self, key_events, mode = None): if(mode != None): self._stick_evts.append((mode, ev)) else: - for mode in Modes: + for mode in self._uip.keys(): if self._uip[mode].keyManaged(ev): self._stick_evts.append((mode, ev)) break From 2993f47248e54a30e13b60ecc5ee26cf21bdbbb1 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 4 Feb 2017 23:13:32 -0500 Subject: [PATCH 071/104] scripts/sc-configurable.py: Added modes specification to EventMapper constructor call --- scripts/sc-configurable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 7c1ccd4..47bd1e6 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -247,7 +247,7 @@ def evminit(config_file_path): (Axes.ABS_HAT1Y, -1, 1, 0, 0) ], 'rels' : [] - }) + }, modes = [Modes.GAMEPAD, Modes.MOUSE]) if('active' in config['left_trackpad']): set_trackpad_config(evm, Pos.LEFT, config['left_trackpad']['active']) From 172d492c06c90b47d99a39a36471f792d763ad12 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 4 Feb 2017 23:54:17 -0500 Subject: [PATCH 072/104] scripts/sc-configurable.py: Added another ridiculous hack; this time, get_binding() is adding 0x100 to all KEY_ constants to trick the uinput subsystem into considering this gamepad/joystick input --- scripts/sc-configurable.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 47bd1e6..b59d209 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -89,7 +89,11 @@ def get_binding(group_inputs, input_name, activator): # {{{ if(binding[1] == 'PERIOD'): binding[1] = 'DOT' - return Keys.__getattr__('KEY_' + binding[1]) + # Holy crap, the hacks don't get much uglier than this. Add 0x100 to + # all KEY_ constants, because the keyboard ends at 0xff and that + # seems to make the uinput subsystem happy about considering this + # to be a gamepad/joystick. + return Keys.__getattr__('KEY_' + binding[1]) + 0x100 elif(binding[0] == 'mouse_wheel'): # TODO: Figure out if we actually need this; if so, add support return None From 37c6830e974504e53c9f05a41c8c30a1db130021 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 5 Feb 2017 00:32:29 -0500 Subject: [PATCH 073/104] scripts/sc-configurable.py: Added get_modes_from_config(), to generate "modes" to pass to EventMapper constructor --- scripts/sc-configurable.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index b59d209..d795b3c 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -227,11 +227,31 @@ def get_keys_from_config(config): # {{{ return buttons # }}} +def get_modes_from_config(config): # {{{ + modes = set() + for group in config.values(): + for mode in group.values(): + if('buttons' in mode): + modes.add(Modes.GAMEPAD) + break + if(Modes.GAMEPAD in modes): + break + for group in ['left_trackpad', 'right_trackpad']: + for mode in config[group].values(): + if(mode['mode'] == PadModes.MOUSE): + modes.add(Modes.MOUSE) + break + if(Modes.MOUSE in modes): + break + return list(modes) +# }}} + def evminit(config_file_path): vdf = load_vdf(config_file_path) config = parse_config(vdf) keys = get_keys_from_config(config) + modes = get_modes_from_config(config) # TODO: Dynamic gamepad definition for axes based on config evm = EventMapper(gamepad_definition = { @@ -251,7 +271,7 @@ def evminit(config_file_path): (Axes.ABS_HAT1Y, -1, 1, 0, 0) ], 'rels' : [] - }, modes = [Modes.GAMEPAD, Modes.MOUSE]) + }, modes = modes) if('active' in config['left_trackpad']): set_trackpad_config(evm, Pos.LEFT, config['left_trackpad']['active']) From 6d6b08ceb7a3b48ca1060aa244afd80f48db2950 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 5 Feb 2017 00:37:27 -0500 Subject: [PATCH 074/104] scripts/sc-configurable.py: Added get_axes_from_config() (currently stub), which will provide the "axes" data member for gamepad_definition as passed to EventMapper constructor --- scripts/sc-configurable.py | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index d795b3c..8d89072 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -227,6 +227,11 @@ def get_keys_from_config(config): # {{{ return buttons # }}} +def get_axes_from_config(config): # {{{ + # TODO: Implement this + return [] +# }}} + def get_modes_from_config(config): # {{{ modes = set() for group in config.values(): @@ -251,25 +256,16 @@ def evminit(config_file_path): config = parse_config(vdf) keys = get_keys_from_config(config) + axes = get_axes_from_config(config) modes = get_modes_from_config(config) - # TODO: Dynamic gamepad definition for axes based on config evm = EventMapper(gamepad_definition = { 'vendor' : 0x28de, 'product' : 0x1142, 'version' : 0x1, 'name' : b"Steam Controller", 'keys' : keys, - 'axes' : [ - (Axes.ABS_X, -32768, 32767, 16, 128), - (Axes.ABS_Y, -32768, 32767, 16, 128), - (Axes.ABS_Z, 0, 255, 0, 0), - (Axes.ABS_RZ, 0, 255, 0, 0), - (Axes.ABS_HAT0X, -1, 1, 0, 0), - (Axes.ABS_HAT0Y, -1, 1, 0, 0), - (Axes.ABS_HAT1X, -1, 1, 0, 0), - (Axes.ABS_HAT1Y, -1, 1, 0, 0) - ], + 'axes' : axes, 'rels' : [] }, modes = modes) From f258d507b083f72ddc7e02ba71c3156975772c4a Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 5 Feb 2017 00:39:48 -0500 Subject: [PATCH 075/104] scripts/sc-configurable.py: Added name of config file to gamepad_definition's "name" field --- scripts/sc-configurable.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 8d89072..ff2d941 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -33,6 +33,7 @@ import gc import json +import os import vdf2json @@ -263,7 +264,7 @@ def evminit(config_file_path): 'vendor' : 0x28de, 'product' : 0x1142, 'version' : 0x1, - 'name' : b"Steam Controller", + 'name' : b"Steam Controller [" + bytes(os.path.basename(config_file_path), 'utf-8') + b']', 'keys' : keys, 'axes' : axes, 'rels' : [] From 287cf23e06506714ddce92df3add62e4f109fed7 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 5 Feb 2017 00:40:35 -0500 Subject: [PATCH 076/104] scripts/sc-configurable.py: Moved get_*_from_config() functions to above set_*_config() --- scripts/sc-configurable.py | 40 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index ff2d941..ab50142 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -196,26 +196,6 @@ def parse_config(config): # {{{ return output_config # }}} -def set_trackpad_config(evm, pos, config): # {{{ - button = SCButtons.RPAD if pos == Pos.RIGHT else SCButtons.LPAD - if(config['mode'] == PadModes.MOUSE): - evm.setPadMouse(pos) - evm.setButtonAction(button, config['buttons']['click'], Modes.GAMEPAD) - elif(config['mode'] == PadModes.MOUSESCROLL): - # TODO: Support configuration for scroll directions - evm.setPadScroll(pos) - evm.setButtonAction(button, config['buttons']['click'], Modes.GAMEPAD) - elif(config['mode'] == PadModes.BUTTONCLICK): - # TODO: Configurable whether or not click is required? - buttons = config['buttons'] - evm.setPadButtons(pos, [buttons['north'], buttons['west'], buttons['south'], buttons['east']], clicked = True, mode = Modes.GAMEPAD) -# }}} - -def set_trigger_config(evm, pos, config): # {{{ - if(config['mode'] == TrigModes.BUTTON): - evm.setTrigButton(pos, config['buttons']['click'], Modes.GAMEPAD) -# }}} - def get_keys_from_config(config): # {{{ buttons = [] for group in config.values(): @@ -252,6 +232,26 @@ def get_modes_from_config(config): # {{{ return list(modes) # }}} +def set_trackpad_config(evm, pos, config): # {{{ + button = SCButtons.RPAD if pos == Pos.RIGHT else SCButtons.LPAD + if(config['mode'] == PadModes.MOUSE): + evm.setPadMouse(pos) + evm.setButtonAction(button, config['buttons']['click'], Modes.GAMEPAD) + elif(config['mode'] == PadModes.MOUSESCROLL): + # TODO: Support configuration for scroll directions + evm.setPadScroll(pos) + evm.setButtonAction(button, config['buttons']['click'], Modes.GAMEPAD) + elif(config['mode'] == PadModes.BUTTONCLICK): + # TODO: Configurable whether or not click is required? + buttons = config['buttons'] + evm.setPadButtons(pos, [buttons['north'], buttons['west'], buttons['south'], buttons['east']], clicked = True, mode = Modes.GAMEPAD) +# }}} + +def set_trigger_config(evm, pos, config): # {{{ + if(config['mode'] == TrigModes.BUTTON): + evm.setTrigButton(pos, config['buttons']['click'], Modes.GAMEPAD) +# }}} + def evminit(config_file_path): vdf = load_vdf(config_file_path) config = parse_config(vdf) From d234f378fca8c5d877dfd79c1dd1e1bbe3c5117e Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 5 Feb 2017 19:00:33 -0500 Subject: [PATCH 077/104] scripts/sc-configurable.py: Split parse_analog_config() into parse_trackpad_config() and parse_joystick_config(); currently, parse_joystick_config() is entirely wrong and is just a carbon copy of parse_trackpad_config() --- scripts/sc-configurable.py | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index ab50142..46ec82f 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -104,7 +104,26 @@ def get_binding(group_inputs, input_name, activator): # {{{ return None # }}} -def parse_analog_config(group): # {{{ +def parse_trackpad_config(group): # {{{ + config = {} + if(group['mode'] == 'absolute_mouse'): + config['mode'] = PadModes.MOUSE + config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} + elif(group['mode'] == 'scrollwheel'): + config['mode'] = PadModes.MOUSESCROLL + config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} + elif(group['mode'] == 'dpad'): + config['mode'] = PadModes.BUTTONCLICK + config['buttons'] = { + 'north' : get_binding(group['inputs'], 'dpad_north', 'Full_Press'), + 'west' : get_binding(group['inputs'], 'dpad_west', 'Full_Press'), + 'south' : get_binding(group['inputs'], 'dpad_south', 'Full_Press'), + 'east' : get_binding(group['inputs'], 'dpad_east', 'Full_Press') + } + return config +# }}} + +def parse_joystick_config(group): # {{{ config = {} if(group['mode'] == 'absolute_mouse'): config['mode'] = PadModes.MOUSE @@ -148,16 +167,16 @@ def parse_config(config): # {{{ } if('left_trackpad active' in bindings): - output_config['left_trackpad']['active'] = parse_analog_config(groups[bindings['left_trackpad active']]) + output_config['left_trackpad']['active'] = parse_trackpad_config(groups[bindings['left_trackpad active']]) print('--- Left trackpad (active) loaded') if('right_trackpad active' in bindings): - output_config['right_trackpad']['active'] = parse_analog_config(groups[bindings['right_trackpad active']]) + output_config['right_trackpad']['active'] = parse_trackpad_config(groups[bindings['right_trackpad active']]) print('--- Right trackpad (active) loaded') if('joystick active' in bindings): group = groups[bindings['joystick active']] - output_config['joystick']['active'] = parse_analog_config(group) + output_config['joystick']['active'] = parse_joystick_config(group) output_config['joystick']['active']['buttons']['click'] = get_binding(group['inputs'], 'click', 'Full_Press') print('--- Joystick (active) loaded') From 7caf9841031893d80a80bca783d1f4b3f3a33169 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 5 Feb 2017 19:40:23 -0500 Subject: [PATCH 078/104] scripts/sc-configurable.py: Refined parse_joystick_config() somewhat --- scripts/sc-configurable.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 46ec82f..50fc93f 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -125,20 +125,29 @@ def parse_trackpad_config(group): # {{{ def parse_joystick_config(group): # {{{ config = {} - if(group['mode'] == 'absolute_mouse'): - config['mode'] = PadModes.MOUSE - config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} + if(group['mode'] == 'joystick_mouse'): + config['mode'] = StickModes.AXIS + if('click' in group['inputs']): + config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} elif(group['mode'] == 'scrollwheel'): - config['mode'] = PadModes.MOUSESCROLL - config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} + # TODO: Implement + pass elif(group['mode'] == 'dpad'): - config['mode'] = PadModes.BUTTONCLICK + config['mode'] = StickModes.BUTTON config['buttons'] = { 'north' : get_binding(group['inputs'], 'dpad_north', 'Full_Press'), 'west' : get_binding(group['inputs'], 'dpad_west', 'Full_Press'), 'south' : get_binding(group['inputs'], 'dpad_south', 'Full_Press'), 'east' : get_binding(group['inputs'], 'dpad_east', 'Full_Press') } + elif(group['mode'] == 'buttons'): + config['mode'] = StickModes.BUTTON + config['buttons'] = { + 'north' : get_binding(group['inputs'], 'button_y', 'Full_Press'), + 'west' : get_binding(group['inputs'], 'button_x', 'Full_Press'), + 'south' : get_binding(group['inputs'], 'button_b', 'Full_Press'), + 'east' : get_binding(group['inputs'], 'button_a', 'Full_Press') + } return config # }}} From fb82b4ca0e8eead01c56d81fb7befc487aee875b Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 5 Feb 2017 20:07:50 -0500 Subject: [PATCH 079/104] scripts/sc-configurable.py: DRY on analog dpad/diamond inputs; refined trackpad config parsing somewhat --- scripts/sc-configurable.py | 42 ++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 50fc93f..bf56e67 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -104,6 +104,24 @@ def get_binding(group_inputs, input_name, activator): # {{{ return None # }}} +def get_dpad_inputs(group): # {{{ + return { + 'north' : get_binding(group, 'dpad_north', 'Full_Press'), + 'west' : get_binding(group, 'dpad_west', 'Full_Press'), + 'south' : get_binding(group, 'dpad_south', 'Full_Press'), + 'east' : get_binding(group, 'dpad_east', 'Full_Press') + } +# }}} + +def get_diamond_inputs(group): # {{{ + return { + 'north' : get_binding(group, 'button_y', 'Full_Press'), + 'west' : get_binding(group, 'button_x', 'Full_Press'), + 'south' : get_binding(group, 'button_b', 'Full_Press'), + 'east' : get_binding(group, 'button_a', 'Full_Press') + } +# }}} + def parse_trackpad_config(group): # {{{ config = {} if(group['mode'] == 'absolute_mouse'): @@ -114,12 +132,10 @@ def parse_trackpad_config(group): # {{{ config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} elif(group['mode'] == 'dpad'): config['mode'] = PadModes.BUTTONCLICK - config['buttons'] = { - 'north' : get_binding(group['inputs'], 'dpad_north', 'Full_Press'), - 'west' : get_binding(group['inputs'], 'dpad_west', 'Full_Press'), - 'south' : get_binding(group['inputs'], 'dpad_south', 'Full_Press'), - 'east' : get_binding(group['inputs'], 'dpad_east', 'Full_Press') - } + config['buttons'] = get_dpad_inputs(group['inputs']) + elif(group['mode'] == 'buttons'): + config['mode'] = PadModes.BUTTONCLICK + config['buttons'] = get_diamond_inputs(group['inputs']) return config # }}} @@ -134,20 +150,10 @@ def parse_joystick_config(group): # {{{ pass elif(group['mode'] == 'dpad'): config['mode'] = StickModes.BUTTON - config['buttons'] = { - 'north' : get_binding(group['inputs'], 'dpad_north', 'Full_Press'), - 'west' : get_binding(group['inputs'], 'dpad_west', 'Full_Press'), - 'south' : get_binding(group['inputs'], 'dpad_south', 'Full_Press'), - 'east' : get_binding(group['inputs'], 'dpad_east', 'Full_Press') - } + config['buttons'] = get_dpad_inputs(group['inputs']) elif(group['mode'] == 'buttons'): config['mode'] = StickModes.BUTTON - config['buttons'] = { - 'north' : get_binding(group['inputs'], 'button_y', 'Full_Press'), - 'west' : get_binding(group['inputs'], 'button_x', 'Full_Press'), - 'south' : get_binding(group['inputs'], 'button_b', 'Full_Press'), - 'east' : get_binding(group['inputs'], 'button_a', 'Full_Press') - } + config['buttons'] = get_diamond_inputs(group['inputs']) return config # }}} From 3f097f2148e94302988c5db86739f80471656a31 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 11 Feb 2017 23:09:11 -0500 Subject: [PATCH 080/104] scripts/sc-configurable.py: Fixed joystick input --- scripts/sc-configurable.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index bf56e67..4b712d2 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -26,7 +26,7 @@ """Steam Controller VDF-configurable mode""" from steamcontroller import SteamController, SCButtons -from steamcontroller.events import EventMapper, Modes, PadModes, Pos, TrigModes +from steamcontroller.events import EventMapper, Modes, StickModes, PadModes, Pos, TrigModes from steamcontroller.uinput import Axes, Keys, Scans from steamcontroller.daemon import Daemon @@ -314,7 +314,7 @@ def evminit(config_file_path): if('active' in config['joystick']): group = config['joystick']['active'] - if(group['mode'] == PadModes.BUTTONCLICK): + if(group['mode'] == StickModes.BUTTON): evm.setStickButtons([group['buttons']['north'], group['buttons']['west'], group['buttons']['south'], group['buttons']['east']], Modes.GAMEPAD) if('click' in group['buttons'] and group['buttons']['click'] != None): evm.setButtonAction(SCButtons.LPAD, group['buttons']['click'], Modes.GAMEPAD) From 7ac593b9466b4711d137bc7c0aff99d4ef90f23e Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 11 Feb 2017 23:27:10 -0500 Subject: [PATCH 081/104] scripts/sc-configurable.py: Fixed axis modes for joystick and trackpads --- scripts/sc-configurable.py | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 4b712d2..17acbb8 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -122,11 +122,15 @@ def get_diamond_inputs(group): # {{{ } # }}} -def parse_trackpad_config(group): # {{{ +def parse_trackpad_config(group, pos): # {{{ config = {} if(group['mode'] == 'absolute_mouse'): config['mode'] = PadModes.MOUSE config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} + elif(group['mode'] == 'mouse_region'): + # TODO: Implement + config['mode'] = PadModes.NOACTION + pass elif(group['mode'] == 'scrollwheel'): config['mode'] = PadModes.MOUSESCROLL config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} @@ -136,6 +140,11 @@ def parse_trackpad_config(group): # {{{ elif(group['mode'] == 'buttons'): config['mode'] = PadModes.BUTTONCLICK config['buttons'] = get_diamond_inputs(group['inputs']) + elif(group['mode'] == 'mouse_joystick'): + config['mode'] = PadModes.AXIS + config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} + axes = [Axes.ABS_HAT0X, Axes.ABS_HAT0Y] if pos == Pos.LEFT else [Axes.ABS_HAT1X, Axes.ABS_HAT1Y] + config['axes'] = [(axis, -1, 1, 0, 0) for axis in axes] return config # }}} @@ -143,10 +152,11 @@ def parse_joystick_config(group): # {{{ config = {} if(group['mode'] == 'joystick_mouse'): config['mode'] = StickModes.AXIS - if('click' in group['inputs']): - config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} + config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} + config['axes'] = [(axis, -32768, 32767, 16, 128) for axis in [Axes.ABS_X, Axes.ABS_Y]] elif(group['mode'] == 'scrollwheel'): # TODO: Implement + config['mode'] = StickModes.NOACTION pass elif(group['mode'] == 'dpad'): config['mode'] = StickModes.BUTTON @@ -182,11 +192,11 @@ def parse_config(config): # {{{ } if('left_trackpad active' in bindings): - output_config['left_trackpad']['active'] = parse_trackpad_config(groups[bindings['left_trackpad active']]) + output_config['left_trackpad']['active'] = parse_trackpad_config(groups[bindings['left_trackpad active']], Pos.LEFT) print('--- Left trackpad (active) loaded') if('right_trackpad active' in bindings): - output_config['right_trackpad']['active'] = parse_trackpad_config(groups[bindings['right_trackpad active']]) + output_config['right_trackpad']['active'] = parse_trackpad_config(groups[bindings['right_trackpad active']], Pos.RIGHT) print('--- Right trackpad (active) loaded') if('joystick active' in bindings): @@ -243,8 +253,15 @@ def get_keys_from_config(config): # {{{ # }}} def get_axes_from_config(config): # {{{ - # TODO: Implement this - return [] + axes = [] + for group in config.values(): + for mode in group.values(): + if('axes' in mode): + for axis in mode['axes']: + if(axis != None): + axes.append(axis) + axes = list(set(axes)) + return axes # }}} def get_modes_from_config(config): # {{{ @@ -279,6 +296,9 @@ def set_trackpad_config(evm, pos, config): # {{{ # TODO: Configurable whether or not click is required? buttons = config['buttons'] evm.setPadButtons(pos, [buttons['north'], buttons['west'], buttons['south'], buttons['east']], clicked = True, mode = Modes.GAMEPAD) + elif(config['mode'] == PadModes.AXIS): + evm.setPadAxes(pos, *[axis[0] for axis in config['axes']]) + evm.setButtonAction(button, config['buttons']['click'], Modes.GAMEPAD) # }}} def set_trigger_config(evm, pos, config): # {{{ @@ -318,6 +338,8 @@ def evminit(config_file_path): evm.setStickButtons([group['buttons']['north'], group['buttons']['west'], group['buttons']['south'], group['buttons']['east']], Modes.GAMEPAD) if('click' in group['buttons'] and group['buttons']['click'] != None): evm.setButtonAction(SCButtons.LPAD, group['buttons']['click'], Modes.GAMEPAD) + elif(group['mode'] == StickModes.AXIS): + evm.setStickAxes(*[axis[0] for axis in group['axes']]) print('--- Joystick configured') if('active' in config['button_diamond']): From a5bb3d6a9c784421041a84313d4486878fccf2ea Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sat, 11 Feb 2017 23:45:40 -0500 Subject: [PATCH 082/104] scripts/sc-configurable.py: Moved joystick, button diamond, and "switch group" event setting to functions --- scripts/sc-configurable.py | 47 +++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 17acbb8..26fd4ba 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -301,6 +301,31 @@ def set_trackpad_config(evm, pos, config): # {{{ evm.setButtonAction(button, config['buttons']['click'], Modes.GAMEPAD) # }}} +def set_joystick_config(evm, config): # {{{ + if(config['mode'] == StickModes.BUTTON): + evm.setStickButtons([config['buttons']['north'], config['buttons']['west'], config['buttons']['south'], config['buttons']['east']], Modes.GAMEPAD) + if('click' in config['buttons'] and config['buttons']['click'] != None): + evm.setButtonAction(SCButtons.LPAD, config['buttons']['click'], Modes.GAMEPAD) + elif(config['mode'] == StickModes.AXIS): + evm.setStickAxes(*[axis[0] for axis in config['axes']]) +# }}} + +def set_diamond_config(evm, config): # {{{ + evm.setButtonAction(SCButtons.A, config['buttons']['a'], Modes.GAMEPAD) + evm.setButtonAction(SCButtons.B, config['buttons']['b'], Modes.GAMEPAD) + evm.setButtonAction(SCButtons.X, config['buttons']['x'], Modes.GAMEPAD) + evm.setButtonAction(SCButtons.Y, config['buttons']['y'], Modes.GAMEPAD) +# }}} + +def set_switches_config(evm, config): # {{{ + evm.setButtonAction(SCButtons.LB, config['buttons']['left_bumper'], Modes.GAMEPAD) + evm.setButtonAction(SCButtons.RB, config['buttons']['right_bumper'], Modes.GAMEPAD) + evm.setButtonAction(SCButtons.START, config['buttons']['start'], Modes.GAMEPAD) + evm.setButtonAction(SCButtons.BACK, config['buttons']['back'], Modes.GAMEPAD) + evm.setButtonAction(SCButtons.LGRIP, config['buttons']['left_grip'], Modes.GAMEPAD) + evm.setButtonAction(SCButtons.RGRIP, config['buttons']['right_grip'], Modes.GAMEPAD) +# }}} + def set_trigger_config(evm, pos, config): # {{{ if(config['mode'] == TrigModes.BUTTON): evm.setTrigButton(pos, config['buttons']['click'], Modes.GAMEPAD) @@ -333,31 +358,15 @@ def evminit(config_file_path): print('--- Right trackpad configured') if('active' in config['joystick']): - group = config['joystick']['active'] - if(group['mode'] == StickModes.BUTTON): - evm.setStickButtons([group['buttons']['north'], group['buttons']['west'], group['buttons']['south'], group['buttons']['east']], Modes.GAMEPAD) - if('click' in group['buttons'] and group['buttons']['click'] != None): - evm.setButtonAction(SCButtons.LPAD, group['buttons']['click'], Modes.GAMEPAD) - elif(group['mode'] == StickModes.AXIS): - evm.setStickAxes(*[axis[0] for axis in group['axes']]) + set_joystick_config(evm, config['joystick']['active']) print('--- Joystick configured') if('active' in config['button_diamond']): - group = config['button_diamond']['active'] - evm.setButtonAction(SCButtons.A, group['buttons']['a'], Modes.GAMEPAD) - evm.setButtonAction(SCButtons.B, group['buttons']['b'], Modes.GAMEPAD) - evm.setButtonAction(SCButtons.X, group['buttons']['x'], Modes.GAMEPAD) - evm.setButtonAction(SCButtons.Y, group['buttons']['y'], Modes.GAMEPAD) + set_diamond_config(evm, config['button_diamond']['active']) print('--- Button diamond configured') if('active' in config['switch']): - group = config['switch']['active'] - evm.setButtonAction(SCButtons.LB, group['buttons']['left_bumper'], Modes.GAMEPAD) - evm.setButtonAction(SCButtons.RB, group['buttons']['right_bumper'], Modes.GAMEPAD) - evm.setButtonAction(SCButtons.START, group['buttons']['start'], Modes.GAMEPAD) - evm.setButtonAction(SCButtons.BACK, group['buttons']['back'], Modes.GAMEPAD) - evm.setButtonAction(SCButtons.LGRIP, group['buttons']['left_grip'], Modes.GAMEPAD) - evm.setButtonAction(SCButtons.RGRIP, group['buttons']['right_grip'], Modes.GAMEPAD) + set_switches_config(evm, config['switch']['active']) print('--- Switches configured') if('active' in config['left_trigger']): From 9f23fa3177a6a1fca218fd92a813f6a7b3ba56f2 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 12 Feb 2017 01:14:41 -0500 Subject: [PATCH 083/104] scripts/sc-configurable.py: Added most of modeshifting support --- scripts/sc-configurable.py | 86 ++++++++++++++++++++++++++++++++------ 1 file changed, 73 insertions(+), 13 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 26fd4ba..686117f 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -73,10 +73,10 @@ def load_vdf(path): # {{{ def get_binding(group_inputs, input_name, activator): # {{{ try: activator = group_inputs[input_name]['activators'][activator] - if(type(activator) == list): - # TODO: Support multiples - activator = activator[0] - binding = activator['bindings']['binding'].split() + # TODO: Proper support for multiples + if(type(activator) != list): + activator = [activator] + binding = activator[0]['bindings']['binding'].split() except KeyError: return None @@ -100,6 +100,8 @@ def get_binding(group_inputs, input_name, activator): # {{{ return None elif(binding[0] == 'mouse_button'): return Keys.__getattr__('BTN_' + binding[1]) + elif(binding[0] == 'mode_shift'): + return [a['bindings']['binding'].split()[1] for a in activator] return None # }}} @@ -193,16 +195,24 @@ def parse_config(config): # {{{ if('left_trackpad active' in bindings): output_config['left_trackpad']['active'] = parse_trackpad_config(groups[bindings['left_trackpad active']], Pos.LEFT) + if('left_trackpad active modeshift' in bindings): + output_config['left_trackpad']['modeshift'] = parse_trackpad_config(groups[bindings['left_trackpad active modeshift']], Pos.LEFT) print('--- Left trackpad (active) loaded') if('right_trackpad active' in bindings): output_config['right_trackpad']['active'] = parse_trackpad_config(groups[bindings['right_trackpad active']], Pos.RIGHT) + if('right_trackpad active modeshift' in bindings): + output_config['right_trackpad']['modeshift'] = parse_trackpad_config(groups[bindings['right_trackpad active modeshift']], Pos.RIGHT) print('--- Right trackpad (active) loaded') if('joystick active' in bindings): group = groups[bindings['joystick active']] output_config['joystick']['active'] = parse_joystick_config(group) output_config['joystick']['active']['buttons']['click'] = get_binding(group['inputs'], 'click', 'Full_Press') + if('joystick active modeshift' in bindings): + group = groups[bindings['joystick active modeshift']] + output_config['joystick']['modeshift'] = parse_joystick_config(group) + output_config['joystick']['modeshift']['buttons']['click'] = get_binding(group['inputs'], 'click', 'Full_Press') print('--- Joystick (active) loaded') if('button_diamond active' in bindings): @@ -213,6 +223,14 @@ def parse_config(config): # {{{ 'x' : get_binding(inputs, 'button_x', 'Full_Press'), 'y' : get_binding(inputs, 'button_y', 'Full_Press') }} + if('button_diamond active modeshift' in bindings): + inputs = groups[bindings['button_diamond active modeshift']]['inputs'] + output_config['button_diamond']['modeshift'] = {'buttons' : { + 'a' : get_binding(inputs, 'button_a', 'Full_Press'), + 'b' : get_binding(inputs, 'button_b', 'Full_Press'), + 'x' : get_binding(inputs, 'button_x', 'Full_Press'), + 'y' : get_binding(inputs, 'button_y', 'Full_Press') + }} print('--- Button diamond (active) loaded') if('switch active' in bindings): @@ -225,16 +243,32 @@ def parse_config(config): # {{{ 'left_grip' : get_binding(inputs, 'button_back_left', 'Full_Press'), 'right_grip' : get_binding(inputs, 'button_back_right', 'Full_Press') }} + if('switch active modeshift' in bindings): + inputs = groups[bindings['switch active modeshift']]['inputs'] + output_config['switch']['modeshift'] = {'buttons' : { + 'left_bumper' : get_binding(inputs, 'left_bumper', 'Full_Press'), + 'right_bumper' : get_binding(inputs, 'right_bumper', 'Full_Press'), + 'start' : get_binding(inputs, 'button_escape', 'Full_Press'), + 'back' : get_binding(inputs, 'button_menu', 'Full_Press'), + 'left_grip' : get_binding(inputs, 'button_back_left', 'Full_Press'), + 'right_grip' : get_binding(inputs, 'button_back_right', 'Full_Press') + }} print('--- Switches (active) loaded') if('left_trigger active' in bindings): group_id = bindings['left_trigger active'] output_config['left_trigger']['active'] = parse_trigger_config(groups[bindings['left_trigger active']]) + if('left_trigger active modeshift' in bindings): + group_id = bindings['left_trigger active modeshift'] + output_config['left_trigger']['modeshift'] = parse_trigger_config(groups[bindings['left_trigger active modeshift']]) print('--- Left trigger (active) loaded') if('right_trigger active' in bindings): group_id = bindings['right_trigger active'] output_config['right_trigger']['active'] = parse_trigger_config(groups[bindings['right_trigger active']]) + if('right_trigger active modeshift' in bindings): + group_id = bindings['right_trigger active modeshift'] + output_config['right_trigger']['modeshift'] = parse_trigger_config(groups[bindings['right_trigger active modeshift']]) print('--- Right trigger (active) loaded') return output_config @@ -246,7 +280,7 @@ def get_keys_from_config(config): # {{{ for mode in group.values(): if('buttons' in mode): for button in mode['buttons'].values(): - if(button != None): + if(button != None and type(button) != list): buttons.append(button) buttons = list(set(buttons)) return buttons @@ -283,6 +317,24 @@ def get_modes_from_config(config): # {{{ return list(modes) # }}} +def modeshift(evm, sections, pressed, config): # {{{ + group = 'modeshift' if pressed else 'active' + if('left_trackpad' in sections and group in config['left_trackpad']): + set_trackpad_config(evm, Pos.LEFT, config['left_trackpad'][group]) + if('right_trackpad' in sections and group in config['right_trackpad']): + set_trackpad_config(evm, Pos.RIGHT, config['right_trackpad'][group]) + if('joystick' in sections and group in config['joystick']): + set_joystick_config(evm, config['joystick'][group]) + if('button_diamond' in sections and group in config['button_diamond']): + set_diamond_config(evm, config['button_diamond'][group]) + if('switch' in sections and group in config['switch']): + set_switches_config(evm, config['switch'][group], config, False) + if('left_trigger' in sections and group in config['left_trigger']): + set_trigger_config(evm, Pos.LEFT, config['left_trigger'][group]) + if('right_trigger' in sections and group in config['right_trigger']): + set_trigger_config(evm, Pos.RIGHT, config['right_trigger'][group]) +# }}} + def set_trackpad_config(evm, pos, config): # {{{ button = SCButtons.RPAD if pos == Pos.RIGHT else SCButtons.LPAD if(config['mode'] == PadModes.MOUSE): @@ -317,13 +369,21 @@ def set_diamond_config(evm, config): # {{{ evm.setButtonAction(SCButtons.Y, config['buttons']['y'], Modes.GAMEPAD) # }}} -def set_switches_config(evm, config): # {{{ - evm.setButtonAction(SCButtons.LB, config['buttons']['left_bumper'], Modes.GAMEPAD) - evm.setButtonAction(SCButtons.RB, config['buttons']['right_bumper'], Modes.GAMEPAD) - evm.setButtonAction(SCButtons.START, config['buttons']['start'], Modes.GAMEPAD) - evm.setButtonAction(SCButtons.BACK, config['buttons']['back'], Modes.GAMEPAD) - evm.setButtonAction(SCButtons.LGRIP, config['buttons']['left_grip'], Modes.GAMEPAD) - evm.setButtonAction(SCButtons.RGRIP, config['buttons']['right_grip'], Modes.GAMEPAD) +def set_switches_config(evm, group, config, do_modeshifts): # {{{ + evm.setButtonAction(SCButtons.LB, group['buttons']['left_bumper'], Modes.GAMEPAD) + evm.setButtonAction(SCButtons.RB, group['buttons']['right_bumper'], Modes.GAMEPAD) + evm.setButtonAction(SCButtons.START, group['buttons']['start'], Modes.GAMEPAD) + evm.setButtonAction(SCButtons.BACK, group['buttons']['back'], Modes.GAMEPAD) + if(type(group['buttons']['left_grip']) == list): + if(do_modeshifts): + evm.setButtonCallback(SCButtons.LGRIP, lambda evm, btn, pressed: modeshift(evm, group['buttons']['left_grip'], pressed, config)) + else: + evm.setButtonAction(SCButtons.LGRIP, group['buttons']['left_grip'], Modes.GAMEPAD) + if(type(group['buttons']['right_grip']) == list): + if(do_modeshifts): + evm.setButtonCallback(SCButtons.RGRIP, lambda evm, btn, pressed: modeshift(evm, group['buttons']['right_grip'], pressed, config)) + else: + evm.setButtonAction(SCButtons.RGRIP, group['buttons']['right_grip'], Modes.GAMEPAD) # }}} def set_trigger_config(evm, pos, config): # {{{ @@ -366,7 +426,7 @@ def evminit(config_file_path): print('--- Button diamond configured') if('active' in config['switch']): - set_switches_config(evm, config['switch']['active']) + set_switches_config(evm, config['switch']['active'], config, True) print('--- Switches configured') if('active' in config['left_trigger']): From 67cfb6b2a539caf661e90cc85e6df2e7940d6e8d Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 12 Feb 2017 01:15:11 -0500 Subject: [PATCH 084/104] scripts/sc-configurable.py: Added a few more hardcoded hacks to get_binding() --- scripts/sc-configurable.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 686117f..a7f8195 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -89,6 +89,12 @@ def get_binding(group_inputs, input_name, activator): # {{{ if(binding[1] == 'PERIOD'): binding[1] = 'DOT' + elif(binding[1] == 'ESCAPE'): + binding[1] = 'ESC' + elif(binding[1] == 'DASH'): + binding[1] = 'MINUS' + elif(binding[1] == 'EQUALS'): + binding[1] = 'EQUAL' # Holy crap, the hacks don't get much uglier than this. Add 0x100 to # all KEY_ constants, because the keyboard ends at 0xff and that From a96d5faaa6541164492220d818f31706b5faeabc Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 12 Feb 2017 01:15:39 -0500 Subject: [PATCH 085/104] scripts/sc-configurable.py: Fixed button diamond mode in parse_trackpad_config() --- scripts/sc-configurable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index a7f8195..323ae5d 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -145,7 +145,7 @@ def parse_trackpad_config(group, pos): # {{{ elif(group['mode'] == 'dpad'): config['mode'] = PadModes.BUTTONCLICK config['buttons'] = get_dpad_inputs(group['inputs']) - elif(group['mode'] == 'buttons'): + elif(group['mode'] == 'four_buttons'): config['mode'] = PadModes.BUTTONCLICK config['buttons'] = get_diamond_inputs(group['inputs']) elif(group['mode'] == 'mouse_joystick'): From 64b8e20f1c07eae680d9591ff8cca7e9a2c95c63 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 12 Feb 2017 10:44:01 -0500 Subject: [PATCH 086/104] + src/config.py; currently, this only contains json2vdf() and vdf2json() --- src/config.py | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 src/config.py diff --git a/src/config.py b/src/config.py new file mode 100644 index 0000000..d3c8bb5 --- /dev/null +++ b/src/config.py @@ -0,0 +1,90 @@ +# The MIT License (MIT) +# +# Copyright (c) 2017 Mike Cronce +# Stany MARCEL +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +import shlex + +def vdf2json(stream): # {{{ + """ + Read a Steam vdf file and return a string in json format + """ + + def _istr(ident, string): + return (ident * ' ') + string + + jbuf = '{\n' + lex = shlex.shlex(stream) + indent = 1 + + while True: + tok = lex.get_token() + if not tok: + return jbuf + '}\n' + if tok == '}': + indent -= 1 + jbuf += _istr(indent, '}') + ntok = lex.get_token() + lex.push_token(ntok) + if ntok and ntok != '}': + jbuf += ',' + jbuf += '\n' + else: + ntok = lex.get_token() + if ntok == '{': + jbuf += _istr(indent, tok + ': {\n') + indent += 1 + else: + jbuf += _istr(indent, tok + ': ' + ntok) + ntok = lex.get_token() + lex.push_token(ntok) + if ntok != '}': + jbuf += ',' + jbuf += '\n' +# }}} + +def json2vdf(stream): # {{{ + + """ + Read a json file and return a string in Steam vdf format + """ + + def _istr(ident, string): + return (ident * '\t') + string + + data = json.loads(stream.read(), object_pairs_hook=list) + + def _json2vdf(data, indent): + out = '' + for k, val in data: + if isinstance(val, list): + if indent: + out += '\n' + out += _istr(indent, '"{}"\n'.format(k)) + out += _istr(indent, '{\n') + out += _json2vdf(val, indent + 1) + out += _istr(indent, '}\n') + else: + out += _istr(indent, '"{}" "{}"\n'.format(k, val)) + return out + return _json2vdf(data, 0) +# }}} + From efe6ed987bf01bbed1d0f17b44dfc1a6cab81efd Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 12 Feb 2017 10:44:38 -0500 Subject: [PATCH 087/104] scripts/json2vdf.py and scripts/vdf2json.py: Changed these to call steamcontroller.config.json2vdf() and steamcontroller.config.vdf2json(), respectively --- scripts/json2vdf.py | 31 ++----------------------------- scripts/vdf2json.py | 42 ++---------------------------------------- 2 files changed, 4 insertions(+), 69 deletions(-) diff --git a/scripts/json2vdf.py b/scripts/json2vdf.py index ab89818..2812ab6 100755 --- a/scripts/json2vdf.py +++ b/scripts/json2vdf.py @@ -24,40 +24,13 @@ import json -def json2vdf(stream): - - """ - Read a json file and return a string in Steam vdf format - """ - - def _istr(ident, string): - return (ident * '\t') + string - - data = json.loads(stream.read(), object_pairs_hook=list) - - def _json2vdf(data, indent): - out = '' - for k, val in data: - if isinstance(val, list): - if indent: - out += '\n' - out += _istr(indent, '"{}"\n'.format(k)) - out += _istr(indent, '{\n') - out += _json2vdf(val, indent + 1) - out += _istr(indent, '}\n') - else: - out += _istr(indent, '"{}" "{}"\n'.format(k, val)) - return out - - return _json2vdf(data, 0) - - def main(): """ Read json and write Steam vdf conversion """ import sys import argparse + import steamcontroller.config parser = argparse.ArgumentParser(prog='json2vdf', description=main.__doc__) parser.add_argument('-i', '--input', default=sys.stdin, @@ -69,7 +42,7 @@ def main(): help='output vdf file (stdout if not specified)') args = parser.parse_args() - args.output.write(json2vdf(args.input)) + args.output.write(steamcontroller.config.json2vdf(args.input)) if __name__ == '__main__': main() diff --git a/scripts/vdf2json.py b/scripts/vdf2json.py index 9ccff6d..4a2e374 100755 --- a/scripts/vdf2json.py +++ b/scripts/vdf2json.py @@ -22,51 +22,13 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from shlex import shlex - -def vdf2json(stream): - - """ - Read a Steam vdf file and return a string in json format - """ - - def _istr(ident, string): - return (ident * ' ') + string - - jbuf = '{\n' - lex = shlex(stream) - indent = 1 - - while True: - tok = lex.get_token() - if not tok: - return jbuf + '}\n' - if tok == '}': - indent -= 1 - jbuf += _istr(indent, '}') - ntok = lex.get_token() - lex.push_token(ntok) - if ntok and ntok != '}': - jbuf += ',' - jbuf += '\n' - else: - ntok = lex.get_token() - if ntok == '{': - jbuf += _istr(indent, tok + ': {\n') - indent += 1 - else: - jbuf += _istr(indent, tok + ': ' + ntok) - ntok = lex.get_token() - lex.push_token(ntok) - if ntok != '}': - jbuf += ',' - jbuf += '\n' def main(): """ Read Steam vdf and write json compatible conversion """ import sys import argparse + import steamcontroller.config parser = argparse.ArgumentParser(prog='vdf2json', description=main.__doc__) parser.add_argument('-i', '--input', @@ -79,7 +41,7 @@ def main(): help='output json file (stdout if not specified)') args = parser.parse_args() - args.output.write(vdf2json(args.input)) + args.output.write(steamcontroller.config.vdf2json(args.input)) if __name__ == '__main__': main() From d9ee3279bb3b48db9879f08058c6aac85a00f4a0 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 12 Feb 2017 14:21:38 -0500 Subject: [PATCH 088/104] Refactored such that all the business logic from scripts/sc-configurable.py is now in src/config.py, primarily but not entirely in a class called Configurator --- scripts/sc-configurable.py | 432 +---------------------------------- src/config.py | 446 +++++++++++++++++++++++++++++++++++++ 2 files changed, 453 insertions(+), 425 deletions(-) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 323ae5d..60fd0d2 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -25,429 +25,11 @@ """Steam Controller VDF-configurable mode""" -from steamcontroller import SteamController, SCButtons -from steamcontroller.events import EventMapper, Modes, StickModes, PadModes, Pos, TrigModes -from steamcontroller.uinput import Axes, Keys, Scans - +from steamcontroller import SteamController +from steamcontroller.config import Configurator from steamcontroller.daemon import Daemon import gc -import json -import os - -import vdf2json - -def join_duplicate_keys(ordered_pairs): # {{{ - d = {} - for k, v in ordered_pairs: - if k in d: - if(type(d[k]) == list): - d[k].append(v) - else: - newlist = [] - newlist.append(d[k]) - newlist.append(v) - d[k] = newlist - else: - d[k] = v - return d -# }}} - -def load_vdf(path): # {{{ - f = open(path, 'r') - obj = json.loads(vdf2json.vdf2json(f), object_pairs_hook = join_duplicate_keys) - - # Since /controller_mappings/group is a key duplicated numerous times, it - # makes it cumbersome to use. This changes /controller_mappings/group - # to be a single-use key with a dict in it; each object in the dict is a - # one of these separate "group" objects, and the keys to the dict are - # the "id" fields of these objects. - obj['controller_mappings']['group'] = {group['id'] : group for group in obj['controller_mappings']['group']} - - # ID -> binding doesn't really do us any good. Flip it. - obj['controller_mappings']['preset']['group_source_bindings'] = {value : key for key, value in obj['controller_mappings']['preset']['group_source_bindings'].items()} - - return obj -# }}} - -def get_binding(group_inputs, input_name, activator): # {{{ - try: - activator = group_inputs[input_name]['activators'][activator] - # TODO: Proper support for multiples - if(type(activator) != list): - activator = [activator] - binding = activator[0]['bindings']['binding'].split() - except KeyError: - return None - - # TODO: mode_shift ... maybe more? - if(binding[0] == 'key_press'): - # Ugly - binding[1] = binding[1].replace('_ARROW', '') - binding[1] = binding[1].replace('_', '') - binding[1] = binding[1].replace(',', '') # Items such as "key_press W, w"; everything after the comma is already trimmed by split() above, ignore trailing items for now' - - if(binding[1] == 'PERIOD'): - binding[1] = 'DOT' - elif(binding[1] == 'ESCAPE'): - binding[1] = 'ESC' - elif(binding[1] == 'DASH'): - binding[1] = 'MINUS' - elif(binding[1] == 'EQUALS'): - binding[1] = 'EQUAL' - - # Holy crap, the hacks don't get much uglier than this. Add 0x100 to - # all KEY_ constants, because the keyboard ends at 0xff and that - # seems to make the uinput subsystem happy about considering this - # to be a gamepad/joystick. - return Keys.__getattr__('KEY_' + binding[1]) + 0x100 - elif(binding[0] == 'mouse_wheel'): - # TODO: Figure out if we actually need this; if so, add support - return None - elif(binding[0] == 'mouse_button'): - return Keys.__getattr__('BTN_' + binding[1]) - elif(binding[0] == 'mode_shift'): - return [a['bindings']['binding'].split()[1] for a in activator] - - return None -# }}} - -def get_dpad_inputs(group): # {{{ - return { - 'north' : get_binding(group, 'dpad_north', 'Full_Press'), - 'west' : get_binding(group, 'dpad_west', 'Full_Press'), - 'south' : get_binding(group, 'dpad_south', 'Full_Press'), - 'east' : get_binding(group, 'dpad_east', 'Full_Press') - } -# }}} - -def get_diamond_inputs(group): # {{{ - return { - 'north' : get_binding(group, 'button_y', 'Full_Press'), - 'west' : get_binding(group, 'button_x', 'Full_Press'), - 'south' : get_binding(group, 'button_b', 'Full_Press'), - 'east' : get_binding(group, 'button_a', 'Full_Press') - } -# }}} - -def parse_trackpad_config(group, pos): # {{{ - config = {} - if(group['mode'] == 'absolute_mouse'): - config['mode'] = PadModes.MOUSE - config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} - elif(group['mode'] == 'mouse_region'): - # TODO: Implement - config['mode'] = PadModes.NOACTION - pass - elif(group['mode'] == 'scrollwheel'): - config['mode'] = PadModes.MOUSESCROLL - config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} - elif(group['mode'] == 'dpad'): - config['mode'] = PadModes.BUTTONCLICK - config['buttons'] = get_dpad_inputs(group['inputs']) - elif(group['mode'] == 'four_buttons'): - config['mode'] = PadModes.BUTTONCLICK - config['buttons'] = get_diamond_inputs(group['inputs']) - elif(group['mode'] == 'mouse_joystick'): - config['mode'] = PadModes.AXIS - config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} - axes = [Axes.ABS_HAT0X, Axes.ABS_HAT0Y] if pos == Pos.LEFT else [Axes.ABS_HAT1X, Axes.ABS_HAT1Y] - config['axes'] = [(axis, -1, 1, 0, 0) for axis in axes] - return config -# }}} - -def parse_joystick_config(group): # {{{ - config = {} - if(group['mode'] == 'joystick_mouse'): - config['mode'] = StickModes.AXIS - config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} - config['axes'] = [(axis, -32768, 32767, 16, 128) for axis in [Axes.ABS_X, Axes.ABS_Y]] - elif(group['mode'] == 'scrollwheel'): - # TODO: Implement - config['mode'] = StickModes.NOACTION - pass - elif(group['mode'] == 'dpad'): - config['mode'] = StickModes.BUTTON - config['buttons'] = get_dpad_inputs(group['inputs']) - elif(group['mode'] == 'buttons'): - config['mode'] = StickModes.BUTTON - config['buttons'] = get_diamond_inputs(group['inputs']) - return config -# }}} - -def parse_trigger_config(group): # {{{ - config = {} - if(group['mode'] == 'trigger'): - config['mode'] = TrigModes.BUTTON - config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} - return config -# }}} - -def parse_config(config): # {{{ - groups = config['controller_mappings']['group'] - bindings = config['controller_mappings']['preset']['group_source_bindings'] - - # TODO: Check/respect all possible "mode" entries in each group - - output_config = { - 'left_trackpad' : {}, - 'right_trackpad' : {}, - 'joystick' : {}, - 'button_diamond' : {}, - 'switch' : {}, - 'left_trigger' : {}, - 'right_trigger' : {} - } - - if('left_trackpad active' in bindings): - output_config['left_trackpad']['active'] = parse_trackpad_config(groups[bindings['left_trackpad active']], Pos.LEFT) - if('left_trackpad active modeshift' in bindings): - output_config['left_trackpad']['modeshift'] = parse_trackpad_config(groups[bindings['left_trackpad active modeshift']], Pos.LEFT) - print('--- Left trackpad (active) loaded') - - if('right_trackpad active' in bindings): - output_config['right_trackpad']['active'] = parse_trackpad_config(groups[bindings['right_trackpad active']], Pos.RIGHT) - if('right_trackpad active modeshift' in bindings): - output_config['right_trackpad']['modeshift'] = parse_trackpad_config(groups[bindings['right_trackpad active modeshift']], Pos.RIGHT) - print('--- Right trackpad (active) loaded') - - if('joystick active' in bindings): - group = groups[bindings['joystick active']] - output_config['joystick']['active'] = parse_joystick_config(group) - output_config['joystick']['active']['buttons']['click'] = get_binding(group['inputs'], 'click', 'Full_Press') - if('joystick active modeshift' in bindings): - group = groups[bindings['joystick active modeshift']] - output_config['joystick']['modeshift'] = parse_joystick_config(group) - output_config['joystick']['modeshift']['buttons']['click'] = get_binding(group['inputs'], 'click', 'Full_Press') - print('--- Joystick (active) loaded') - - if('button_diamond active' in bindings): - inputs = groups[bindings['button_diamond active']]['inputs'] - output_config['button_diamond']['active'] = {'buttons' : { - 'a' : get_binding(inputs, 'button_a', 'Full_Press'), - 'b' : get_binding(inputs, 'button_b', 'Full_Press'), - 'x' : get_binding(inputs, 'button_x', 'Full_Press'), - 'y' : get_binding(inputs, 'button_y', 'Full_Press') - }} - if('button_diamond active modeshift' in bindings): - inputs = groups[bindings['button_diamond active modeshift']]['inputs'] - output_config['button_diamond']['modeshift'] = {'buttons' : { - 'a' : get_binding(inputs, 'button_a', 'Full_Press'), - 'b' : get_binding(inputs, 'button_b', 'Full_Press'), - 'x' : get_binding(inputs, 'button_x', 'Full_Press'), - 'y' : get_binding(inputs, 'button_y', 'Full_Press') - }} - print('--- Button diamond (active) loaded') - - if('switch active' in bindings): - inputs = groups[bindings['switch active']]['inputs'] - output_config['switch']['active'] = {'buttons' : { - 'left_bumper' : get_binding(inputs, 'left_bumper', 'Full_Press'), - 'right_bumper' : get_binding(inputs, 'right_bumper', 'Full_Press'), - 'start' : get_binding(inputs, 'button_escape', 'Full_Press'), - 'back' : get_binding(inputs, 'button_menu', 'Full_Press'), - 'left_grip' : get_binding(inputs, 'button_back_left', 'Full_Press'), - 'right_grip' : get_binding(inputs, 'button_back_right', 'Full_Press') - }} - if('switch active modeshift' in bindings): - inputs = groups[bindings['switch active modeshift']]['inputs'] - output_config['switch']['modeshift'] = {'buttons' : { - 'left_bumper' : get_binding(inputs, 'left_bumper', 'Full_Press'), - 'right_bumper' : get_binding(inputs, 'right_bumper', 'Full_Press'), - 'start' : get_binding(inputs, 'button_escape', 'Full_Press'), - 'back' : get_binding(inputs, 'button_menu', 'Full_Press'), - 'left_grip' : get_binding(inputs, 'button_back_left', 'Full_Press'), - 'right_grip' : get_binding(inputs, 'button_back_right', 'Full_Press') - }} - print('--- Switches (active) loaded') - - if('left_trigger active' in bindings): - group_id = bindings['left_trigger active'] - output_config['left_trigger']['active'] = parse_trigger_config(groups[bindings['left_trigger active']]) - if('left_trigger active modeshift' in bindings): - group_id = bindings['left_trigger active modeshift'] - output_config['left_trigger']['modeshift'] = parse_trigger_config(groups[bindings['left_trigger active modeshift']]) - print('--- Left trigger (active) loaded') - - if('right_trigger active' in bindings): - group_id = bindings['right_trigger active'] - output_config['right_trigger']['active'] = parse_trigger_config(groups[bindings['right_trigger active']]) - if('right_trigger active modeshift' in bindings): - group_id = bindings['right_trigger active modeshift'] - output_config['right_trigger']['modeshift'] = parse_trigger_config(groups[bindings['right_trigger active modeshift']]) - print('--- Right trigger (active) loaded') - - return output_config -# }}} - -def get_keys_from_config(config): # {{{ - buttons = [] - for group in config.values(): - for mode in group.values(): - if('buttons' in mode): - for button in mode['buttons'].values(): - if(button != None and type(button) != list): - buttons.append(button) - buttons = list(set(buttons)) - return buttons -# }}} - -def get_axes_from_config(config): # {{{ - axes = [] - for group in config.values(): - for mode in group.values(): - if('axes' in mode): - for axis in mode['axes']: - if(axis != None): - axes.append(axis) - axes = list(set(axes)) - return axes -# }}} - -def get_modes_from_config(config): # {{{ - modes = set() - for group in config.values(): - for mode in group.values(): - if('buttons' in mode): - modes.add(Modes.GAMEPAD) - break - if(Modes.GAMEPAD in modes): - break - for group in ['left_trackpad', 'right_trackpad']: - for mode in config[group].values(): - if(mode['mode'] == PadModes.MOUSE): - modes.add(Modes.MOUSE) - break - if(Modes.MOUSE in modes): - break - return list(modes) -# }}} - -def modeshift(evm, sections, pressed, config): # {{{ - group = 'modeshift' if pressed else 'active' - if('left_trackpad' in sections and group in config['left_trackpad']): - set_trackpad_config(evm, Pos.LEFT, config['left_trackpad'][group]) - if('right_trackpad' in sections and group in config['right_trackpad']): - set_trackpad_config(evm, Pos.RIGHT, config['right_trackpad'][group]) - if('joystick' in sections and group in config['joystick']): - set_joystick_config(evm, config['joystick'][group]) - if('button_diamond' in sections and group in config['button_diamond']): - set_diamond_config(evm, config['button_diamond'][group]) - if('switch' in sections and group in config['switch']): - set_switches_config(evm, config['switch'][group], config, False) - if('left_trigger' in sections and group in config['left_trigger']): - set_trigger_config(evm, Pos.LEFT, config['left_trigger'][group]) - if('right_trigger' in sections and group in config['right_trigger']): - set_trigger_config(evm, Pos.RIGHT, config['right_trigger'][group]) -# }}} - -def set_trackpad_config(evm, pos, config): # {{{ - button = SCButtons.RPAD if pos == Pos.RIGHT else SCButtons.LPAD - if(config['mode'] == PadModes.MOUSE): - evm.setPadMouse(pos) - evm.setButtonAction(button, config['buttons']['click'], Modes.GAMEPAD) - elif(config['mode'] == PadModes.MOUSESCROLL): - # TODO: Support configuration for scroll directions - evm.setPadScroll(pos) - evm.setButtonAction(button, config['buttons']['click'], Modes.GAMEPAD) - elif(config['mode'] == PadModes.BUTTONCLICK): - # TODO: Configurable whether or not click is required? - buttons = config['buttons'] - evm.setPadButtons(pos, [buttons['north'], buttons['west'], buttons['south'], buttons['east']], clicked = True, mode = Modes.GAMEPAD) - elif(config['mode'] == PadModes.AXIS): - evm.setPadAxes(pos, *[axis[0] for axis in config['axes']]) - evm.setButtonAction(button, config['buttons']['click'], Modes.GAMEPAD) -# }}} - -def set_joystick_config(evm, config): # {{{ - if(config['mode'] == StickModes.BUTTON): - evm.setStickButtons([config['buttons']['north'], config['buttons']['west'], config['buttons']['south'], config['buttons']['east']], Modes.GAMEPAD) - if('click' in config['buttons'] and config['buttons']['click'] != None): - evm.setButtonAction(SCButtons.LPAD, config['buttons']['click'], Modes.GAMEPAD) - elif(config['mode'] == StickModes.AXIS): - evm.setStickAxes(*[axis[0] for axis in config['axes']]) -# }}} - -def set_diamond_config(evm, config): # {{{ - evm.setButtonAction(SCButtons.A, config['buttons']['a'], Modes.GAMEPAD) - evm.setButtonAction(SCButtons.B, config['buttons']['b'], Modes.GAMEPAD) - evm.setButtonAction(SCButtons.X, config['buttons']['x'], Modes.GAMEPAD) - evm.setButtonAction(SCButtons.Y, config['buttons']['y'], Modes.GAMEPAD) -# }}} - -def set_switches_config(evm, group, config, do_modeshifts): # {{{ - evm.setButtonAction(SCButtons.LB, group['buttons']['left_bumper'], Modes.GAMEPAD) - evm.setButtonAction(SCButtons.RB, group['buttons']['right_bumper'], Modes.GAMEPAD) - evm.setButtonAction(SCButtons.START, group['buttons']['start'], Modes.GAMEPAD) - evm.setButtonAction(SCButtons.BACK, group['buttons']['back'], Modes.GAMEPAD) - if(type(group['buttons']['left_grip']) == list): - if(do_modeshifts): - evm.setButtonCallback(SCButtons.LGRIP, lambda evm, btn, pressed: modeshift(evm, group['buttons']['left_grip'], pressed, config)) - else: - evm.setButtonAction(SCButtons.LGRIP, group['buttons']['left_grip'], Modes.GAMEPAD) - if(type(group['buttons']['right_grip']) == list): - if(do_modeshifts): - evm.setButtonCallback(SCButtons.RGRIP, lambda evm, btn, pressed: modeshift(evm, group['buttons']['right_grip'], pressed, config)) - else: - evm.setButtonAction(SCButtons.RGRIP, group['buttons']['right_grip'], Modes.GAMEPAD) -# }}} - -def set_trigger_config(evm, pos, config): # {{{ - if(config['mode'] == TrigModes.BUTTON): - evm.setTrigButton(pos, config['buttons']['click'], Modes.GAMEPAD) -# }}} - -def evminit(config_file_path): - vdf = load_vdf(config_file_path) - config = parse_config(vdf) - - keys = get_keys_from_config(config) - axes = get_axes_from_config(config) - modes = get_modes_from_config(config) - - evm = EventMapper(gamepad_definition = { - 'vendor' : 0x28de, - 'product' : 0x1142, - 'version' : 0x1, - 'name' : b"Steam Controller [" + bytes(os.path.basename(config_file_path), 'utf-8') + b']', - 'keys' : keys, - 'axes' : axes, - 'rels' : [] - }, modes = modes) - - if('active' in config['left_trackpad']): - set_trackpad_config(evm, Pos.LEFT, config['left_trackpad']['active']) - print('--- Left trackpad configured') - - if('active' in config['right_trackpad']): - set_trackpad_config(evm, Pos.RIGHT, config['right_trackpad']['active']) - print('--- Right trackpad configured') - - if('active' in config['joystick']): - set_joystick_config(evm, config['joystick']['active']) - print('--- Joystick configured') - - if('active' in config['button_diamond']): - set_diamond_config(evm, config['button_diamond']['active']) - print('--- Button diamond configured') - - if('active' in config['switch']): - set_switches_config(evm, config['switch']['active'], config, True) - print('--- Switches configured') - - if('active' in config['left_trigger']): - set_trigger_config(evm, Pos.LEFT, config['left_trigger']['active']) - print('--- Left trigger configured') - - if('active' in config['right_trigger']): - set_trigger_config(evm, Pos.RIGHT, config['right_trigger']['active']) - print('--- Right trigger configured') - - # This cannot be configured from the Steam UI. Should we extend that file - # to support configuring it? - evm.setButtonAction(SCButtons.STEAM, Keys.KEY_HOMEPAGE, Modes.GAMEPAD) - - return evm class SCDaemon(Daemon): def __init__(self, pidfile, config_file): @@ -455,11 +37,11 @@ def __init__(self, pidfile, config_file): self.config_file = config_file def run(self): - evm = evminit(self.config_file) - sc = SteamController(callback=evm.process) + config = Configurator('Steam Controller', self.config_file) + sc = SteamController(callback = config.evm.process) sc.run() del sc - del evm + del config gc.collect() if __name__ == '__main__': @@ -485,8 +67,8 @@ def _main(): daemon.restart() elif 'debug' == args.command: try: - evm = evminit(args.config_file) - sc = SteamController(callback=evm.process) + config = Configurator('Steam Controller', args.config_file) + sc = SteamController(callback = config.evm.process) sc.run() except KeyboardInterrupt: return diff --git a/src/config.py b/src/config.py index d3c8bb5..e21f37d 100644 --- a/src/config.py +++ b/src/config.py @@ -21,8 +21,14 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. +import json +import os import shlex +from steamcontroller import SCButtons +from steamcontroller.events import EventMapper, Modes, StickModes, PadModes, Pos, TrigModes +from steamcontroller.uinput import Axes, Keys, Scans + def vdf2json(stream): # {{{ """ Read a Steam vdf file and return a string in json format @@ -88,3 +94,443 @@ def _json2vdf(data, indent): return _json2vdf(data, 0) # }}} +def join_duplicate_keys(ordered_pairs): # {{{ + d = {} + for k, v in ordered_pairs: + if k in d: + if(type(d[k]) == list): + d[k].append(v) + else: + newlist = [] + newlist.append(d[k]) + newlist.append(v) + d[k] = newlist + else: + d[k] = v + return d +# }}} + +def load_vdf(path): # {{{ + f = open(path, 'r') + obj = json.loads(vdf2json(f), object_pairs_hook = join_duplicate_keys) + + # Since /controller_mappings/group is a key duplicated numerous times, it + # makes it cumbersome to use. This changes /controller_mappings/group + # to be a single-use key with a dict in it; each object in the dict is a + # one of these separate "group" objects, and the keys to the dict are + # the "id" fields of these objects. + obj['controller_mappings']['group'] = {group['id'] : group for group in obj['controller_mappings']['group']} + + # ID -> binding doesn't really do us any good. Flip it. + obj['controller_mappings']['preset']['group_source_bindings'] = {value : key for key, value in obj['controller_mappings']['preset']['group_source_bindings'].items()} + + return obj +# }}} + +def get_binding(group_inputs, input_name, activator): # {{{ + try: + activator = group_inputs[input_name]['activators'][activator] + # TODO: Proper support for multiples + if(type(activator) != list): + activator = [activator] + binding = activator[0]['bindings']['binding'].split() + except KeyError: + return None + + # TODO: mode_shift ... maybe more? + if(binding[0] == 'key_press'): + # Ugly + binding[1] = binding[1].replace('_ARROW', '') + binding[1] = binding[1].replace('_', '') + binding[1] = binding[1].replace(',', '') # Items such as "key_press W, w"; everything after the comma is already trimmed by split() above, ignore trailing items for now' + + if(binding[1] == 'PERIOD'): + binding[1] = 'DOT' + elif(binding[1] == 'ESCAPE'): + binding[1] = 'ESC' + elif(binding[1] == 'DASH'): + binding[1] = 'MINUS' + elif(binding[1] == 'EQUALS'): + binding[1] = 'EQUAL' + + # Holy crap, the hacks don't get much uglier than this. Add 0x100 to + # all KEY_ constants, because the keyboard ends at 0xff and that + # seems to make the uinput subsystem happy about considering this + # to be a gamepad/joystick. + return Keys.__getattr__('KEY_' + binding[1]) + 0x100 + elif(binding[0] == 'mouse_wheel'): + # TODO: Figure out if we actually need this; if so, add support + return None + elif(binding[0] == 'mouse_button'): + return Keys.__getattr__('BTN_' + binding[1]) + elif(binding[0] == 'mode_shift'): + return [a['bindings']['binding'].split()[1] for a in activator] + + return None +# }}} + +def get_dpad_inputs(group): # {{{ + return { + 'north' : get_binding(group, 'dpad_north', 'Full_Press'), + 'west' : get_binding(group, 'dpad_west', 'Full_Press'), + 'south' : get_binding(group, 'dpad_south', 'Full_Press'), + 'east' : get_binding(group, 'dpad_east', 'Full_Press') + } +# }}} + +def get_diamond_inputs(group): # {{{ + return { + 'north' : get_binding(group, 'button_y', 'Full_Press'), + 'west' : get_binding(group, 'button_x', 'Full_Press'), + 'south' : get_binding(group, 'button_b', 'Full_Press'), + 'east' : get_binding(group, 'button_a', 'Full_Press') + } +# }}} + +def parse_trackpad_config(group, pos): # {{{ + config = {} + if(group['mode'] == 'absolute_mouse'): + config['mode'] = PadModes.MOUSE + config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} + elif(group['mode'] == 'mouse_region'): + # TODO: Implement + config['mode'] = PadModes.NOACTION + pass + elif(group['mode'] == 'scrollwheel'): + config['mode'] = PadModes.MOUSESCROLL + config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} + elif(group['mode'] == 'dpad'): + config['mode'] = PadModes.BUTTONCLICK + config['buttons'] = get_dpad_inputs(group['inputs']) + elif(group['mode'] == 'four_buttons'): + config['mode'] = PadModes.BUTTONCLICK + config['buttons'] = get_diamond_inputs(group['inputs']) + elif(group['mode'] == 'mouse_joystick'): + config['mode'] = PadModes.AXIS + config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} + axes = [Axes.ABS_HAT0X, Axes.ABS_HAT0Y] if pos == Pos.LEFT else [Axes.ABS_HAT1X, Axes.ABS_HAT1Y] + config['axes'] = [(axis, -1, 1, 0, 0) for axis in axes] + return config +# }}} + +def parse_joystick_config(group): # {{{ + config = {} + if(group['mode'] == 'joystick_mouse'): + config['mode'] = StickModes.AXIS + config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} + config['axes'] = [(axis, -32768, 32767, 16, 128) for axis in [Axes.ABS_X, Axes.ABS_Y]] + elif(group['mode'] == 'scrollwheel'): + # TODO: Implement + config['mode'] = StickModes.NOACTION + pass + elif(group['mode'] == 'dpad'): + config['mode'] = StickModes.BUTTON + config['buttons'] = get_dpad_inputs(group['inputs']) + elif(group['mode'] == 'buttons'): + config['mode'] = StickModes.BUTTON + config['buttons'] = get_diamond_inputs(group['inputs']) + return config +# }}} + +def parse_trigger_config(group): # {{{ + config = {} + if(group['mode'] == 'trigger'): + config['mode'] = TrigModes.BUTTON + config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} + return config +# }}} + +def parse_config(config): # {{{ + groups = config['controller_mappings']['group'] + bindings = config['controller_mappings']['preset']['group_source_bindings'] + + # TODO: Check/respect all possible "mode" entries in each group + + output_config = { + 'left_trackpad' : {}, + 'right_trackpad' : {}, + 'joystick' : {}, + 'button_diamond' : {}, + 'switch' : {}, + 'left_trigger' : {}, + 'right_trigger' : {} + } + + if('left_trackpad active' in bindings): + output_config['left_trackpad']['active'] = parse_trackpad_config(groups[bindings['left_trackpad active']], Pos.LEFT) + if('left_trackpad active modeshift' in bindings): + output_config['left_trackpad']['modeshift'] = parse_trackpad_config(groups[bindings['left_trackpad active modeshift']], Pos.LEFT) + print('--- Left trackpad (active) loaded') + + if('right_trackpad active' in bindings): + output_config['right_trackpad']['active'] = parse_trackpad_config(groups[bindings['right_trackpad active']], Pos.RIGHT) + if('right_trackpad active modeshift' in bindings): + output_config['right_trackpad']['modeshift'] = parse_trackpad_config(groups[bindings['right_trackpad active modeshift']], Pos.RIGHT) + print('--- Right trackpad (active) loaded') + + if('joystick active' in bindings): + group = groups[bindings['joystick active']] + output_config['joystick']['active'] = parse_joystick_config(group) + output_config['joystick']['active']['buttons']['click'] = get_binding(group['inputs'], 'click', 'Full_Press') + if('joystick active modeshift' in bindings): + group = groups[bindings['joystick active modeshift']] + output_config['joystick']['modeshift'] = parse_joystick_config(group) + output_config['joystick']['modeshift']['buttons']['click'] = get_binding(group['inputs'], 'click', 'Full_Press') + print('--- Joystick (active) loaded') + + if('button_diamond active' in bindings): + inputs = groups[bindings['button_diamond active']]['inputs'] + output_config['button_diamond']['active'] = {'buttons' : { + 'a' : get_binding(inputs, 'button_a', 'Full_Press'), + 'b' : get_binding(inputs, 'button_b', 'Full_Press'), + 'x' : get_binding(inputs, 'button_x', 'Full_Press'), + 'y' : get_binding(inputs, 'button_y', 'Full_Press') + }} + if('button_diamond active modeshift' in bindings): + inputs = groups[bindings['button_diamond active modeshift']]['inputs'] + output_config['button_diamond']['modeshift'] = {'buttons' : { + 'a' : get_binding(inputs, 'button_a', 'Full_Press'), + 'b' : get_binding(inputs, 'button_b', 'Full_Press'), + 'x' : get_binding(inputs, 'button_x', 'Full_Press'), + 'y' : get_binding(inputs, 'button_y', 'Full_Press') + }} + print('--- Button diamond (active) loaded') + + if('switch active' in bindings): + inputs = groups[bindings['switch active']]['inputs'] + output_config['switch']['active'] = {'buttons' : { + 'left_bumper' : get_binding(inputs, 'left_bumper', 'Full_Press'), + 'right_bumper' : get_binding(inputs, 'right_bumper', 'Full_Press'), + 'start' : get_binding(inputs, 'button_escape', 'Full_Press'), + 'back' : get_binding(inputs, 'button_menu', 'Full_Press'), + 'left_grip' : get_binding(inputs, 'button_back_left', 'Full_Press'), + 'right_grip' : get_binding(inputs, 'button_back_right', 'Full_Press') + }} + if('switch active modeshift' in bindings): + inputs = groups[bindings['switch active modeshift']]['inputs'] + output_config['switch']['modeshift'] = {'buttons' : { + 'left_bumper' : get_binding(inputs, 'left_bumper', 'Full_Press'), + 'right_bumper' : get_binding(inputs, 'right_bumper', 'Full_Press'), + 'start' : get_binding(inputs, 'button_escape', 'Full_Press'), + 'back' : get_binding(inputs, 'button_menu', 'Full_Press'), + 'left_grip' : get_binding(inputs, 'button_back_left', 'Full_Press'), + 'right_grip' : get_binding(inputs, 'button_back_right', 'Full_Press') + }} + print('--- Switches (active) loaded') + + if('left_trigger active' in bindings): + group_id = bindings['left_trigger active'] + output_config['left_trigger']['active'] = parse_trigger_config(groups[bindings['left_trigger active']]) + if('left_trigger active modeshift' in bindings): + group_id = bindings['left_trigger active modeshift'] + output_config['left_trigger']['modeshift'] = parse_trigger_config(groups[bindings['left_trigger active modeshift']]) + print('--- Left trigger (active) loaded') + + if('right_trigger active' in bindings): + group_id = bindings['right_trigger active'] + output_config['right_trigger']['active'] = parse_trigger_config(groups[bindings['right_trigger active']]) + if('right_trigger active modeshift' in bindings): + group_id = bindings['right_trigger active modeshift'] + output_config['right_trigger']['modeshift'] = parse_trigger_config(groups[bindings['right_trigger active modeshift']]) + print('--- Right trigger (active) loaded') + + return output_config +# }}} + +class Configurator(): + vdf_path = None + config = None + evm = None + + # These are all used for gamepad definition as passed down the stack, + # through EventMapper, to the Gamepad subclass of UInput + name = None + vendor = 0x28de + product = 0x1142 + version = 0x1 + + def __init__(self, name, vdf_path = None, vendor = 0x28de, product = 0x1142, version = 0x1): # {{{ + self.name = name + self.vdf_path = vdf_path + if(self.vdf_path != None): + self.load_config() + self.generate_eventmapper() + self.vendor = vendor + self.product = product + self.version = version + # }}} + + def load_config(self): # {{{ + self.config = parse_config(load_vdf(self.vdf_path)) + # }}} + + def generate_gamepad_definition(self): # {{{ + return { + 'vendor' : self.vendor, + 'product' : self.product, + 'version' : self.version, + 'name' : bytes(self.name + ((' [' + os.path.basename(self.vdf_path) + ']') if self.vdf_path != None else ''), 'utf-8'), + 'keys' : self.get_keys(), + 'axes' : self.get_axes(), + 'rels' : [] + } + # }}} + + def generate_eventmapper(self): # {{{ + assert self.config != None + self.evm = EventMapper(gamepad_definition = self.generate_gamepad_definition(), modes = self.get_modes()) + + if('active' in self.config['left_trackpad']): + self.set_trackpad_config(Pos.LEFT, 'active') + print('--- Left trackpad configured') + + if('active' in self.config['right_trackpad']): + self.set_trackpad_config(Pos.RIGHT, 'active') + print('--- Right trackpad configured') + + if('active' in self.config['joystick']): + self.set_joystick_config('active') + print('--- Joystick configured') + + if('active' in self.config['button_diamond']): + self.set_diamond_config('active') + print('--- Button diamond configured') + + if('active' in self.config['switch']): + self.set_switches_config('active', True) + print('--- Switches configured') + + if('active' in self.config['left_trigger']): + self.set_trigger_config(Pos.LEFT, 'active') + print('--- Left trigger configured') + + if('active' in self.config['right_trigger']): + self.set_trigger_config(Pos.RIGHT, 'active') + print('--- Right trigger configured') + + # This cannot be configured from the Steam UI. Should we extend that file + # to support configuring it? + self.evm.setButtonAction(SCButtons.STEAM, Keys.KEY_HOMEPAGE, Modes.GAMEPAD) + # }}} + + def get_keys(self): # {{{ + buttons = [] + for group in self.config.values(): + for mode in group.values(): + if('buttons' in mode): + for button in mode['buttons'].values(): + if(button != None and type(button) != list): + buttons.append(button) + buttons = list(set(buttons)) + return buttons + # }}} + + def get_axes(self): # {{{ + axes = [] + for group in self.config.values(): + for mode in group.values(): + if('axes' in mode): + for axis in mode['axes']: + if(axis != None): + axes.append(axis) + axes = list(set(axes)) + return axes + # }}} + + def get_modes(self): # {{{ + modes = set() + for group in self.config.values(): + for mode in group.values(): + if('buttons' in mode): + modes.add(Modes.GAMEPAD) + break + if(Modes.GAMEPAD in modes): + break + for group in ['left_trackpad', 'right_trackpad']: + for mode in self.config[group].values(): + if(mode['mode'] == PadModes.MOUSE): + modes.add(Modes.MOUSE) + break + if(Modes.MOUSE in modes): + break + return list(modes) + # }}} + + def modeshift(self, sections, pressed): # {{{ + group = 'modeshift' if pressed else 'active' + if('left_trackpad' in sections and group in self.config['left_trackpad']): + self.set_trackpad_config(Pos.LEFT, group) + if('right_trackpad' in sections and group in self.config['right_trackpad']): + self.set_trackpad_config(Pos.RIGHT, group) + if('joystick' in sections and group in self.config['joystick']): + self.set_joystick_config(group) + if('button_diamond' in sections and group in self.config['button_diamond']): + self.set_diamond_config(group) + if('switch' in sections and group in self.config['switch']): + self.set_switches_config(group, False) + if('left_trigger' in sections and group in self.config['left_trigger']): + self.set_trigger_config(Pos.LEFT, group) + if('right_trigger' in sections and group in self.config['right_trigger']): + self.set_trigger_config(Pos.RIGHT, group) + # }}} + + def set_trackpad_config(self, pos, mode): # {{{ + button = SCButtons.RPAD if pos == Pos.RIGHT else SCButtons.LPAD + group = self.config['right_trackpad'][mode] if pos == Pos.RIGHT else self.config['left_trackpad'][mode] + if(group['mode'] == PadModes.MOUSE): + self.evm.setPadMouse(pos) + self.evm.setButtonAction(button, group['buttons']['click'], Modes.GAMEPAD) + elif(group['mode'] == PadModes.MOUSESCROLL): + # TODO: Support configuration for scroll directions + self.evm.setPadScroll(pos) + self.evm.setButtonAction(button, group['buttons']['click'], Modes.GAMEPAD) + elif(group['mode'] == PadModes.BUTTONCLICK): + # TODO: Configurable whether or not click is required? + buttons = group['buttons'] + self.evm.setPadButtons(pos, [buttons['north'], buttons['west'], buttons['south'], buttons['east']], clicked = True, mode = Modes.GAMEPAD) + elif(group['mode'] == PadModes.AXIS): + self.evm.setPadAxes(pos, *[axis[0] for axis in group['axes']]) + self.evm.setButtonAction(button, group['buttons']['click'], Modes.GAMEPAD) + # }}} + + def set_joystick_config(self, mode): # {{{ + group = self.config['joystick'][mode] + if(group['mode'] == StickModes.BUTTON): + self.evm.setStickButtons([group['buttons']['north'], group['buttons']['west'], group['buttons']['south'], group['buttons']['east']], Modes.GAMEPAD) + if('click' in group['buttons'] and group['buttons']['click'] != None): + self.evm.setButtonAction(SCButtons.LPAD, group['buttons']['click'], Modes.GAMEPAD) + elif(group['mode'] == StickModes.AXIS): + self.evm.setStickAxes(*[axis[0] for axis in group['axes']]) + # }}} + + def set_diamond_config(self, mode): # {{{ + group = self.config['button_diamond'][mode] + self.evm.setButtonAction(SCButtons.A, group['buttons']['a'], Modes.GAMEPAD) + self.evm.setButtonAction(SCButtons.B, group['buttons']['b'], Modes.GAMEPAD) + self.evm.setButtonAction(SCButtons.X, group['buttons']['x'], Modes.GAMEPAD) + self.evm.setButtonAction(SCButtons.Y, group['buttons']['y'], Modes.GAMEPAD) + # }}} + + def set_switches_config(self, mode, assign_modeshifts): # {{{ + group = self.config['switch'][mode] + self.evm.setButtonAction(SCButtons.LB, group['buttons']['left_bumper'], Modes.GAMEPAD) + self.evm.setButtonAction(SCButtons.RB, group['buttons']['right_bumper'], Modes.GAMEPAD) + self.evm.setButtonAction(SCButtons.START, group['buttons']['start'], Modes.GAMEPAD) + self.evm.setButtonAction(SCButtons.BACK, group['buttons']['back'], Modes.GAMEPAD) + if(type(group['buttons']['left_grip']) == list): + if(assign_modeshifts): + self.evm.setButtonCallback(SCButtons.LGRIP, lambda evm, btn, pressed: self.modeshift(group['buttons']['left_grip'], pressed)) + else: + self.evm.setButtonAction(SCButtons.LGRIP, group['buttons']['left_grip'], Modes.GAMEPAD) + if(type(group['buttons']['right_grip']) == list): + if(assign_modeshifts): + self.evm.setButtonCallback(SCButtons.RGRIP, lambda evm, btn, pressed: self.modeshift(group['buttons']['right_grip'], pressed)) + else: + self.evm.setButtonAction(SCButtons.RGRIP, group['buttons']['right_grip'], Modes.GAMEPAD) + # }}} + + def set_trigger_config(self, pos, mode): # {{{ + group = self.config['right_trigger'][mode] if pos == Pos.RIGHT else self.config['left_trigger'][mode] + if(group['mode'] == TrigModes.BUTTON): + self.evm.setTrigButton(pos, group['buttons']['click'], Modes.GAMEPAD) + # }}} From f9dbb4b841aac5d9a6c28c9e9b06642f1299e682 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 12 Feb 2017 14:57:42 -0500 Subject: [PATCH 089/104] src/config.py: Fixed Configurator::get_modes() for MOUSE mode detection --- src/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.py b/src/config.py index e21f37d..3a44cb9 100644 --- a/src/config.py +++ b/src/config.py @@ -448,7 +448,7 @@ def get_modes(self): # {{{ break for group in ['left_trackpad', 'right_trackpad']: for mode in self.config[group].values(): - if(mode['mode'] == PadModes.MOUSE): + if(mode['mode'] in [PadModes.MOUSE, PadModes.MOUSESCROLL]): modes.add(Modes.MOUSE) break if(Modes.MOUSE in modes): From e1b5f1832f8f5ad7fff3a2f6bb2e9a75a3572154 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 12 Feb 2017 15:35:47 -0500 Subject: [PATCH 090/104] src/daemon.py: Added logfile support --- src/daemon.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/daemon.py b/src/daemon.py index 964c765..56aa8d2 100644 --- a/src/daemon.py +++ b/src/daemon.py @@ -18,8 +18,9 @@ class Daemon(object): Usage: subclass the daemon class and override the run() method.""" - def __init__(self, pidfile): + def __init__(self, pidfile, logfile = os.devnull): self.pidfile = pidfile + self.logfile = logfile def daemonize(self): """Deamonize class. UNIX double fork mechanism.""" @@ -42,7 +43,6 @@ def daemonize(self): try: pid = os.fork() if pid > 0: - # exit from second parent sys.exit(0) except OSError as err: @@ -53,8 +53,8 @@ def daemonize(self): sys.stdout.flush() sys.stderr.flush() stdi = open(os.devnull, 'r') - stdo = open(os.devnull, 'a+') - stde = open(os.devnull, 'a+') + stdo = open(self.logfile, 'a+') + stde = open(self.logfile, 'a+') os.dup2(stdi.fileno(), sys.stdin.fileno()) os.dup2(stdo.fileno(), sys.stdout.fileno()) From eebc31b2fd96fa356864c0c7038b401a2c4df594 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 12 Feb 2017 15:36:11 -0500 Subject: [PATCH 091/104] scripts/sc-configurable.py: Added logfile argument to SCDaemon::__init__() --- scripts/sc-configurable.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/sc-configurable.py b/scripts/sc-configurable.py index 60fd0d2..55db5d7 100755 --- a/scripts/sc-configurable.py +++ b/scripts/sc-configurable.py @@ -35,6 +35,7 @@ class SCDaemon(Daemon): def __init__(self, pidfile, config_file): self.pidfile = pidfile self.config_file = config_file + self.logfile = '/var/log/steam-controller.log' def run(self): config = Configurator('Steam Controller', self.config_file) From 2686129f0c5bc6a3f0eb4d07f21c22fb64697250 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 12 Feb 2017 15:44:14 -0500 Subject: [PATCH 092/104] src/config.py: Adjusted trackpad axes for a bit more granularity --- src/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.py b/src/config.py index 3a44cb9..6e5144a 100644 --- a/src/config.py +++ b/src/config.py @@ -209,7 +209,7 @@ def parse_trackpad_config(group, pos): # {{{ config['mode'] = PadModes.AXIS config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} axes = [Axes.ABS_HAT0X, Axes.ABS_HAT0Y] if pos == Pos.LEFT else [Axes.ABS_HAT1X, Axes.ABS_HAT1Y] - config['axes'] = [(axis, -1, 1, 0, 0) for axis in axes] + config['axes'] = [(axis, -8, 7, 2, 2) for axis in axes] return config # }}} From 150592ea8ecb8b7fdb1df57a66b96abf6993fa56 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 12 Feb 2017 20:27:18 -0500 Subject: [PATCH 093/104] src/events.py: Fixed issue with joystick also triggering LPAD axis when both are in axis mode --- src/events.py | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/src/events.py b/src/events.py index f6cf9d0..3357e3c 100644 --- a/src/events.py +++ b/src/events.py @@ -242,16 +242,17 @@ def _keyreleased(mode, ev): click = SCButtons.RPAD if sci.buttons & touch == touch: - # Compute mean pos - try: - xm_p = int(sum(self._xdq[pos]) / len(self._xdq[pos])) - except ZeroDivisionError: - xm_p = 0 - - try: - ym_p = int(sum(self._ydq[pos]) / len(self._ydq[pos])) - except ZeroDivisionError: - ym_p = 0 + if(sci_p.buttons & touch == touch): + # Compute mean pos + try: + xm_p = int(sum(self._xdq[pos]) / len(self._xdq[pos])) + except ZeroDivisionError: + xm_p = 0 + + try: + ym_p = int(sum(self._ydq[pos]) / len(self._ydq[pos])) + except ZeroDivisionError: + ym_p = 0 self._xdq[pos].append(x) self._ydq[pos].append(y) @@ -265,8 +266,10 @@ def _keyreleased(mode, ev): except ZeroDivisionError: ym = 0 - if not sci_p.buttons & touch == touch: + if(not sci_p.buttons & touch == touch): xm_p, ym_p = xm, ym + xm = 0 + ym = 0 # Mouse and mouse scroll modes {{{ if self._pad_modes[pos] in (PadModes.MOUSE, PadModes.MOUSESCROLL): @@ -306,12 +309,19 @@ def _keyreleased(mode, ev): sc.addFeedback(pos, amplitude=100) self._moved[pos] %= 4000 - if x != x_p: - self._uip[xmode].axisEvent(xev, x) - syn.add(xmode) - if y != y_p: - self._uip[ymode].axisEvent(yev, y if not revert else -y) - syn.add(ymode) + if x != x_p: + self._uip[xmode].axisEvent(xev, x) + syn.add(xmode) + if y != y_p: + self._uip[ymode].axisEvent(yev, y if not revert else -y) + syn.add(ymode) + else: + if(x_p != 0): + self._uip[xmode].axisEvent(xev, 0) + syn.add(xmode) + if(y_p != 0): + self._uip[ymode].axisEvent(yev, 0) + syn.add(ymode) # }}} # Button touch mode {{{ From b4db577270f8acd81aa0b84cf33f96f6a0237857 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 12 Feb 2017 21:25:33 -0500 Subject: [PATCH 094/104] src/config.py: Pad axes broadened to (-32768, 32768, 16, 128) --- src/config.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/config.py b/src/config.py index 6e5144a..413d70d 100644 --- a/src/config.py +++ b/src/config.py @@ -209,7 +209,7 @@ def parse_trackpad_config(group, pos): # {{{ config['mode'] = PadModes.AXIS config['buttons'] = {'click' : get_binding(group['inputs'], 'click', 'Full_Press')} axes = [Axes.ABS_HAT0X, Axes.ABS_HAT0Y] if pos == Pos.LEFT else [Axes.ABS_HAT1X, Axes.ABS_HAT1Y] - config['axes'] = [(axis, -8, 7, 2, 2) for axis in axes] + config['axes'] = [(axis, -32768, 32767, 16, 128) for axis in axes] return config # }}} @@ -534,3 +534,4 @@ def set_trigger_config(self, pos, mode): # {{{ if(group['mode'] == TrigModes.BUTTON): self.evm.setTrigButton(pos, group['buttons']['click'], Modes.GAMEPAD) # }}} + From d85e4b7552093a93cbfc03878436cb073a2ebfc7 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 12 Feb 2017 21:59:59 -0500 Subject: [PATCH 095/104] src/config.py: Fixed KEYBOARD mode detection --- src/config.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/config.py b/src/config.py index 413d70d..e9844cb 100644 --- a/src/config.py +++ b/src/config.py @@ -442,9 +442,14 @@ def get_modes(self): # {{{ for group in self.config.values(): for mode in group.values(): if('buttons' in mode): - modes.add(Modes.GAMEPAD) - break - if(Modes.GAMEPAD in modes): + for button in mode['buttons'].values(): + if(button == None or type(button) == list): + continue + if(button < 0x100): + modes.add(Modes.KEYBOARD) + else: + modes.add(Modes.GAMEPAD) + if(Modes.GAMEPAD in modes and Modes.KEYBOARD in modes): break for group in ['left_trackpad', 'right_trackpad']: for mode in self.config[group].values(): From fb567ff5e64986a367f3ae9d4b4564de163c7889 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Sun, 12 Feb 2017 22:04:41 -0500 Subject: [PATCH 096/104] src/config.py: Replaced long if-else ladder in get_binding() with a dict and a single if statement for key name replacement --- src/config.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/config.py b/src/config.py index e9844cb..8f16fb3 100644 --- a/src/config.py +++ b/src/config.py @@ -128,6 +128,15 @@ def load_vdf(path): # {{{ # }}} def get_binding(group_inputs, input_name, activator): # {{{ + # This is the list of key "names" from Valve's VDF files (keys) that need + # to be replaced with libinput constants (values) + replace = { + 'PERIOD' : 'DOT', + 'ESCAPE' : 'ESC', + 'DASH' : 'MINUS', + 'EQUALS' : 'EQUAL' + } + try: activator = group_inputs[input_name]['activators'][activator] # TODO: Proper support for multiples @@ -144,14 +153,8 @@ def get_binding(group_inputs, input_name, activator): # {{{ binding[1] = binding[1].replace('_', '') binding[1] = binding[1].replace(',', '') # Items such as "key_press W, w"; everything after the comma is already trimmed by split() above, ignore trailing items for now' - if(binding[1] == 'PERIOD'): - binding[1] = 'DOT' - elif(binding[1] == 'ESCAPE'): - binding[1] = 'ESC' - elif(binding[1] == 'DASH'): - binding[1] = 'MINUS' - elif(binding[1] == 'EQUALS'): - binding[1] = 'EQUAL' + if(binding[1] in replace): + binding[1] = replace[binding[1]] # Holy crap, the hacks don't get much uglier than this. Add 0x100 to # all KEY_ constants, because the keyboard ends at 0xff and that From faf14335e6ee114282ddb25c29912e5e8d1db0f6 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Mon, 13 Feb 2017 21:12:21 -0500 Subject: [PATCH 097/104] src/config.py: Will no longer crash on startup if a section is missing --- src/config.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/config.py b/src/config.py index 8f16fb3..9fad5b0 100644 --- a/src/config.py +++ b/src/config.py @@ -383,31 +383,31 @@ def generate_eventmapper(self): # {{{ assert self.config != None self.evm = EventMapper(gamepad_definition = self.generate_gamepad_definition(), modes = self.get_modes()) - if('active' in self.config['left_trackpad']): + if('left_trackpad' in self.config and 'active' in self.config['left_trackpad']): self.set_trackpad_config(Pos.LEFT, 'active') print('--- Left trackpad configured') - if('active' in self.config['right_trackpad']): + if('right_trackpad' in self.config and 'active' in self.config['right_trackpad']): self.set_trackpad_config(Pos.RIGHT, 'active') print('--- Right trackpad configured') - if('active' in self.config['joystick']): + if('joystick' in self.config and 'active' in self.config['joystick']): self.set_joystick_config('active') print('--- Joystick configured') - if('active' in self.config['button_diamond']): + if('button_diamond' in self.config and 'active' in self.config['button_diamond']): self.set_diamond_config('active') print('--- Button diamond configured') - if('active' in self.config['switch']): + if('switch' in self.config and 'active' in self.config['switch']): self.set_switches_config('active', True) print('--- Switches configured') - if('active' in self.config['left_trigger']): + if('left_trigger' in self.config and 'active' in self.config['left_trigger']): self.set_trigger_config(Pos.LEFT, 'active') print('--- Left trigger configured') - if('active' in self.config['right_trigger']): + if('right_trigger' in self.config and 'active' in self.config['right_trigger']): self.set_trigger_config(Pos.RIGHT, 'active') print('--- Right trigger configured') From 4c5b0d24fc3b50082f822c62b2ac85488bb3ff48 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Tue, 14 Feb 2017 12:22:25 -0500 Subject: [PATCH 098/104] src/config.py: No longer forcing GAMEPAD mode for all button assignments --- src/config.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/config.py b/src/config.py index 9fad5b0..0211dde 100644 --- a/src/config.py +++ b/src/config.py @@ -413,7 +413,7 @@ def generate_eventmapper(self): # {{{ # This cannot be configured from the Steam UI. Should we extend that file # to support configuring it? - self.evm.setButtonAction(SCButtons.STEAM, Keys.KEY_HOMEPAGE, Modes.GAMEPAD) + self.evm.setButtonAction(SCButtons.STEAM, Keys.KEY_HOMEPAGE) # }}} def get_keys(self): # {{{ @@ -487,59 +487,59 @@ def set_trackpad_config(self, pos, mode): # {{{ group = self.config['right_trackpad'][mode] if pos == Pos.RIGHT else self.config['left_trackpad'][mode] if(group['mode'] == PadModes.MOUSE): self.evm.setPadMouse(pos) - self.evm.setButtonAction(button, group['buttons']['click'], Modes.GAMEPAD) + self.evm.setButtonAction(button, group['buttons']['click']) elif(group['mode'] == PadModes.MOUSESCROLL): # TODO: Support configuration for scroll directions self.evm.setPadScroll(pos) - self.evm.setButtonAction(button, group['buttons']['click'], Modes.GAMEPAD) + self.evm.setButtonAction(button, group['buttons']['click']) elif(group['mode'] == PadModes.BUTTONCLICK): # TODO: Configurable whether or not click is required? buttons = group['buttons'] self.evm.setPadButtons(pos, [buttons['north'], buttons['west'], buttons['south'], buttons['east']], clicked = True, mode = Modes.GAMEPAD) elif(group['mode'] == PadModes.AXIS): self.evm.setPadAxes(pos, *[axis[0] for axis in group['axes']]) - self.evm.setButtonAction(button, group['buttons']['click'], Modes.GAMEPAD) + self.evm.setButtonAction(button, group['buttons']['click']) # }}} def set_joystick_config(self, mode): # {{{ group = self.config['joystick'][mode] if(group['mode'] == StickModes.BUTTON): - self.evm.setStickButtons([group['buttons']['north'], group['buttons']['west'], group['buttons']['south'], group['buttons']['east']], Modes.GAMEPAD) + self.evm.setStickButtons([group['buttons']['north'], group['buttons']['west'], group['buttons']['south'], group['buttons']['east']]) if('click' in group['buttons'] and group['buttons']['click'] != None): - self.evm.setButtonAction(SCButtons.LPAD, group['buttons']['click'], Modes.GAMEPAD) + self.evm.setButtonAction(SCButtons.LPAD, group['buttons']['click']) elif(group['mode'] == StickModes.AXIS): self.evm.setStickAxes(*[axis[0] for axis in group['axes']]) # }}} def set_diamond_config(self, mode): # {{{ group = self.config['button_diamond'][mode] - self.evm.setButtonAction(SCButtons.A, group['buttons']['a'], Modes.GAMEPAD) - self.evm.setButtonAction(SCButtons.B, group['buttons']['b'], Modes.GAMEPAD) - self.evm.setButtonAction(SCButtons.X, group['buttons']['x'], Modes.GAMEPAD) - self.evm.setButtonAction(SCButtons.Y, group['buttons']['y'], Modes.GAMEPAD) + self.evm.setButtonAction(SCButtons.A, group['buttons']['a']) + self.evm.setButtonAction(SCButtons.B, group['buttons']['b']) + self.evm.setButtonAction(SCButtons.X, group['buttons']['x']) + self.evm.setButtonAction(SCButtons.Y, group['buttons']['y']) # }}} def set_switches_config(self, mode, assign_modeshifts): # {{{ group = self.config['switch'][mode] - self.evm.setButtonAction(SCButtons.LB, group['buttons']['left_bumper'], Modes.GAMEPAD) - self.evm.setButtonAction(SCButtons.RB, group['buttons']['right_bumper'], Modes.GAMEPAD) - self.evm.setButtonAction(SCButtons.START, group['buttons']['start'], Modes.GAMEPAD) - self.evm.setButtonAction(SCButtons.BACK, group['buttons']['back'], Modes.GAMEPAD) + self.evm.setButtonAction(SCButtons.LB, group['buttons']['left_bumper']) + self.evm.setButtonAction(SCButtons.RB, group['buttons']['right_bumper']) + self.evm.setButtonAction(SCButtons.START, group['buttons']['start']) + self.evm.setButtonAction(SCButtons.BACK, group['buttons']['back']) if(type(group['buttons']['left_grip']) == list): if(assign_modeshifts): self.evm.setButtonCallback(SCButtons.LGRIP, lambda evm, btn, pressed: self.modeshift(group['buttons']['left_grip'], pressed)) else: - self.evm.setButtonAction(SCButtons.LGRIP, group['buttons']['left_grip'], Modes.GAMEPAD) + self.evm.setButtonAction(SCButtons.LGRIP, group['buttons']['left_grip']) if(type(group['buttons']['right_grip']) == list): if(assign_modeshifts): self.evm.setButtonCallback(SCButtons.RGRIP, lambda evm, btn, pressed: self.modeshift(group['buttons']['right_grip'], pressed)) else: - self.evm.setButtonAction(SCButtons.RGRIP, group['buttons']['right_grip'], Modes.GAMEPAD) + self.evm.setButtonAction(SCButtons.RGRIP, group['buttons']['right_grip']) # }}} def set_trigger_config(self, pos, mode): # {{{ group = self.config['right_trigger'][mode] if pos == Pos.RIGHT else self.config['left_trigger'][mode] if(group['mode'] == TrigModes.BUTTON): - self.evm.setTrigButton(pos, group['buttons']['click'], Modes.GAMEPAD) + self.evm.setTrigButton(pos, group['buttons']['click']) # }}} From 7cde38f588d1e96f0a44ccdec67f9227d1b3f4c4 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Mon, 13 Feb 2017 20:27:05 -0500 Subject: [PATCH 099/104] src/config.py: Added Configurator::import_config() which sets self.config and runs self.generate_eventmapper(); changed load_config() to utilize import_config(); and changed __init__() to not call generate_eventmapper() directly --- src/config.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/config.py b/src/config.py index 0211dde..c28b907 100644 --- a/src/config.py +++ b/src/config.py @@ -357,14 +357,18 @@ def __init__(self, name, vdf_path = None, vendor = 0x28de, product = 0x1142, ver self.vdf_path = vdf_path if(self.vdf_path != None): self.load_config() - self.generate_eventmapper() self.vendor = vendor self.product = product self.version = version # }}} def load_config(self): # {{{ - self.config = parse_config(load_vdf(self.vdf_path)) + self.import_config(parse_config(load_vdf(self.vdf_path))) + # }}} + + def import_config(self, config): # {{{ + self.config = config + self.generate_eventmapper() # }}} def generate_gamepad_definition(self): # {{{ From 01f0c225fdd84cb65efa54782d23cf1af1f055a7 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Tue, 14 Feb 2017 14:04:14 -0500 Subject: [PATCH 100/104] src/config.py: Added support for PadModes.BUTTONTOUCH in set_trackpad_config() --- src/config.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/config.py b/src/config.py index c28b907..6e680a0 100644 --- a/src/config.py +++ b/src/config.py @@ -497,9 +497,12 @@ def set_trackpad_config(self, pos, mode): # {{{ self.evm.setPadScroll(pos) self.evm.setButtonAction(button, group['buttons']['click']) elif(group['mode'] == PadModes.BUTTONCLICK): - # TODO: Configurable whether or not click is required? buttons = group['buttons'] self.evm.setPadButtons(pos, [buttons['north'], buttons['west'], buttons['south'], buttons['east']], clicked = True, mode = Modes.GAMEPAD) + elif(group['mode'] == PadModes.BUTTONTOUCH): + buttons = group['buttons'] + self.evm.setPadButtons(pos, [buttons['north'], buttons['west'], buttons['south'], buttons['east']], clicked = False, mode = Modes.GAMEPAD) + self.evm.setButtonAction(button, group['buttons']['click']) elif(group['mode'] == PadModes.AXIS): self.evm.setPadAxes(pos, *[axis[0] for axis in group['axes']]) self.evm.setButtonAction(button, group['buttons']['click']) From e8a02d6baf17146d281424e2a5652f82ce639806 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Tue, 14 Feb 2017 14:05:54 -0500 Subject: [PATCH 101/104] src/config.py: Configurator::get_modes() is now a stub that just returns all three modes --- src/config.py | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/src/config.py b/src/config.py index 6e680a0..a49ef1b 100644 --- a/src/config.py +++ b/src/config.py @@ -445,27 +445,8 @@ def get_axes(self): # {{{ # }}} def get_modes(self): # {{{ - modes = set() - for group in self.config.values(): - for mode in group.values(): - if('buttons' in mode): - for button in mode['buttons'].values(): - if(button == None or type(button) == list): - continue - if(button < 0x100): - modes.add(Modes.KEYBOARD) - else: - modes.add(Modes.GAMEPAD) - if(Modes.GAMEPAD in modes and Modes.KEYBOARD in modes): - break - for group in ['left_trackpad', 'right_trackpad']: - for mode in self.config[group].values(): - if(mode['mode'] in [PadModes.MOUSE, PadModes.MOUSESCROLL]): - modes.add(Modes.MOUSE) - break - if(Modes.MOUSE in modes): - break - return list(modes) + # TODO: Figure out if this is actually useful or not + return [Modes.GAMEPAD, Modes.MOUSE, Modes.KEYBOARD] # }}} def modeshift(self, sections, pressed): # {{{ From e1fb1765225c3cad005d27ee84333d1290eb1e12 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Tue, 14 Feb 2017 14:06:43 -0500 Subject: [PATCH 102/104] src/config.py: Like the rest, Configurator::set_trackpad_config() is no longer forcing GAMEPAD mode --- src/config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config.py b/src/config.py index a49ef1b..cc9d403 100644 --- a/src/config.py +++ b/src/config.py @@ -479,10 +479,10 @@ def set_trackpad_config(self, pos, mode): # {{{ self.evm.setButtonAction(button, group['buttons']['click']) elif(group['mode'] == PadModes.BUTTONCLICK): buttons = group['buttons'] - self.evm.setPadButtons(pos, [buttons['north'], buttons['west'], buttons['south'], buttons['east']], clicked = True, mode = Modes.GAMEPAD) + self.evm.setPadButtons(pos, [buttons['north'], buttons['west'], buttons['south'], buttons['east']], clicked = True) elif(group['mode'] == PadModes.BUTTONTOUCH): buttons = group['buttons'] - self.evm.setPadButtons(pos, [buttons['north'], buttons['west'], buttons['south'], buttons['east']], clicked = False, mode = Modes.GAMEPAD) + self.evm.setPadButtons(pos, [buttons['north'], buttons['west'], buttons['south'], buttons['east']], clicked = False) self.evm.setButtonAction(button, group['buttons']['click']) elif(group['mode'] == PadModes.AXIS): self.evm.setPadAxes(pos, *[axis[0] for axis in group['axes']]) From 708a512ea686f24022b97a405e4b098ee7855ebb Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Tue, 14 Feb 2017 14:30:36 -0500 Subject: [PATCH 103/104] src/config.py: Changed hardcoded STEAM button from KEY_HOMEPAGE to the much more common KEY_ESC --- src/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.py b/src/config.py index cc9d403..dc0bf01 100644 --- a/src/config.py +++ b/src/config.py @@ -417,7 +417,7 @@ def generate_eventmapper(self): # {{{ # This cannot be configured from the Steam UI. Should we extend that file # to support configuring it? - self.evm.setButtonAction(SCButtons.STEAM, Keys.KEY_HOMEPAGE) + self.evm.setButtonAction(SCButtons.STEAM, Keys.KEY_ESC) # }}} def get_keys(self): # {{{ From 5a52d35c18217881f8e00599055331ed0bad32a5 Mon Sep 17 00:00:00 2001 From: Mike Cronce Date: Wed, 15 Feb 2017 19:32:55 -0500 Subject: [PATCH 104/104] src/config.py: Fixed a python2 incompatibility --- src/config.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/config.py b/src/config.py index dc0bf01..9fc4237 100644 --- a/src/config.py +++ b/src/config.py @@ -376,7 +376,7 @@ def generate_gamepad_definition(self): # {{{ 'vendor' : self.vendor, 'product' : self.product, 'version' : self.version, - 'name' : bytes(self.name + ((' [' + os.path.basename(self.vdf_path) + ']') if self.vdf_path != None else ''), 'utf-8'), + 'name' : self.get_gamepad_name(), 'keys' : self.get_keys(), 'axes' : self.get_axes(), 'rels' : [] @@ -420,6 +420,17 @@ def generate_eventmapper(self): # {{{ self.evm.setButtonAction(SCButtons.STEAM, Keys.KEY_ESC) # }}} + def get_gamepad_name(self): # {{{ + name = self.name + ((' [' + os.path.basename(self.vdf_path) + ']') if self.vdf_path != None else '') + try: + # In python3, we need to do this to get a string of 8-bit chars + return bytes(name) + except TypeError: + # But in python2, str consists of 8-bit chars; it's the unicode type + # that consists of wide chars + return name + # }}} + def get_keys(self): # {{{ buttons = [] for group in self.config.values():