1c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang# -*- coding: utf-8 -*- 2c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 3c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang# Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 4c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang# Use of this source code is governed by a BSD-style license that can be 5c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang# found in the LICENSE file. 6c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 7c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang"""Guide the user to perform gestures. Record and validate the gestures.""" 8c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 92fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwangimport fcntl 10d9b03cc8ece225087e203658ded151005eea0456Joseph Hwangimport glob 11c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwangimport os 12c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwangimport subprocess 13c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwangimport sys 145a61f5a19dfde799a3ca407e761f400184ae5fddJoseph Hwang 15c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwangimport common_util 167981beea4b6dfdff43ca61e17b51ba295a342702Joseph Hwangimport firmware_log 17c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwangimport firmware_utils 18c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwangimport fuzzy 19c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwangimport mini_color 2069227234dabb3942f25a70004fd9347308c56a32Joseph Hwangimport mtb 21c0d30cbdfb45cfb800689451f29fe37345c66f48Charlie Mooneyimport touchbotII_robot_wrapper as robot_wrapper 22c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwangimport test_conf as conf 23c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwangimport validators 24c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 2501273ed49c5f0726b14412d6701a01c74315254aJoseph Hwangfrom firmware_utils import GestureList 2601273ed49c5f0726b14412d6701a01c74315254aJoseph Hwang 27c113079e5ee877c4e9f311653d18daf576926b37Joseph Hwangsys.path.append('../../bin/input') 28c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwangimport input_device 29c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 303fb591eb36e473794ba56b633f6690f685fff6c6Joseph Hwang# Include some constants 31b0612e11b87281c1ab8ab95d3c47de2601a9df26Mindy Huangfrom firmware_constants import DEV, GV, MODE, OPTIONS, TFK 325a61f5a19dfde799a3ca407e761f400184ae5fddJoseph Hwang 335a61f5a19dfde799a3ca407e761f400184ae5fddJoseph Hwang 34c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwangclass TestFlow: 35c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """Guide the user to perform gestures. Record and validate the gestures.""" 36c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 37ed82f0322e54196f116566309594b7e5f958fae4Joseph Hwang def __init__(self, device_geometry, device, keyboard, win, parser, output, 38bc9dba0f212df1b31ed43032c68f5e07e9ee9974Joseph Hwang test_version, board, firmware_version, options): 39c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.device_geometry = device_geometry 40c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.device = device 41c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.device_node = self.device.device_node 42ed82f0322e54196f116566309594b7e5f958fae4Joseph Hwang self.keyboard = keyboard 4340cb76895b4a52d85d5d2c1a25b45e49bdeb9828Joseph Hwang self.firmware_version = firmware_version 44c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.output = output 45bc9dba0f212df1b31ed43032c68f5e07e9ee9974Joseph Hwang self.board = board 46bc9dba0f212df1b31ed43032c68f5e07e9ee9974Joseph Hwang self.test_version = test_version 47bc9dba0f212df1b31ed43032c68f5e07e9ee9974Joseph Hwang self.output.print_report('%s' % test_version) 48c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self._get_record_cmd() 49c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.win = win 50c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.parser = parser 51c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.packets = None 52c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.gesture_file_name = None 53c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.prefix_space = self.output.get_prefix_space() 54c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.scores = [] 5534f7784f607ce1bd2916f5db6cf95a9802780a6dJoseph Hwang self.mode = options[OPTIONS.MODE] 5642bc23b188cdf856d24494842909ac0e0930b257Charlie Mooney self.fngenerator_only = options[OPTIONS.FNGENERATOR] 5708eb4422f1e718c67e29e25c3269662070716a01Joseph Hwang self.iterations = options[OPTIONS.ITERATIONS] 58d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang self.replay_dir = options[OPTIONS.REPLAY] 59ecb52de991febef82dc9fa08f033921e8e20bc91Joseph Hwang self.resume_dir = options[OPTIONS.RESUME] 603bad937cb81c5c22183024c7bc67575cd099b051Joseph Hwang self.recording = not any([bool(self.replay_dir), bool(self.resume_dir)]) 614a9648f9d60fecffadb3c629222b9486bd198080Joseph Hwang self.device_type = (DEV.TOUCHSCREEN if options[OPTIONS.TOUCHSCREEN] 624a9648f9d60fecffadb3c629222b9486bd198080Joseph Hwang else DEV.TOUCHPAD) 6342bc23b188cdf856d24494842909ac0e0930b257Charlie Mooney 6442bc23b188cdf856d24494842909ac0e0930b257Charlie Mooney self.robot = robot_wrapper.RobotWrapper(self.board, options) 6542bc23b188cdf856d24494842909ac0e0930b257Charlie Mooney self.robot_waiting = False 6642bc23b188cdf856d24494842909ac0e0930b257Charlie Mooney 6708eb4422f1e718c67e29e25c3269662070716a01Joseph Hwang self.gv_count = float('infinity') 6801273ed49c5f0726b14412d6701a01c74315254aJoseph Hwang gesture_names = self._get_gesture_names() 69dee21b175441da05e032ece48d774b4107569c07Charlie Mooney order = None 70dee21b175441da05e032ece48d774b4107569c07Charlie Mooney if self._is_robot_mode(): 71dee21b175441da05e032ece48d774b4107569c07Charlie Mooney order = lambda x: conf.finger_tips_required[x.name] 72dee21b175441da05e032ece48d774b4107569c07Charlie Mooney self.gesture_list = GestureList(gesture_names).get_gesture_list(order) 7334f7784f607ce1bd2916f5db6cf95a9802780a6dJoseph Hwang self._get_all_gesture_variations(options[OPTIONS.SIMPLIFIED]) 7442bc23b188cdf856d24494842909ac0e0930b257Charlie Mooney 75c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.init_flag = False 762fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang self.system_device = self._non_blocking_open(self.device_node) 77c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.evdev_device = input_device.InputEvent() 78c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.screen_shot = firmware_utils.ScreenShot(self.geometry_str) 793f245993196c7cead8716ff09633a6ad49e8b006Joseph Hwang self.mtb_evemu = mtb.MtbEvemu(device) 8042bc23b188cdf856d24494842909ac0e0930b257Charlie Mooney 81d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang self._rename_old_log_and_html_files() 8221df1fa2829a71c8c43ea807c75595d39352b229Joseph Hwang self._set_static_prompt_messages() 8309890dba0014937e0be1d75d1a46c05dd16cc6b8Joseph Hwang self.gesture_image_name = None 8409890dba0014937e0be1d75d1a46c05dd16cc6b8Joseph Hwang self.gesture_continues_flag = False 8579009095b5857565709897cf01a23c15e8fefdb5Joseph Hwang self.use_existent_event_file_flag = False 86c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 87c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def __del__(self): 88c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.system_device.close() 89c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 90d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang def _rename_old_log_and_html_files(self): 91ecb52de991febef82dc9fa08f033921e8e20bc91Joseph Hwang """When in replay or resume mode, rename the old log and html files.""" 92ecb52de991febef82dc9fa08f033921e8e20bc91Joseph Hwang if self.replay_dir or self.resume_dir: 93d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang for file_type in ['*.log', '*.html']: 94d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang path_names = os.path.join(self.output.log_dir, file_type) 95d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang for old_path_name in glob.glob(path_names): 96d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang new_path_name = '.'.join([old_path_name, 'old']) 97d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang os.rename(old_path_name, new_path_name) 98d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang 995a61f5a19dfde799a3ca407e761f400184ae5fddJoseph Hwang def _is_robot_mode(self): 10042bc23b188cdf856d24494842909ac0e0930b257Charlie Mooney return self.robot.is_robot_action_mode() or self.mode == MODE.ROBOT_SIM 1015a61f5a19dfde799a3ca407e761f400184ae5fddJoseph Hwang 10201273ed49c5f0726b14412d6701a01c74315254aJoseph Hwang def _get_gesture_names(self): 10301273ed49c5f0726b14412d6701a01c74315254aJoseph Hwang """Determine the gesture names based on the mode.""" 1042cbb23bb88733c3e0a40f7d17681ed957b54ce27Charlie Mooney if self.mode == MODE.QUICKSTEP: 105b0612e11b87281c1ab8ab95d3c47de2601a9df26Mindy Huang return conf.gesture_names_quickstep 106b0612e11b87281c1ab8ab95d3c47de2601a9df26Mindy Huang elif self.mode == MODE.NOISE: 107b0612e11b87281c1ab8ab95d3c47de2601a9df26Mindy Huang return conf.gesture_names_noise_extended 1082cbb23bb88733c3e0a40f7d17681ed957b54ce27Charlie Mooney elif self._is_robot_mode(): 109c0d30cbdfb45cfb800689451f29fe37345c66f48Charlie Mooney # The mode could be MODE.ROBOT or MODE.ROBOT_SIM. 110c0d30cbdfb45cfb800689451f29fe37345c66f48Charlie Mooney # The same gesture names list is used in both modes. 111c0d30cbdfb45cfb800689451f29fe37345c66f48Charlie Mooney return conf.gesture_names_robot[self.device_type] 112e943442184657cf8fbe9c33345ce6d436a0ceb1bJoseph Hwang elif self.mode == MODE.MANUAL: 11342bc23b188cdf856d24494842909ac0e0930b257Charlie Mooney # Define the manual list which is gesture_names_complete: 11442bc23b188cdf856d24494842909ac0e0930b257Charlie Mooney # gesture_names_robot - gesture_names_equipment_required 115ab03ed85a8ca7f99608e872d0717c53d3742d031Charlie Mooney manual_set = (set(conf.gesture_names_complete[self.device_type]) - 116ab03ed85a8ca7f99608e872d0717c53d3742d031Charlie Mooney set(conf.gesture_names_robot[self.device_type])) 117ab03ed85a8ca7f99608e872d0717c53d3742d031Charlie Mooney return list(manual_set - set(conf.gesture_names_fngenerator_required)) 11842bc23b188cdf856d24494842909ac0e0930b257Charlie Mooney 119bb6f69b8c90e4896dd82e0266a096674c957f7dbJoseph Hwang elif self.mode == MODE.CALIBRATION: 120bb6f69b8c90e4896dd82e0266a096674c957f7dbJoseph Hwang return conf.gesture_names_calibration 12101273ed49c5f0726b14412d6701a01c74315254aJoseph Hwang else: 12242bc23b188cdf856d24494842909ac0e0930b257Charlie Mooney # Filter out tests that need a function generator for COMPLETE mode 12342bc23b188cdf856d24494842909ac0e0930b257Charlie Mooney # unless they've indicated that they have one 124b0612e11b87281c1ab8ab95d3c47de2601a9df26Mindy Huang return [n for n in conf.gesture_names_complete[self.device_type] 12542bc23b188cdf856d24494842909ac0e0930b257Charlie Mooney if (self.fngenerator_only or 12642bc23b188cdf856d24494842909ac0e0930b257Charlie Mooney n not in conf.gesture_names_fngenerator_required)] 12701273ed49c5f0726b14412d6701a01c74315254aJoseph Hwang 1282fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang def _non_blocking_open(self, filename): 1292fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang """Open the file in non-blocing mode.""" 1302fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang fd = open(filename) 1312fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang fcntl.fcntl(fd, fcntl.F_SETFL, os.O_NONBLOCK) 1322fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang return fd 1332fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang 1342fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang def _non_blocking_read(self, dev, fd): 1352fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang """Non-blocking read on fd.""" 1362fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang try: 1372fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang dev.read(fd) 1382fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang event = (dev.tv_sec, dev.tv_usec, dev.type, dev.code, dev.value) 1392fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang except Exception, e: 1402fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang event = None 1412fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang return event 1422fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang 143c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def _reopen_system_device(self): 144c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """Close the device and open a new one.""" 145c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.system_device.close() 146c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.system_device = open(self.device_node) 1472fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang self.system_device = self._non_blocking_open(self.device_node) 148c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 14921df1fa2829a71c8c43ea807c75595d39352b229Joseph Hwang def _set_static_prompt_messages(self): 15021df1fa2829a71c8c43ea807c75595d39352b229Joseph Hwang """Set static prompt messages.""" 15121df1fa2829a71c8c43ea807c75595d39352b229Joseph Hwang # Prompt for next gesture. 15221df1fa2829a71c8c43ea807c75595d39352b229Joseph Hwang self._prompt_next = ( 15321df1fa2829a71c8c43ea807c75595d39352b229Joseph Hwang "Press SPACE to save this file and go to next test,\n" 15421df1fa2829a71c8c43ea807c75595d39352b229Joseph Hwang " 'm' to save this file and record again,\n" 15521df1fa2829a71c8c43ea807c75595d39352b229Joseph Hwang " 'd' to delete this file and try again,\n" 15621df1fa2829a71c8c43ea807c75595d39352b229Joseph Hwang " 'x' to discard this file and exit.") 15721df1fa2829a71c8c43ea807c75595d39352b229Joseph Hwang 15821df1fa2829a71c8c43ea807c75595d39352b229Joseph Hwang # Prompt to see test result through timeout callback. 15921df1fa2829a71c8c43ea807c75595d39352b229Joseph Hwang self._prompt_result = ( 16021df1fa2829a71c8c43ea807c75595d39352b229Joseph Hwang "Perform the gesture now.\n" 16121df1fa2829a71c8c43ea807c75595d39352b229Joseph Hwang "See the test result on the right after finger lifted.\n" 16221df1fa2829a71c8c43ea807c75595d39352b229Joseph Hwang "Or press 'x' to exit.") 16321df1fa2829a71c8c43ea807c75595d39352b229Joseph Hwang 164a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang def _get_prompt_abnormal_gestures(self, warn_msg): 165a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang """Prompt for next gesture.""" 166a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang prompt = '\n'.join( 167a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang ["It is very likely that you perform a WRONG gesture!", 168a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang warn_msg, 169a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang "Press 'd' to delete this file and try again (recommended),", 170a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang " SPACE to save this file if you are sure it's correct,", 171a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang " 'x' to discard this file and exit."]) 172a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang return prompt 1738ee3e33e92f4e609c9b5fd9474e6a2263e93c79dJoseph Hwang 174c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def _get_prompt_no_data(self): 175c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """Prompt to remind user of performing gestures.""" 176c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang prompt = ("You need to perform the specified gestures " 177c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang "before pressing SPACE.\n") 17821df1fa2829a71c8c43ea807c75595d39352b229Joseph Hwang return prompt + self._prompt_result 179c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 180c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def _get_record_cmd(self): 181c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """Get the device event record command.""" 18242740f2c8a15b00c69847855bf477270f4b84cf2Charlie Mooney # Run mtplot with settings to disable clearing the display if the robot 18342740f2c8a15b00c69847855bf477270f4b84cf2Charlie Mooney # clicks the pad, and adding a visible click indicator in the output 1843ceb6419c90576ba7df8cee03d4b42d38d1b6d00Charlie Mooney self.record_program = 'mtplot -s1 -c0 -m0' 185c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang if not common_util.program_exists(self.record_program): 186c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang msg = 'Error: the program "%s" does not exist in $PATH.' 187c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.output.print_report(msg % self.record_program) 188c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang exit(1) 189c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 190c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang display_name = firmware_utils.get_display_name() 191c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.geometry_str = '%dx%d+%d+%d' % self.device_geometry 192c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang format_str = '%s %s -d %s -g %s' 193c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.record_cmd = format_str % (self.record_program, 194c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.device_node, 195c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang display_name, 196c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.geometry_str) 197c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.output.print_report('Record program: %s' % self.record_cmd) 198c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 199c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def _span_seq(self, seq1, seq2): 200c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """Span sequence seq1 over sequence seq2. 201c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 202c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang E.g., seq1 = (('a', 'b'), 'c') 203c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang seq2 = ('1', ('2', '3')) 204c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang res = (('a', 'b', '1'), ('a', 'b', '2', '3'), 205c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang ('c', '1'), ('c', '2', '3')) 206c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang E.g., seq1 = ('a', 'b') 207c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang seq2 = ('1', '2', '3') 208c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang res = (('a', '1'), ('a', '2'), ('a', '3'), 209c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang ('b', '1'), ('b', '2'), ('b', '3')) 210c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang E.g., seq1 = (('a', 'b'), ('c', 'd')) 211c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang seq2 = ('1', '2', '3') 212c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang res = (('a', 'b', '1'), ('a', 'b', '2'), ('a', 'b', '3'), 213c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang ('c', 'd', '1'), ('c', 'd', '2'), ('c', 'd', '3')) 214c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """ 215c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang to_list = lambda s: list(s) if isinstance(s, tuple) else [s] 216c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang return tuple(tuple(to_list(s1) + to_list(s2)) for s1 in seq1 217c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang for s2 in seq2) 218c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 219c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def span_variations(self, seq): 220c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """Span the variations of a gesture.""" 22176fe3da7a718ff2c47f9f2d793c5fc1e863aa285Joseph Hwang if seq is None: 22276fe3da7a718ff2c47f9f2d793c5fc1e863aa285Joseph Hwang return (None,) 22376fe3da7a718ff2c47f9f2d793c5fc1e863aa285Joseph Hwang elif isinstance(seq[0], tuple): 22476fe3da7a718ff2c47f9f2d793c5fc1e863aa285Joseph Hwang return reduce(self._span_seq, seq) 22576fe3da7a718ff2c47f9f2d793c5fc1e863aa285Joseph Hwang else: 22676fe3da7a718ff2c47f9f2d793c5fc1e863aa285Joseph Hwang return seq 227c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 228c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def _stop(self): 229c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """Terminate the recording process.""" 230c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.record_proc.poll() 231c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang # Terminate the process only when it was not terminated yet. 232c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang if self.record_proc.returncode is None: 233c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.record_proc.terminate() 234c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.record_proc.wait() 235c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.output.print_window('') 236c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 237c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def _get_gesture_image_name(self): 238c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """Get the gesture file base name without file extension.""" 239c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang filepath = os.path.splitext(self.gesture_file_name)[0] 240c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.gesture_image_name = filepath + '.png' 241c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang return filepath 242c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 243d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang def _close_gesture_file(self): 244d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang """Close the gesture file.""" 245d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang if self.gesture_file.closed: 246d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang return 247d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang 248d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang filename = self.gesture_file.name 249d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang self.gesture_file.close() 250d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang 251d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang # Strip off the header of the gesture file. 252d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang # 253d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang # Input driver version is 1.0.1 254d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang # Input device ID: bus 0x18 vendor 0x0 product 0x0 version 0x0 255d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang # Input device name: "Atmel maXTouch Touchpad" 256d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang # ... 257d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang # Testing ... (interrupt to exit) 258d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang # Event: time 519.855, type 3 (EV_ABS), code 57 (ABS_MT_TRACKING_ID), 259d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang # value 884 260d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang # 261d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang tmp_filename = filename + '.tmp' 262d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang os.rename(filename, tmp_filename) 263d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang with open(tmp_filename) as src_f: 264d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang with open(filename, 'w') as dst_f: 265d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang for line in src_f: 266d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang if line.startswith('Event:'): 267d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang dst_f.write(line) 268d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang os.remove(tmp_filename) 269d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang 270c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def _stop_record_and_post_image(self): 271c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """Terminate the recording process.""" 272ecb52de991febef82dc9fa08f033921e8e20bc91Joseph Hwang if self.record_new_file: 273d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang self._close_gesture_file() 274d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang self.screen_shot.dump_root(self._get_gesture_image_name()) 275d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang self.record_proc.terminate() 276d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang self.record_proc.wait() 277d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang else: 278d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang self._get_gesture_image_name() 279c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.win.set_image(self.gesture_image_name) 280c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 281c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def _create_prompt(self, test, variation): 282c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """Create a color prompt.""" 283c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang prompt = test.prompt 284c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang if isinstance(variation, tuple): 285c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang subprompt = reduce(lambda s1, s2: s1 + s2, 286c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang tuple(test.subprompt[s] for s in variation)) 287c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang elif variation is None or test.subprompt is None: 288c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang subprompt = None 289c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang else: 290c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang subprompt = test.subprompt[variation] 291c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 292c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang if subprompt is None: 293c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang color_prompt = prompt 29476fe3da7a718ff2c47f9f2d793c5fc1e863aa285Joseph Hwang monochrome_prompt = prompt 295c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang else: 296c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang color_prompt = mini_color.color_string(prompt, '{', '}', 'green') 297c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang color_prompt = color_prompt.format(*subprompt) 298c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang monochrome_prompt = prompt.format(*subprompt) 299c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 300c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang color_msg_format = mini_color.color_string('\n<%s>:\n%s%s', '<', '>', 30176fe3da7a718ff2c47f9f2d793c5fc1e863aa285Joseph Hwang 'blue') 302c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang color_msg = color_msg_format % (test.name, self.prefix_space, 303c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang color_prompt) 304c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang msg = '%s: %s' % (test.name, monochrome_prompt) 305c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 3067981beea4b6dfdff43ca61e17b51ba295a342702Joseph Hwang glog = firmware_log.GestureLog() 307ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang glog.name = test.name 308ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang glog.variation = variation 309ecc254fc00e6b3504d4f7d87abad937cf73a267dJoseph Hwang glog.prompt = monochrome_prompt 3107981beea4b6dfdff43ca61e17b51ba295a342702Joseph Hwang 3117981beea4b6dfdff43ca61e17b51ba295a342702Joseph Hwang return (msg, color_msg, glog) 312c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 313c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def _choice_exit(self): 314c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """Procedure to exit.""" 315c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self._stop() 316c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang if os.path.exists(self.gesture_file_name): 317c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang os.remove(self.gesture_file_name) 318c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.output.print_report(self.deleted_msg) 319c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 320c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def _stop_record_and_rm_file(self): 321c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """Stop recording process and remove the current gesture file.""" 322c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self._stop() 323c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang if os.path.exists(self.gesture_file_name): 324c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang os.remove(self.gesture_file_name) 325c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.output.print_report(self.deleted_msg) 326c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 327c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def _create_gesture_file_name(self, gesture, variation): 328d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang """Create the gesture file name based on its variation. 329d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang 330d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang Examples of different levels of file naming: 331d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang Primary name: 332d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang pinch_to_zoom.zoom_in-lumpy-fw_11.27 333d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang Root name: 334d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang pinch_to_zoom.zoom_in-lumpy-fw_11.27-manual-20130221_050510 335d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang Base name: 336d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang pinch_to_zoom.zoom_in-lumpy-fw_11.27-manual-20130221_050510.dat 337d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang """ 338c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang if variation is None: 339c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang gesture_name = gesture.name 340c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang else: 341c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang if type(variation) is tuple: 342c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang name_list = [gesture.name,] + list(variation) 343c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang else: 344c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang name_list = [gesture.name, variation] 345c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang gesture_name = '.'.join(name_list) 346c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 347d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang self.primary_name = conf.filename.sep.join([ 348c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang gesture_name, 349ad3136c03a931b4c1742cdec472780be15f7e1edJoseph Hwang self.board, 35040cb76895b4a52d85d5d2c1a25b45e49bdeb9828Joseph Hwang conf.fw_prefix + self.firmware_version]) 351d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang root_name = conf.filename.sep.join([ 352d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang self.primary_name, 353cea259e9b1f95c10892179ea8594e2be73438858Joseph Hwang self.mode, 354c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang firmware_utils.get_current_time_str()]) 355d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang basename = '.'.join([root_name, conf.filename.ext]) 356d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang return basename 357c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 358c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def _add_scores(self, new_scores): 359c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """Add the new scores of a single gesture to the scores list.""" 360c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang if new_scores is not None: 361c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.scores += new_scores 362c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 363c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def _final_scores(self, scores): 364c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """Print the final score.""" 365c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang # Note: conf.score_aggregator uses a function in fuzzy module. 366c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang final_score = eval(conf.score_aggregator)(scores) 367c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.output.print_report('\nFinal score: %s\n' % str(final_score)) 368c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 369aaa25e0898b712793078936d112520ed7cf1a569Joseph Hwang def _robot_action(self): 370aaa25e0898b712793078936d112520ed7cf1a569Joseph Hwang """Control the robot to perform the action.""" 37142bc23b188cdf856d24494842909ac0e0930b257Charlie Mooney if self._is_robot_mode() or self.robot.is_manual_noise_test_mode(): 37242bc23b188cdf856d24494842909ac0e0930b257Charlie Mooney self.robot.configure_noise(self.gesture, self.variation) 37342bc23b188cdf856d24494842909ac0e0930b257Charlie Mooney 3743162c02ea4a2287fc77436ba28f2c9c83349b63eCharlie Mooney if self._is_robot_mode(): 3753162c02ea4a2287fc77436ba28f2c9c83349b63eCharlie Mooney self.robot.control(self.gesture, self.variation) 376af9472281594241369d693c45722c6a8b2310840Charlie Mooney # Once the script terminates start a timeout to clean up if one 377af9472281594241369d693c45722c6a8b2310840Charlie Mooney # hasn't already been set to keep the test suite from hanging. 378af9472281594241369d693c45722c6a8b2310840Charlie Mooney if not self.gesture_begins_flag: 379af9472281594241369d693c45722c6a8b2310840Charlie Mooney self.win.register_timeout_add(self.gesture_timeout_callback, 380af9472281594241369d693c45722c6a8b2310840Charlie Mooney self.gesture.timeout) 38115dcc7520cc7f821fdc8db20109d62a7011bc649Joseph Hwang 38209890dba0014937e0be1d75d1a46c05dd16cc6b8Joseph Hwang def _handle_user_choice_save_after_parsing(self, next_gesture=True): 383c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """Handle user choice for saving the parsed gesture file.""" 384c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.output.print_window('') 3853bad937cb81c5c22183024c7bc67575cd099b051Joseph Hwang if self.use_existent_event_file_flag or self.recording: 38679009095b5857565709897cf01a23c15e8fefdb5Joseph Hwang if self.saved_msg: 38779009095b5857565709897cf01a23c15e8fefdb5Joseph Hwang self.output.print_report(self.saved_msg) 38879009095b5857565709897cf01a23c15e8fefdb5Joseph Hwang if self.new_scores: 38979009095b5857565709897cf01a23c15e8fefdb5Joseph Hwang self._add_scores(self.new_scores) 39079009095b5857565709897cf01a23c15e8fefdb5Joseph Hwang self.output.report_html.insert_image(self.gesture_image_name) 39179009095b5857565709897cf01a23c15e8fefdb5Joseph Hwang self.output.report_html.flush() 3921e4a6cce6769e50e5ef33dafd228c46ec6e3bc0eJoseph Hwang # After flushing to report_html, reset the gesture_image_name so that 3931e4a6cce6769e50e5ef33dafd228c46ec6e3bc0eJoseph Hwang # it will not be reused by next gesture variation accidentally. 3941e4a6cce6769e50e5ef33dafd228c46ec6e3bc0eJoseph Hwang self.gesture_image_name = None 3951e4a6cce6769e50e5ef33dafd228c46ec6e3bc0eJoseph Hwang 396c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang if self._pre_setup_this_gesture_variation(next_gesture=next_gesture): 397c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang # There are more gestures. 398c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self._setup_this_gesture_variation() 399c0d30cbdfb45cfb800689451f29fe37345c66f48Charlie Mooney self._robot_action() 400c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang else: 401c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang # No more gesture. 402c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self._final_scores(self.scores) 403c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.output.stop() 4047981beea4b6dfdff43ca61e17b51ba295a342702Joseph Hwang self.output.report_html.stop() 4051fd993155b6d1c6996daafd5789101d3342c7bc9Joseph Hwang self.win.stop() 406c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.packets = None 407c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 408c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def _handle_user_choice_discard_after_parsing(self): 409c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """Handle user choice for discarding the parsed gesture file.""" 410c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.output.print_window('') 411c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self._setup_this_gesture_variation() 412c0d30cbdfb45cfb800689451f29fe37345c66f48Charlie Mooney self._robot_action() 413c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.packets = None 414c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 415c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def _handle_user_choice_exit_after_parsing(self): 416c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """Handle user choice to exit after the gesture file is parsed.""" 417c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self._stop_record_and_rm_file() 4187981beea4b6dfdff43ca61e17b51ba295a342702Joseph Hwang self.output.stop() 4197981beea4b6dfdff43ca61e17b51ba295a342702Joseph Hwang self.output.report_html.stop() 4201fd993155b6d1c6996daafd5789101d3342c7bc9Joseph Hwang self.win.stop() 421c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 422a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang def check_for_wrong_number_of_fingers(self, details): 423a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang flag_found = False 424a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang try: 425a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang position = details.index('CountTrackingIDValidator') 426a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang except ValueError as e: 427a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang return None 428a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang 429a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang # An example of the count of tracking IDs: 430a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang # ' count of trackid IDs: 1' 431a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang number_tracking_ids = int(details[position + 1].split()[-1]) 432a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang # An example of the criteria_str looks like: 433a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang # ' criteria_str: == 2' 434a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang criteria = int(details[position + 2].split()[-1]) 435a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang if number_tracking_ids < criteria: 436a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang print ' CountTrackingIDValidator: ' 437a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang print ' number_tracking_ids: ', number_tracking_ids 438a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang print ' criteria: ', criteria 439a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang print ' number_tracking_ids should be larger!' 440a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang msg = 'Number of Tracking IDs should be %d instead of %d' 441a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang return msg % (criteria, number_tracking_ids) 442a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang return None 443a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang 4448b3cb003be644a2b78689346628122bb5b3f2f6bCharlie Mooney def _empty_packets_is_legal_result(self): 4458b3cb003be644a2b78689346628122bb5b3f2f6bCharlie Mooney return ('tap' in self.gesture.name and self._is_robot_mode()) 4468b3cb003be644a2b78689346628122bb5b3f2f6bCharlie Mooney 447c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def _handle_user_choice_validate_before_parsing(self): 448c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """Handle user choice for validating before gesture file is parsed.""" 449c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang # Parse the device events. Make sure there are events. 450c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.packets = self.parser.parse_file(self.gesture_file_name) 4518b3cb003be644a2b78689346628122bb5b3f2f6bCharlie Mooney if self.packets or self._empty_packets_is_legal_result(): 452c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang # Validate this gesture and get the results. 4537981beea4b6dfdff43ca61e17b51ba295a342702Joseph Hwang (self.new_scores, msg_list, vlogs) = validators.validate( 4547981beea4b6dfdff43ca61e17b51ba295a342702Joseph Hwang self.packets, self.gesture, self.variation) 455a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang 456a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang # If the number of tracking IDs is less than the expected value, 457a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang # the user probably made a wrong gesture. 458a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang error = self.check_for_wrong_number_of_fingers(msg_list) 459a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang if error: 460a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang prompt = self._get_prompt_abnormal_gestures(error) 461a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang color = 'red' 462a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang else: 46321df1fa2829a71c8c43ea807c75595d39352b229Joseph Hwang prompt = self._prompt_next 464a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang color = 'black' 465a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang 466d66db93c0cf3878bbef19756eb1118bacd845eb0Joseph Hwang self.output.print_window(msg_list) 467d66db93c0cf3878bbef19756eb1118bacd845eb0Joseph Hwang self.output.buffer_report(msg_list) 4687981beea4b6dfdff43ca61e17b51ba295a342702Joseph Hwang self.output.report_html.insert_validator_logs(vlogs) 469a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang self.win.set_prompt(prompt, color=color) 470a385567aa9e120da24561fe470a078f0d4aed365Joseph Hwang print prompt 471c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self._stop_record_and_post_image() 472c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang else: 473c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.win.set_prompt(self._get_prompt_no_data(), color='red') 474c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 475c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def _handle_user_choice_exit_before_parsing(self): 476c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """Handle user choice to exit before the gesture file is parsed.""" 477d40afdf230b71e93e626c1ee9682f372940159b4Joseph Hwang self._close_gesture_file() 4787981beea4b6dfdff43ca61e17b51ba295a342702Joseph Hwang self._handle_user_choice_exit_after_parsing() 479c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 480c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def _is_parsing_gesture_file_done(self): 481c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """Is parsing the gesture file done?""" 482c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang return self.packets is not None 483c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 4845a90d71e179bcc3b1fac4897806db4a58a450ba4Joseph Hwang def _is_arrow_key(self, choice): 4855a90d71e179bcc3b1fac4897806db4a58a450ba4Joseph Hwang """Is this an arrow key?""" 4865a90d71e179bcc3b1fac4897806db4a58a450ba4Joseph Hwang return (choice in TFK.ARROW_KEY_LIST) 4875a90d71e179bcc3b1fac4897806db4a58a450ba4Joseph Hwang 488ed82f0322e54196f116566309594b7e5f958fae4Joseph Hwang def user_choice_callback(self, fd, condition): 489c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """A callback to handle the key pressed by the user. 490c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 491c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang This is the primary GUI event-driven method handling the user input. 492c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """ 493ed82f0322e54196f116566309594b7e5f958fae4Joseph Hwang choice = self.keyboard.get_key_press_event(fd) 494ed82f0322e54196f116566309594b7e5f958fae4Joseph Hwang if choice: 495ed82f0322e54196f116566309594b7e5f958fae4Joseph Hwang self._handle_keyboard_event(choice) 496ed82f0322e54196f116566309594b7e5f958fae4Joseph Hwang return True 497ed82f0322e54196f116566309594b7e5f958fae4Joseph Hwang 498ed82f0322e54196f116566309594b7e5f958fae4Joseph Hwang def _handle_keyboard_event(self, choice): 499ed82f0322e54196f116566309594b7e5f958fae4Joseph Hwang """Handle the keyboard event.""" 5005a90d71e179bcc3b1fac4897806db4a58a450ba4Joseph Hwang if self._is_arrow_key(choice): 5015a90d71e179bcc3b1fac4897806db4a58a450ba4Joseph Hwang self.win.scroll(choice) 5025a90d71e179bcc3b1fac4897806db4a58a450ba4Joseph Hwang elif self.robot_waiting: 503ed82f0322e54196f116566309594b7e5f958fae4Joseph Hwang # The user wants the robot to start its action. 504ed82f0322e54196f116566309594b7e5f958fae4Joseph Hwang if choice in (TFK.SAVE, TFK.SAVE2): 505aaa25e0898b712793078936d112520ed7cf1a569Joseph Hwang self.robot_waiting = False 506aaa25e0898b712793078936d112520ed7cf1a569Joseph Hwang self._robot_action() 507ed82f0322e54196f116566309594b7e5f958fae4Joseph Hwang # The user wants to exit. 508ed82f0322e54196f116566309594b7e5f958fae4Joseph Hwang elif choice == TFK.EXIT: 509ed82f0322e54196f116566309594b7e5f958fae4Joseph Hwang self._handle_user_choice_exit_after_parsing() 510aaa25e0898b712793078936d112520ed7cf1a569Joseph Hwang elif self._is_parsing_gesture_file_done(): 511c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang # Save this gesture file and go to next gesture. 512ed82f0322e54196f116566309594b7e5f958fae4Joseph Hwang if choice in (TFK.SAVE, TFK.SAVE2): 51309890dba0014937e0be1d75d1a46c05dd16cc6b8Joseph Hwang self._handle_user_choice_save_after_parsing() 514c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang # Save this file and perform the same gesture again. 515ed82f0322e54196f116566309594b7e5f958fae4Joseph Hwang elif choice == TFK.MORE: 516c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self._handle_user_choice_save_after_parsing(next_gesture=False) 517c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang # Discard this file and perform the gesture again. 518ed82f0322e54196f116566309594b7e5f958fae4Joseph Hwang elif choice == TFK.DISCARD: 519c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self._handle_user_choice_discard_after_parsing() 520c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang # The user wants to exit. 521ed82f0322e54196f116566309594b7e5f958fae4Joseph Hwang elif choice == TFK.EXIT: 522c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self._handle_user_choice_exit_after_parsing() 523c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang # The user presses any wrong key. 524c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang else: 52521df1fa2829a71c8c43ea807c75595d39352b229Joseph Hwang self.win.set_prompt(self._prompt_next, color='red') 526c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang else: 527ed82f0322e54196f116566309594b7e5f958fae4Joseph Hwang if choice == TFK.EXIT: 528c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self._handle_user_choice_exit_before_parsing() 529c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang # The user presses any wrong key. 530c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang else: 53121df1fa2829a71c8c43ea807c75595d39352b229Joseph Hwang self.win.set_prompt(self._prompt_result, color='red') 532c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 5333fb591eb36e473794ba56b633f6690f685fff6c6Joseph Hwang def _get_all_gesture_variations(self, simplified): 534c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """Get all variations for all gestures.""" 535c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang gesture_variations_list = [] 5368ee3e33e92f4e609c9b5fd9474e6a2263e93c79dJoseph Hwang self.variations_dict = {} 537c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang for gesture in self.gesture_list: 5388ee3e33e92f4e609c9b5fd9474e6a2263e93c79dJoseph Hwang variations_list = [] 539c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang variations = self.span_variations(gesture.variations) 540c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang for variation in variations: 541c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang gesture_variations_list.append((gesture, variation)) 5428ee3e33e92f4e609c9b5fd9474e6a2263e93c79dJoseph Hwang variations_list.append(variation) 5433fb591eb36e473794ba56b633f6690f685fff6c6Joseph Hwang if simplified: 5443fb591eb36e473794ba56b633f6690f685fff6c6Joseph Hwang break 5458ee3e33e92f4e609c9b5fd9474e6a2263e93c79dJoseph Hwang self.variations_dict[gesture.name] = variations_list 546c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.gesture_variations = iter(gesture_variations_list) 547c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 548c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def gesture_timeout_callback(self): 549c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """A callback watching whether a gesture has timed out.""" 55009890dba0014937e0be1d75d1a46c05dd16cc6b8Joseph Hwang if self.replay_dir: 55109890dba0014937e0be1d75d1a46c05dd16cc6b8Joseph Hwang # There are event files to replay for this gesture variation. 55209890dba0014937e0be1d75d1a46c05dd16cc6b8Joseph Hwang if self.use_existent_event_file_flag: 55309890dba0014937e0be1d75d1a46c05dd16cc6b8Joseph Hwang self._handle_user_choice_validate_before_parsing() 55409890dba0014937e0be1d75d1a46c05dd16cc6b8Joseph Hwang self._handle_user_choice_save_after_parsing(next_gesture=True) 55509890dba0014937e0be1d75d1a46c05dd16cc6b8Joseph Hwang return False 55609890dba0014937e0be1d75d1a46c05dd16cc6b8Joseph Hwang 55769227234dabb3942f25a70004fd9347308c56a32Joseph Hwang # A gesture is stopped only when two conditions are met simultaneously: 55869227234dabb3942f25a70004fd9347308c56a32Joseph Hwang # (1) there are no reported packets for a timeout interval, and 55969227234dabb3942f25a70004fd9347308c56a32Joseph Hwang # (2) the number of tracking IDs is 0. 56009890dba0014937e0be1d75d1a46c05dd16cc6b8Joseph Hwang elif (self.gesture_continues_flag or 56169227234dabb3942f25a70004fd9347308c56a32Joseph Hwang not self.mtb_evemu.all_fingers_leaving()): 562c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.gesture_continues_flag = False 563c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang return True 56409890dba0014937e0be1d75d1a46c05dd16cc6b8Joseph Hwang 565c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang else: 566c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self._handle_user_choice_validate_before_parsing() 567c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.win.remove_event_source(self.gesture_file_watch_tag) 568d534df8a12153d7006dceed16cd90b54c05dd5cfJoseph Hwang if self._is_robot_mode(): 569d534df8a12153d7006dceed16cd90b54c05dd5cfJoseph Hwang self._handle_keyboard_event(TFK.SAVE) 570c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang return False 571c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 572c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def gesture_file_watch_callback(self, fd, condition, evdev_device): 5732fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang """A callback to watch the device input.""" 5742fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang # Read the device node continuously until end 5752fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang event = True 5762fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang while event: 5772fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang event = self._non_blocking_read(evdev_device, fd) 57869227234dabb3942f25a70004fd9347308c56a32Joseph Hwang if event: 57969227234dabb3942f25a70004fd9347308c56a32Joseph Hwang self.mtb_evemu.process_event(event) 5802fa046e44242b11bfe17a3acf20b74dd0407d83eJoseph Hwang 581c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.gesture_continues_flag = True 582c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang if (not self.gesture_begins_flag): 583c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.gesture_begins_flag = True 584c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.win.register_timeout_add(self.gesture_timeout_callback, 5856bbab3e8ff24fd3b0c44f753cfce03225e108bb5Joseph Hwang self.gesture.timeout) 586c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang return True 587c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 588c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def init_gesture_setup_callback(self, widget, event): 589c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """A callback to set up environment before a user starts a gesture.""" 590c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang if not self.init_flag: 591c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.init_flag = True 592c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self._pre_setup_this_gesture_variation() 593c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self._setup_this_gesture_variation() 594c0d30cbdfb45cfb800689451f29fe37345c66f48Charlie Mooney self._robot_action() 595c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 596d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang def _get_existent_event_files(self): 597d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang """Get the existent event files that starts with the primary_name.""" 598d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang primary_pathnames = os.path.join(self.output.log_dir, 599d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang self.primary_name + '*.dat') 600d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang self.primary_gesture_files = glob.glob(primary_pathnames) 601d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang # Reverse sorting the file list so that we could pop from the tail. 602d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang self.primary_gesture_files.sort() 603d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang self.primary_gesture_files.reverse() 604d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang 605d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang def _use_existent_event_file(self): 606d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang """If the replay flag is set in the command line, and there exists a 607d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang file(s) with the same primary name, then use the existent file(s) 608d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang instead of recording a new one. 609d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang """ 610d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang if self.primary_gesture_files: 611d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang self.gesture_file_name = self.primary_gesture_files.pop() 612d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang return True 613d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang return False 614d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang 615c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def _pre_setup_this_gesture_variation(self, next_gesture=True): 616c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang """Get gesture, variation, filename, prompt, etc.""" 617d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang next_gesture_first_time = False 618c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang if next_gesture: 61908eb4422f1e718c67e29e25c3269662070716a01Joseph Hwang if self.gv_count < self.iterations: 62008eb4422f1e718c67e29e25c3269662070716a01Joseph Hwang self.gv_count += 1 62108eb4422f1e718c67e29e25c3269662070716a01Joseph Hwang else: 62208eb4422f1e718c67e29e25c3269662070716a01Joseph Hwang self.gv_count = 1 62308eb4422f1e718c67e29e25c3269662070716a01Joseph Hwang gesture_variation = next(self.gesture_variations, None) 62408eb4422f1e718c67e29e25c3269662070716a01Joseph Hwang if gesture_variation is None: 62508eb4422f1e718c67e29e25c3269662070716a01Joseph Hwang return False 62608eb4422f1e718c67e29e25c3269662070716a01Joseph Hwang self.gesture, self.variation = gesture_variation 627d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang next_gesture_first_time = True 628d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang 629d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang basename = self._create_gesture_file_name(self.gesture, self.variation) 630d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang if next_gesture_first_time: 631d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang self._get_existent_event_files() 632d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang 633ecb52de991febef82dc9fa08f033921e8e20bc91Joseph Hwang if self.replay_dir or self.resume_dir: 634d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang self.use_existent_event_file_flag = self._use_existent_event_file() 635ecb52de991febef82dc9fa08f033921e8e20bc91Joseph Hwang 636ecb52de991febef82dc9fa08f033921e8e20bc91Joseph Hwang if ((not self.replay_dir and not self.resume_dir) or 637ecb52de991febef82dc9fa08f033921e8e20bc91Joseph Hwang (self.resume_dir and not self.use_existent_event_file_flag)): 638d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang self.gesture_file_name = os.path.join(self.output.log_dir, basename) 639ecb52de991febef82dc9fa08f033921e8e20bc91Joseph Hwang self.saved_msg = '(saved: %s)\n' % self.gesture_file_name 640ecb52de991febef82dc9fa08f033921e8e20bc91Joseph Hwang self.deleted_msg = '(deleted: %s)\n' % self.gesture_file_name 641ecb52de991febef82dc9fa08f033921e8e20bc91Joseph Hwang else: 642ecb52de991febef82dc9fa08f033921e8e20bc91Joseph Hwang self.saved_msg = None 643ecb52de991febef82dc9fa08f033921e8e20bc91Joseph Hwang self.deleted_msg = None 644ecb52de991febef82dc9fa08f033921e8e20bc91Joseph Hwang self.new_scores = None 645c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 64642bc23b188cdf856d24494842909ac0e0930b257Charlie Mooney if self.robot.is_robot_action_mode() or self.robot.is_manual_noise_test_mode(): 64742bc23b188cdf856d24494842909ac0e0930b257Charlie Mooney self.robot.turn_off_noise() 64842bc23b188cdf856d24494842909ac0e0930b257Charlie Mooney 6497981beea4b6dfdff43ca61e17b51ba295a342702Joseph Hwang (msg, color_msg, glog) = self._create_prompt(self.gesture, 6507981beea4b6dfdff43ca61e17b51ba295a342702Joseph Hwang self.variation) 651c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.win.set_gesture_name(msg) 6527981beea4b6dfdff43ca61e17b51ba295a342702Joseph Hwang self.output.report_html.insert_gesture_log(glog) 6534e8330caaca32549aeb1c61903355d1efc63955dJoseph Hwang print color_msg 654c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.output.print_report(color_msg) 655c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang return True 656c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 657c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang def _setup_this_gesture_variation(self): 658d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang """Set up the recording process or use an existent event data file.""" 659d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang if self.replay_dir: 660ecb52de991febef82dc9fa08f033921e8e20bc91Joseph Hwang self.record_new_file = False 66109890dba0014937e0be1d75d1a46c05dd16cc6b8Joseph Hwang self.win.register_timeout_add(self.gesture_timeout_callback, 0) 662d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang return 663d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang 664ecb52de991febef82dc9fa08f033921e8e20bc91Joseph Hwang if self.resume_dir and self.use_existent_event_file_flag: 665ecb52de991febef82dc9fa08f033921e8e20bc91Joseph Hwang self.record_new_file = False 666ecb52de991febef82dc9fa08f033921e8e20bc91Joseph Hwang self._handle_user_choice_validate_before_parsing() 667ecb52de991febef82dc9fa08f033921e8e20bc91Joseph Hwang self._handle_keyboard_event(TFK.SAVE) 668ecb52de991febef82dc9fa08f033921e8e20bc91Joseph Hwang return 669ecb52de991febef82dc9fa08f033921e8e20bc91Joseph Hwang 67045f891b832de8f1c94e1006478fb557cd341aa57Joseph Hwang # Initiate the MtbSanityValidator. Note that this should be done each 67145f891b832de8f1c94e1006478fb557cd341aa57Joseph Hwang # time just before recording the gesture file since it requires a 67245f891b832de8f1c94e1006478fb557cd341aa57Joseph Hwang # snapshot of the input device before any finger touching the device. 673dfeafca16e4aacb865b51768f607a1a5a2db956cCharlie Mooney self.gesture.mtb_sanity_validator = validators.MtbSanityValidator() 67445f891b832de8f1c94e1006478fb557cd341aa57Joseph Hwang 675d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang # Now, we will record a new gesture event file. 676d9b03cc8ece225087e203658ded151005eea0456Joseph Hwang # Fork a new process for mtplot. Add io watch for the gesture file. 677ecb52de991febef82dc9fa08f033921e8e20bc91Joseph Hwang self.record_new_file = True 678c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.gesture_file = open(self.gesture_file_name, 'w') 679c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.record_proc = subprocess.Popen(self.record_cmd.split(), 680c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang stdout=self.gesture_file) 681c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang 682c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang # Watch if data come in to the monitored file. 683c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.gesture_begins_flag = False 684c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self._reopen_system_device() 685c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.gesture_file_watch_tag = self.win.register_io_add_watch( 686c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.gesture_file_watch_callback, self.system_device, 687c3d6c06ce24969123b90292808bdec37bc7313d7Joseph Hwang self.evdev_device) 688