示例#1
0
    def insert_bind_button(self, param, section, name, double=False):
        button = Gtk.Button()
        button.set_size_request(105 * self.scale_factor, -1)
        raw_value = self.parent.m64p_wrapper.ConfigGetParameter(param)
        #self.map_controls[param] = raw_value
        if raw_value != '':
            if self.parent.m64p_wrapper.ConfigGetParameter(
                    'name') == "Keyboard":
                raw_value = raw_value.split(',')
                if len(raw_value) == 2:
                    first_value = sdl.SDL_GetKeyName(
                        self.filter_number(raw_value[0]))
                    second_value = sdl.SDL_GetKeyName(
                        self.filter_number(raw_value[1]))
                    keyname = b"(" + self.purify(
                        first_value) + b", " + self.purify(second_value) + b")"
                else:
                    keyname = self.purify(
                        sdl.SDL_GetKeyName(self.filter_number(raw_value[0])))

                button.set_label(keyname.decode('utf-8'))
            else:
                button.set_label(raw_value)
        else:
            button.set_label("(empty)")
        button.connect("clicked", self.on_bind_key, param, section, name,
                       double)

        return button
示例#2
0
 def handle_input(self, key, shift_pressed, alt_pressed, ctrl_pressed):
     keystr = sdl2.SDL_GetKeyName(key).decode()
     if keystr == 'Left':
         self.other_pressed()
     elif keystr == 'Right':
         self.confirm_pressed()
     elif keystr == 'Escape':
         self.cancel_pressed()
示例#3
0
 def handle_input(self, event, shift_pressed, alt_pressed, ctrl_pressed):
     # pass event's key to any objects that want to handle it
     if not event.type in [sdl2.SDL_KEYDOWN, sdl2.SDL_KEYUP]:
         return
     key = sdl2.SDL_GetKeyName(event.key.keysym.sym).decode()
     key = key.lower()
     args = (key, shift_pressed, alt_pressed, ctrl_pressed)
     for obj in self.objects.values():
         if obj.handle_key_events:
             if event.type == sdl2.SDL_KEYDOWN:
                 self.try_object_method(obj, obj.handle_key_down, args)
             elif event.type == sdl2.SDL_KEYUP:
                 self.try_object_method(obj, obj.handle_key_up, args)
示例#4
0
 def waitForResponse():
     # sdl2.SDL_FlushEvents()
     done = False
     while not done:
         sdl2.SDL_PumpEvents()
         for event in sdl2.ext.get_events():
             if event.type == sdl2.SDL_KEYDOWN:
                 response = sdl2.SDL_GetKeyName(
                     event.key.keysym.sym).lower()
                 if response == 'escape':
                     exitSafely()
                 else:
                     done = True
     # sdl2.SDL_FlushEvents()
     return response
示例#5
0
 def handle_input(self, key, shift_pressed, alt_pressed, ctrl_pressed):
     keystr = sdl2.SDL_GetKeyName(key).decode()
     # up/down keys navigate list
     new_index = self.selected_item_index
     navigated = False
     if keystr == 'Return':
         # if handle_enter returns True, bail before rest of input handling -
         # make sure any changes to handle_enter are safe for this!
         if self.handle_enter(shift_pressed, alt_pressed, ctrl_pressed):
             return
     elif keystr == 'Up':
         navigated = True
         if self.selected_item_index > 0:
             new_index -= 1
     elif keystr == 'Down':
         navigated = True
         if self.selected_item_index < len(self.items) - 1:
             new_index += 1
     elif keystr == 'PageUp':
         navigated = True
         page_size = int(self.items_in_view / 2)
         new_index -= page_size
         new_index = max(0, new_index)
         # scroll follows selection jumps
         self.scroll_index -= page_size
         self.scroll_index = max(0, self.scroll_index)
     elif keystr == 'PageDown':
         navigated = True
         page_size = int(self.items_in_view / 2)
         new_index += page_size
         new_index = min(new_index, len(self.items) - 1)
         self.scroll_index += page_size
         self.scroll_index = min(self.scroll_index, self.get_max_scroll())
     # home/end: beginning/end of list, respectively
     elif keystr == 'Home':
         navigated = True
         new_index = 0
         self.scroll_index = 0
     elif keystr == 'End':
         navigated = True
         new_index = len(self.items) - 1
         self.scroll_index = len(self.items) - self.items_in_view
     self.set_selected_item_index(new_index, set_field_text=navigated)
     # handle alphanumeric input etc
     UIDialog.handle_input(self, key, shift_pressed, alt_pressed, ctrl_pressed)
     # if we didn't navigate, seek based on new alphanumeric input
     if not navigated:
         self.text_input_seek()
示例#6
0
文件: test.py 项目: wahoti/PyDAW
def run2():
    sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO)
    sdl2.SDL_Init(sdl2.SDL_INIT_JOYSTICK)
    joystick = sdl2.SDL_JoystickOpen(0)
    sdl2.ext.init()
    window = sdl2.ext.Window("test",
                             size=(800, 600),
                             position=(0, 0),
                             flags=sdl2.SDL_WINDOW_SHOWN)
    window.refresh()
    while True:
        for event in sdl2.ext.get_events():
            if event.type == sdl2.SDL_KEYDOWN:
                print sdl2.SDL_GetKeyName(event.key.keysym.sym).lower()
            elif event.type == sdl2.SDL_JOYAXISMOTION:
                print[event.jaxis.axis, event.jaxis.value]
    return 0
示例#7
0
    def binding(self, widget, param, device, name, controller, execute):
        dialog = BindDialog(self, widget, device, name, controller)

        if dialog.key_pressed != None:
            if dialog.key_pressed.value == 42:
                store = ""
                if execute == True:
                    widget.set_label("(empty)")
                    self.parent.m64p_wrapper.ConfigSetParameter(param, store)
                return [store, "empty"]
            else:
                value = dialog.key_pressed.value
                keycode = sdl.SDL_GetKeyFromScancode(value)
                store = "key(" + str(keycode) + ")"
                if execute == True:
                    widget.set_label(
                        sdl.SDL_GetKeyName(keycode).decode("utf-8"))
                    self.parent.m64p_wrapper.ConfigSetParameter(param, store)
                else:
                    return [str(keycode), "key"]

        elif dialog.gamepad_pressed != None:
            value = dialog.gamepad_pressed
            if dialog.gamepad_type == "button":
                store = "button(" + str(value) + ")"
            else:
                if dialog.gamepad_type == "Naxis":
                    store = "axis(" + str(value) + "-)"
                elif dialog.gamepad_type == "Paxis":
                    store = "axis(" + str(value) + "+)"
            if execute == True:
                widget.set_label(store)
                self.parent.m64p_wrapper.ConfigSetParameter(param, store)
            else:
                return [str(value), dialog.gamepad_type]
        else:
            return ["", None]
示例#8
0
 def handle_input(self, key, shift_pressed, alt_pressed, ctrl_pressed):
     keystr = sdl2.SDL_GetKeyName(key).decode()
     field = None
     field_text = ''
     if self.active_field < len(self.fields):
         field = self.fields[self.active_field]
         field_text = self.field_texts[self.active_field]
     # special case: shortcut 'D' for 3rd button if no field input
     if len(self.fields) == 0 and keystr.lower() == 'd':
         self.other_pressed()
         return
     if keystr == '`' and not shift_pressed:
         self.ui.console.toggle()
         return
     # if list panel is up don't let user tab away
     lp = self.ui.edit_list_panel
     # only allow tab to focus shift IF list panel accepts it
     if keystr == 'Tab' and lp.is_visible() and \
        lp.list_operation in lp.list_operations_allow_kb_focus:
         self.ui.keyboard_focus_element = self.ui.edit_list_panel
         return
     elif keystr == 'Return':
         self.confirm_pressed()
     elif keystr == 'Escape':
         self.cancel_pressed()
     # cycle through fields with up/down
     elif keystr == 'Up' or (keystr == 'Tab' and shift_pressed):
         if len(self.fields) > 1:
             self.active_field -= 1
             self.active_field %= len(self.fields)
             # skip over None-type fields aka dead labels
             while self.fields[self.active_field].type is None:
                 self.active_field -= 1
                 self.active_field %= len(self.fields)
         return
     elif keystr == 'Down' or keystr == 'Tab':
         if len(self.fields) > 1:
             self.active_field += 1
             self.active_field %= len(self.fields)
             while self.fields[self.active_field].type is None:
                 self.active_field += 1
                 self.active_field %= len(self.fields)
         return
     elif keystr == 'Backspace':
         if len(field_text) == 0:
             pass
         # don't let user clear a bool value
         # TODO: allow for checkboxes but not radio buttons
         elif field and field.type is bool:
             pass
         elif alt_pressed:
             # for file dialogs, delete back to last slash
             last_slash = field_text[:-1].rfind('/')
             # on windows, recognize backslash as well
             if platform.system() == 'Windows':
                 last_backslash = field_text[:-1].rfind('\\')
                 if last_backslash != -1 and last_slash != -1:
                     last_slash = min(last_backslash, last_slash)
             if last_slash == -1:
                 field_text = ''
             else:
                 field_text = field_text[:last_slash + 1]
         else:
             field_text = field_text[:-1]
     elif keystr == 'Space':
         # if field.type is bool, toggle value
         if field.type is bool:
             field_text = self.get_toggled_bool_field(self.active_field)
         else:
             field_text += ' '
     elif len(keystr) > 1:
         return
     # alphanumeric text input
     elif field and not field.type is bool:
         if field.type is str:
             if not shift_pressed:
                 keystr = keystr.lower()
             if not keystr.isalpha() and shift_pressed:
                 keystr = SHIFT_MAP.get(keystr, '')
         elif field.type is int and not keystr.isdigit() and keystr != '-':
             return
         # this doesn't guard against things like 0.00.001
         elif field.type is float and not keystr.isdigit(
         ) and keystr != '.' and keystr != '-':
             return
         field_text += keystr
     # apply new field text and redraw
     if field and (len(field_text) < field.width or field.type is bool):
         self.field_texts[self.active_field] = field_text
     self.draw_fields(self.always_redraw_labels)
示例#9
0
#!/usr/bin/python

import sdl2
import sdl2.ext
sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO)
sdl2.SDL_Init(sdl2.SDL_INIT_JOYSTICK)
joystick = sdl2.SDL_JoystickOpen(0)
#sdl2.ext.Window("test", size=(800,600),position=(0,0),flags=sdl2.SDL_WINDOW_SHOWN)
#window.refresh()
while True:
    for event in sdl2.ext.get_events():
        if event.type == sdl2.SDL_KEYDOWN:
            print(sdl2.SDL_GetKeyName(event.key.keysym.sym).lower())
        elif event.type == sdl2.SDL_JOYAXISMOTION:
            print('Axis: ', [event.jaxis.axis, event.jaxis.value])
            if event.jaxis.axis == 0:
                print('detectado eje 0')
            if event.jaxis.axis == 1:
                print('detectado eje 1')
            # Eje Throttle
            if event.jaxis.axis == 3:
                print('detectado eje throttle')
        elif event.type == sdl2.SDL_JOYBUTTONDOWN:
            print('Button: ', [event.jaxis.axis, event.jaxis.value])
            if event.jaxis.axis == 0:
                print('detectado boton 1')
            if event.jaxis.axis == 1:
                print('detectado boton 2')
            if event.jaxis.axis == 2:
                print('detectado boton 3')
            if event.jaxis.axis == 3:
示例#10
0
def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('-l', '--list-controllers', action='store_true', help='Display a list of controllers attached to the system.')
    parser.add_argument('-c', '--controller', type=str, default='0', help='Controller to use. Default: 0.')
    parser.add_argument('-m', '--macro-controller', metavar='CONTROLLER:RECORD_BUTTON:PLAY_BUTTON', type=str, default=None, help='Controller and buttons to use for macro control. Default: None.')
    parser.add_argument('-p', '--port', type=str, default='/dev/ttyUSB0', help='Serial port or "functionfs" for direct USB mode. Default: /dev/ttyUSB0.')
    parser.add_argument('-b', '--baud-rate', type=int, default=115200, help='Baud rate. Default: 115200.')
    parser.add_argument('-u', '--udc', type=str, default='dummy_udc.0', help='UDC for direct USB mode. Default: dummy_udc.0 (loopback mode).')
    parser.add_argument('-R', '--record', type=str, default=None, help='Record events to file.')
    parser.add_argument('-P', '--playback', type=str, default=None, help='Play back events from file.')
    parser.add_argument('-d', '--dontexit', action='store_true', help='Switch to live input when playback finishes, instead of exiting. Default: False.')
    parser.add_argument('-q', '--quiet', action='store_true', help='Disable speed meter. Default: False.')
    parser.add_argument('-M', '--macros-dir', type=str, default='.', help='Directory to save macros. Default: current directory.')
    parser.add_argument('-f', '--function', type=str, nargs='*', default=[], help='Map a macro function to a button.')
    parser.add_argument('-D', '--log-level', type=str, default='INFO', help='Debugging level. CRITICAL, ERROR, WARNING, INFO, DEBUG. Default=INFO')

    args = parser.parse_args()

    numeric_level = getattr(logging, args.log_level.upper(), None)
    if not isinstance(numeric_level, int):
        raise ValueError('Invalid log level: %s' % args.log_level)
    root_logger.setLevel(numeric_level)

    if args.list_controllers:
        Controller.enumerate()
        exit(0)

    states = []

    if args.playback is None or args.dontexit:
        if args.controller == 'fake':
            states = fakeinput()
        else:
            states = Controller(args.controller)
    if args.playback is not None:
        states = itertools.chain(replay_states(args.playback), states)

    macro_controller = None
    macro_record = None
    macro_play = None

    if args.macro_controller is not None:
        try:
            macro_controller, macro_record, macro_play = args.macro_controller.rsplit(':', maxsplit=3)
            macro_record = int(macro_record, 10)
            macro_play = int(macro_play, 10)
        except ValueError:
            logger.critical('Macro controller must be <controller number or name>:<record button>:<play button>')
            exit(-1)

        try:
            n = int(macro_controller, 10)
            if n < sdl2.SDL_NumJoysticks():
                sdl2.SDL_JoystickOpen(n)
                macro_controller = n
        except ValueError:
            for n in range(sdl2.SDL_NumJoysticks()):
                name = sdl2.SDL_JoystickNameForIndex(n)
                if name is not None:
                    name = name.decode('utf8')
                    if name == macro_controller:
                        sdl2.SDL_JoystickOpen(n)
                        macro_controller = n

    window = None
    try:
        window = Window()
    except sdl2.ext.common.SDLError:
        logger.warning('Could not create a window with SDL. Keyboard input will not be available.')
        pass

    function_macros = {}
    for arg in args.function:
        try:
            b,f = arg.split(':')
            function_macros[int(b, 10)] = macros_dict[f]
        except ValueError:
            logger.error('Invalid function macro ignored.')
        except KeyError:
            logger.error('Invalid function macro ignored.')

    with MacroManager(states, macros_dir=args.macros_dir, record_button=macro_record, play_button=macro_play, function_macros=function_macros) as mm:
        with Recorder(args.record) as record:
            with HAL(args.port, args.baud_rate, args.udc) as hal:
                with tqdm(unit=' updates', disable=args.quiet, dynamic_ncols=True) as pbar:

                    try:

                        while True:

                            for event in sdl2.ext.get_events():
                                # we have to fetch the events from SDL in order for the controller
                                # state to be updated.
                                if event.type == sdl2.SDL_WINDOWEVENT:
                                    if event.window.event == sdl2.SDL_WINDOWEVENT_CLOSE:
                                        raise WindowClosed
                                else:
                                    if event.type == sdl2.SDL_KEYDOWN and event.key.repeat == 0:
                                        logger.debug('Key down: {:s}'.format(sdl2.SDL_GetKeyName(event.key.keysym.sym).decode('utf8')))
                                        mm.key_event(event.key.keysym.sym, True)
                                    elif event.type == sdl2.SDL_KEYUP:
                                        logger.debug('Key up: {:s}'.format(sdl2.SDL_GetKeyName(event.key.keysym.sym).decode('utf8')))
                                        mm.key_event(event.key.keysym.sym, False)
                                    elif event.jdevice.which == macro_controller:
                                        if event.type == sdl2.SDL_JOYBUTTONDOWN:
                                            logger.debug('Macro controller button down: {:d}'.format(event.jbutton.button))
                                            mm.button_event(event.jbutton.button, True)
                                        elif event.type == sdl2.SDL_JOYBUTTONUP:
                                            mm.button_event(event.jbutton.button, False)

                            # wait for the arduino to request another state.
                            if hal.poll():
                                state = next(mm)
                                hal.write(state)
                                record.write(state)
                                pbar.set_description('Sent {:s}'.format(state.hexstr))
                                pbar.update()
                                if window is not None:
                                    window.update(state)

                    except StopIteration:
                        logger.info('Exiting because replay finished.')
                    except KeyboardInterrupt:
                        logger.info('Exiting due to keyboard interrupt.')
                    except WindowClosed:
                        logger.info('Exiting because input window was closed.')
示例#11
0
 def handle_keyboard_input(self, key, shift_pressed, ctrl_pressed,
                           alt_pressed):
     # for now, do nothing on ctrl/alt
     if ctrl_pressed or alt_pressed:
         return
     # popup should get input if it's up
     if self.ui.popup.visible:
         return
     keystr = sdl2.SDL_GetKeyName(key).decode()
     art = self.ui.active_art
     frame, layer = art.active_frame, art.active_layer
     x, y = int(self.cursor.x), int(-self.cursor.y)
     char_w, char_h = art.quad_width, art.quad_height
     # TODO: if cursor isn't inside selection, bail early
     if keystr == 'Return':
         if self.cursor.y < art.width:
             self.cursor.x = self.start_x
             self.cursor.y -= 1
     elif keystr == 'Backspace':
         if self.cursor.x > self.start_x:
             self.cursor.x -= char_w
             # undo command on previous tile
             self.cursor.current_command.undo_commands_for_tile(
                 frame, layer, x - 1, y)
     elif keystr == 'Space':
         keystr = ' '
     elif keystr == 'Up':
         if -self.cursor.y > 0:
             self.cursor.y += 1
     elif keystr == 'Down':
         if -self.cursor.y < art.height - 1:
             self.cursor.y -= 1
     elif keystr == 'Left':
         if self.cursor.x > 0:
             self.cursor.x -= char_w
     elif keystr == 'Right':
         if self.cursor.x < art.width - 1:
             self.cursor.x += char_w
     elif keystr == 'Escape':
         self.finish_entry()
         return
     # ignore any other non-character keys
     if len(keystr) > 1:
         return
     if keystr.isalpha() and not shift_pressed:
         keystr = keystr.lower()
     elif not keystr.isalpha() and shift_pressed:
         keystr = SHIFT_MAP.get(keystr, ' ')
     # if cursor got out of bounds, don't input
     if 0 > x or x >= art.width or 0 > y or y >= art.height:
         return
     # create tile command
     new_tc = EditCommandTile(art)
     new_tc.set_tile(frame, layer, x, y)
     b_char, b_fg, b_bg, b_xform = art.get_tile_at(frame, layer, x, y)
     new_tc.set_before(b_char, b_fg, b_bg, b_xform)
     a_char = art.charset.get_char_index(keystr)
     a_fg = self.ui.selected_fg_color if self.affects_fg_color else None
     a_bg = self.ui.selected_bg_color if self.affects_bg_color else None
     a_xform = self.ui.selected_xform if self.affects_xform else None
     new_tc.set_after(a_char, a_fg, a_bg, a_xform)
     # add command, apply immediately, and move cursor
     if self.cursor.current_command:
         self.cursor.current_command.add_command_tiles([new_tc])
     else:
         self.ui.app.log('DEV WARNING: Cursor current command was expected')
     new_tc.apply()
     self.cursor.x += char_w
     if self.cursor.x >= self.ui.active_art.width:
         self.cursor.x = self.start_x
         self.cursor.y -= char_h
     if -self.cursor.y >= self.ui.active_art.height:
         self.finish_entry()
示例#12
0
文件: main.py 项目: aib/MPv2
def main():
	args = argparse.ArgumentParser(description="Run " + TITLE)
	args.add_argument('-i', '--midi-input',   help="connect to specified MIDI input port")
	args.add_argument('-o', '--midi-output',  help="connect to specified MIDI output port")
	args.add_argument('-c', '--debug-camera', action='store_true', help="use a controllable camera")
	args.add_argument('-s', '--vsync',        action='store_true', help="use vsync")
	args.add_argument('-v', '--verbose',      action='store_true', help="increase verbosity")
	args.add_argument('-w', '--windowed',     action='store_true', help="run in a window")
	args.add_argument('-3', '--stereoscopy', choices=[scene.STEREOSCOPY_OFF, scene.STEREOSCOPY_ANAGLYPH], help="stereoscopy mode")
	args.add_argument('-e', '--eye-separation', type=float, help="stereoscopic eye separation")
	opts = args.parse_args(sys.argv[1:])

	if opts.verbose:
		logging.basicConfig(level=logging.DEBUG)
	else:
		logging.basicConfig(level=logging.INFO)

	logger = logging.getLogger(__name__)

	logger.info("Initializing")
	sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO)

	dm = sdl2.SDL_DisplayMode()
	sdl2.SDL_GetDesktopDisplayMode(0, dm)
	if not opts.windowed:
		width = dm.w
		height = dm.h
	else:
		width = round(dm.w * .8)
		height = round(dm.h * .8)

	window_flags = sdl2.SDL_WINDOW_OPENGL | (sdl2.SDL_WINDOW_FULLSCREEN if not opts.windowed else 0)
	window = sdl2.SDL_CreateWindow(TITLE.encode('utf-8'), sdl2.SDL_WINDOWPOS_UNDEFINED, sdl2.SDL_WINDOWPOS_UNDEFINED, width, height, window_flags)
	context = sdl2.SDL_GL_CreateContext(window)

	fbo = create_multisampled_fbo(width, height, 0)

	if opts.vsync:
		if sdl2.SDL_GL_SetSwapInterval(-1) == -1:
			logger.warning("Adaptive vsync not available")
			sdl2.SDL_GL_SetSwapInterval(1)
	else:
		sdl2.SDL_GL_SetSwapInterval(0)

	midi_handler = midi.MidiHandler(opts.midi_input, opts.midi_output)
	main_scene = scene.Scene((width, height), midi_handler, debug_camera=opts.debug_camera)

	if opts.stereoscopy is not None:
		main_scene.set_stereoscopy(opts.stereoscopy)

	if opts.eye_separation is not None:
		main_scene.stereoscopy_eye_separation = opts.eye_separation

	frames = 0
	frame_count_time = time.monotonic()

	ev = sdl2.SDL_Event()
	running = True
	while running:
		while True:
			if (sdl2.SDL_PollEvent(ev) == 0):
				break

			if ev.type == sdl2.SDL_QUIT:
				running = False

			elif ev.type == sdl2.SDL_KEYUP and ev.key.keysym.sym == sdl2.SDLK_ESCAPE:
				running = False

			elif ev.type == sdl2.SDL_KEYDOWN and ev.key.repeat == 0:
				main_scene.key_down(sdl2.SDL_GetKeyName(ev.key.keysym.sym).decode('ascii').lower())

			elif ev.type == sdl2.SDL_KEYUP and ev.key.repeat == 0:
				main_scene.key_up(sdl2.SDL_GetKeyName(ev.key.keysym.sym).decode('ascii').lower())

			elif ev.type == sdl2.SDL_MOUSEBUTTONDOWN:
				main_scene.mouse_down(ev.button.button, (ev.button.x / width, ev.button.y / height))

			elif ev.type == sdl2.SDL_MOUSEBUTTONUP:
				main_scene.mouse_up(ev.button.button, (ev.button.x / width, ev.button.y / height))

		main_scene.update()
		main_scene.render()
		blit_multisampled_fbo(width, height, fbo)
		sdl2.SDL_GL_SwapWindow(window)

		frames += 1
		now = time.monotonic()
		if now - frame_count_time > FPS_PRINT_TIME:
			fps = frames / (now - frame_count_time)
			frames = 0
			frame_count_time = now
			logger.debug("%.3f FPS", fps)

	main_scene.shutdown()

	sdl2.SDL_GL_DeleteContext(context)
	sdl2.SDL_DestroyWindow(window)
	sdl2.SDL_Quit()
示例#13
0
 def get_bind_functions(self, keysym, shift, alt, ctrl):
     "returns a list of methods for the given key + mods if one exists"
     keystr = sdl2.SDL_GetKeyName(keysym).decode().lower()
     key_data = (keystr, shift, alt, ctrl)
     return self.edit_binds.get(key_data, [])
示例#14
0
 def handle_input(self, key, shift_pressed, alt_pressed, ctrl_pressed):
     "handles a key from Application.input"
     keystr = sdl2.SDL_GetKeyName(key).decode()
     # TODO: get console bound key from InputLord, detect that instead of
     # hard-coded backquote
     if keystr == '`':
         self.toggle()
         return
     elif keystr == 'Return':
         line = '%s %s' % (self.prompt, self.current_line)
         self.ui.app.log(line)
         # if command is same as last, don't repeat it
         if len(self.command_history) == 0 or (
                 len(self.command_history) > 0
                 and self.current_line != self.command_history[-1]):
             self.command_history.append(self.current_line)
             self.history_file.write(self.current_line + '\n')
         self.parse(self.current_line)
         self.current_line = ''
         self.history_index = 0
     elif keystr == 'Tab':
         # TODO: autocomplete (commands, filenames)
         pass
     elif keystr == 'Up':
         # page back through command history
         self.visit_command_history(self.history_index - 1)
     elif keystr == 'Down':
         # page forward through command history
         self.visit_command_history(self.history_index + 1)
     elif keystr == 'Backspace' and len(self.current_line) > 0:
         # alt-backspace: delete to last delimiter, eg periods
         if alt_pressed:
             # "index to delete to"
             delete_index = -1
             for delimiter in delimiters:
                 this_delimiter_index = self.current_line.rfind(delimiter)
                 if this_delimiter_index > delete_index:
                     delete_index = this_delimiter_index
             if delete_index > -1:
                 self.current_line = self.current_line[:delete_index]
             else:
                 self.current_line = ''
                 # user is bailing on whatever they were typing,
                 # reset position in cmd history
                 self.history_index = 0
         else:
             self.current_line = self.current_line[:-1]
             if len(self.current_line) == 0:
                 # same as above: reset position in cmd history
                 self.history_index = 0
     elif keystr == 'Space':
         keystr = ' '
     # ignore any other non-character keys
     if len(keystr) > 1:
         return
     if keystr.isalpha() and not shift_pressed:
         keystr = keystr.lower()
     elif not keystr.isalpha() and shift_pressed:
         keystr = SHIFT_MAP.get(keystr, '')
     if len(self.current_line) < self.max_line_length:
         self.current_line += keystr
示例#15
0
def trackerChildFunction(qTo,
                         qFrom,
                         camIndex=0,
                         camRes=[1920, 1080],
                         previewDownsize=2,
                         previewLoc=[0, 0],
                         faceDetectionScale=10,
                         eyeDetectionScale=5,
                         timestampMethod=0,
                         viewingDistance=100,
                         stimDisplayWidth=100,
                         stimDisplayRes=[1920, 1080],
                         stimDisplayPosition=[0, 0],
                         mirrorDisplayPosition=[0, 0],
                         mirrorDownSize=2,
                         manualCalibrationOrder=True,
                         calibrationDotSizeInDegrees=.5):
    import fileForker
    import numpy
    import cv2
    import scipy.ndimage.filters
    # import scipy.interpolate
    import sys
    import sdl2
    import sdl2.ext
    import sdl2.sdlmixer

    #define a class for a clickable text UI
    class clickableText:
        def __init__(self, x, y, text, rightJustified=False, valueText=''):
            self.x = x
            self.y = y
            self.text = text
            self.rightJustified = rightJustified
            self.valueText = valueText
            self.isActive = False
            self.clicked = False
            self.updateSurf()

        def updateSurf(self):
            if self.isActive:
                self.surf = sdl2.sdlttf.TTF_RenderText_Blended_Wrapped(
                    font, self.text + self.valueText,
                    sdl2.pixels.SDL_Color(r=0, g=255, b=255, a=255),
                    previewWindow.size[0]).contents
            else:
                self.surf = sdl2.sdlttf.TTF_RenderText_Blended_Wrapped(
                    font, self.text + self.valueText,
                    sdl2.pixels.SDL_Color(r=0, g=0, b=255, a=255),
                    previewWindow.size[0]).contents

        def checkIfActive(self, event):
            if self.rightJustified:
                xLeft = self.x - self.surf.w
                xRight = self.x
            else:
                xLeft = self.x
                xRight = self.x + self.surf.w
            if (event.button.x > xLeft) & (event.button.x < xRight) & (
                    event.button.y > self.y) & (event.button.y <
                                                (self.y + fontSize)):
                self.isActive = True
            else:
                self.isActive = False
            self.updateSurf()

        def draw(self, targetWindowSurf):
            if self.rightJustified:
                sdl2.SDL_BlitSurface(
                    self.surf, None, targetWindowSurf,
                    sdl2.SDL_Rect(self.x - self.surf.w, self.y, self.surf.w,
                                  self.surf.h))
            else:
                sdl2.SDL_BlitSurface(
                    self.surf, None, targetWindowSurf,
                    sdl2.SDL_Rect(self.x, self.y, self.surf.w, self.surf.h))

    #define a class for settings
    class settingText(clickableText):
        def __init__(self, value, x, y, text, rightJustified=False):
            self.value = value
            self.valueText = str(value)
            clickableText.__init__(self, x, y, text, rightJustified,
                                   self.valueText)

        def addValue(self, toAdd):
            self.valueText = self.valueText + toAdd
            self.updateSurf()

        def delValue(self):
            if self.valueText != '':
                self.valueText = self.valueText[0:(len(self.valueText) - 1)]
                self.updateSurf()

        def finalizeValue(self):
            try:
                self.value = int(self.valueText)
            except:
                print 'Non-numeric value entered!'

    #define a class for dots
    class dotObj:
        def __init__(self, name, isFid, fid, xPixel, yPixel, radiusPixel,
                     blinkCriterion, blurSize, filterSize):
            self.name = name
            self.isFid = isFid
            self.x = xPixel
            self.y = yPixel
            self.radius = radiusPixel
            self.first = True
            self.last = [self.x, self.y, self.radius]
            self.lost = False
            self.blinkHappened = False
            self.radii = []
            self.SDs = []
            self.lostCount = 0
            self.blinkCriterion = blinkCriterion
            self.blurSize = blurSize
            self.filterSize = filterSize
            self.setPixels()
            if not self.isFid:
                self.makeRelativeToFid(fid)

        def setPixels(self):
            self.xPixel = int(self.x)
            self.yPixel = int(self.y)
            self.radiusPixel = int(self.radius)
            return None

        def makeRelativeToFid(self, fid):
            self.x2 = (self.x - fid.x) / fid.radius
            self.y2 = (self.y - fid.y) / fid.radius
            self.radius2 = self.radius / fid.radius
            return None

        def getDarkEllipse(self, img):
            #if not self.isFid:
            #	#cv2.imwrite(self.name + "_" + "%.2d" % imageNum + "_raw.png" , img)
            try:
                smoothedImg = cv2.GaussianBlur(img,
                                               (self.blurSize, self.blurSize),
                                               0)
                #if not self.isFid:
                #	#cv2.imwrite(self.name + "_" + "%.2d" % imageNum + "_smoothed.png" , img)
            except:
                print 'cv2.GaussianBlur failed'
                # cv2.imwrite('temp.png',img)
                return None
            try:
                dataMin = scipy.ndimage.filters.minimum_filter(
                    smoothedImg, self.filterSize)
            except:
                print 'scipy.ndimage.filters.minimum_filter failed'
                # cv2.imwrite('temp.png',img)
                return None
            if dataMin != None:
                try:
                    minLocs = numpy.where(
                        dataMin < (numpy.min(dataMin) + numpy.std(dataMin)))
                except:
                    print 'numpy.where failed'
                    # cv2.imwrite('temp.png',img)
                    return None
                if len(minLocs[0]) >= 5:
                    try:
                        ellipse = cv2.fitEllipse(
                            numpy.reshape(
                                numpy.column_stack((minLocs[1], minLocs[0])),
                                (len(minLocs[0]), 1, 2)))
                    except:
                        print 'cv2.fitEllipse failed'
                        # cv2.imwrite('temp.png',img)
                        return None
                    return ellipse

        def cropImage(self, img, cropSize):
            xLo = self.xPixel - cropSize
            if xLo < 0:
                xLo = 0
            xHi = self.xPixel + cropSize
            if xHi > img.shape[1]:
                xHi = img.shape[1]
            yLo = self.yPixel - cropSize
            if yLo < 0:
                yLo = 0
            yHi = self.yPixel + cropSize
            if yHi > img.shape[0]:
                yHi = img.shape[0]
            return [img[yLo:yHi, xLo:xHi], xLo, xHi, yLo, yHi]

        def search(self, img):
            if self.first and self.isFid:
                searchSize = 1
            elif self.lost:
                searchSize = 5
            else:
                searchSize = 3
            if self.first:
                self.first = False
            img, xLo, xHi, yLo, yHi = self.cropImage(img=img,
                                                     cropSize=searchSize *
                                                     self.radiusPixel)
            self.ellipse = self.getDarkEllipse(img=img)
            if self.ellipse != None:
                self.ellipse = ((self.ellipse[0][0] + xLo,
                                 self.ellipse[0][1] + yLo), self.ellipse[1],
                                self.ellipse[2])
                self.lost = False
                self.x = self.ellipse[0][0]
                self.y = self.ellipse[0][1]
                self.major = self.ellipse[1][0]
                self.minor = self.ellipse[1][1]
                self.angle = self.ellipse[2]
                self.radius = (self.ellipse[1][0] + self.ellipse[1][1]) / 4
                self.setPixels()
            else:
                self.lost = True

        def checkSearch(self):
            self.medianRadius = numpy.median(self.radii)
            self.critRadius = 10 * ((numpy.median(
                (self.radii - self.medianRadius)**2))**.5)
            #print [self.name, self.radius2,(self.radius2<(1/6)) , (self.radius2>2)]
            if len(self.radii) < 30:
                self.radii.append(self.radius2)
                self.lost = False
            else:
                #fid diameter is 6mm, so range from 1mm to 12mm
                #if (self.radius2<(1/6)) or (self.radius2>2) or (self.radius2<(self.medianRadius - self.critRadius)) or (self.radius2>(self.medianRadius + self.critRadius)):
                if (self.radius2 < (1 / 6)) or (self.radius2 > 2):
                    self.lost = True
                else:
                    self.lost = False
                    self.radii.append(self.radius2)
                if len(self.radii) >= 300:
                    self.radii.pop()

        def checkSD(self, img, fid):
            self.obsSD = numpy.std(
                self.cropImage(img=img, cropSize=5 * fid.radiusPixel)[0])
            self.medianSD = numpy.median(self.SDs)
            self.critSD = self.medianSD * self.blinkCriterion
            #print [self.name,self.obsSD,self.medianSD,self.critSD,self.blinkCriterion]
            if len(self.SDs) < 30:
                self.SDs.append(self.obsSD)
                self.blinkHappened = False
            else:
                if (self.obsSD < self.critSD):
                    self.blinkHappened = True
                else:
                    self.SDs.append(self.obsSD)
                    self.blinkHappened = False
                if len(self.SDs) >= 300:
                    self.SDs.pop()

        def update(self, img, fid, blinkCriterion, blurSize, filterSize):
            self.blinkCriterion = blinkCriterion
            self.blurSize = blurSize
            self.filterSize = filterSize
            self.last = [self.x, self.y, self.radius]
            if self.isFid:
                self.search(img=img)
            else:
                self.checkSD(
                    img=img, fid=fid
                )  #alters the value of self.blinkHappened, amongst other things
                if self.blinkHappened:
                    self.x, self.y, self.radius = self.last
                    self.setPixels()
                    self.makeRelativeToFid(fid)
                else:
                    self.search(
                        img=img
                    )  #alters the value of self.lost, amongst other things
                    if self.lost:
                        self.x, self.y, self.radius = self.last
                        self.setPixels()
                        self.makeRelativeToFid(fid)
                    else:
                        self.makeRelativeToFid(fid=fid)
                        self.checkSearch(
                        )  #alters the value of self.lost, among other things
                        if self.lost:
                            self.x, self.y, self.radius = self.last
                            self.setPixels()
                            self.makeRelativeToFid(fid)
            if self.lost and not self.blinkHappened:
                self.lostCount += 1
            else:
                self.lostCount = 0

    ########
    # Initialize audio and define a class that handles playing sounds in PySDL2
    ########
    sdl2.SDL_Init(sdl2.SDL_INIT_AUDIO)
    sdl2.sdlmixer.Mix_OpenAudio(44100, sdl2.sdlmixer.MIX_DEFAULT_FORMAT, 2,
                                1024)

    class Sound:
        def __init__(self, fileName):
            self.sample = sdl2.sdlmixer.Mix_LoadWAV(
                sdl2.ext.compat.byteify(fileName, "utf-8"))
            self.started = False

        def play(self):
            self.channel = sdl2.sdlmixer.Mix_PlayChannel(-1, self.sample, 0)
            self.started = True

        def stillPlaying(self):
            if self.started:
                if sdl2.sdlmixer.Mix_Playing(self.channel):
                    return True
                else:
                    self.started = False
                    return False

    ########
    # define some useful functions
    ########

    #define a function to exit safely
    def exitSafely():
        qFrom.put('done')
        sys.exit()

    #define a function to rescale
    def rescaleBiggestHaar(detected, scale, addToX=0, addToY=0):
        x, y, w, h = detected[numpy.argmax(
            [numpy.sqrt(w * w + h * h) for x, y, w, h in detected])]
        return [x * scale + addToX, y * scale + addToY, w * scale, h * scale]

    ########
    # Initialize variables
    ########

    #initialize sounds
    blinkSound = Sound('./pytracker/Resources/sounds/beep.wav')
    saccadeSound = Sound('./pytracker/Resources/sounds/stop.wav')

    #specify the getTime function
    if (timestampMethod == 0) or (timestampMethod == 1):
        #initialize timer
        sdl2.SDL_Init(sdl2.SDL_INIT_TIMER)
        if timestampMethod == 0:
            #define a function to use the high-precision timer, returning a float in seconds
            def getTime():
                return sdl2.SDL_GetPerformanceCounter(
                ) * 1.0 / sdl2.SDL_GetPerformanceFrequency()
        elif timestampMethod == 1:
            #use the SDL_GetTicks timer
            def getTime():
                return sdl2.SDL_GetTicks() / 1000.0
    elif timestampMethod == 2:
        #use time.time
        import time
        getTime = time.time

    #initialize font
    fontSize = camRes[1] / previewDownsize / 10
    sdl2.sdlttf.TTF_Init()
    font = sdl2.sdlttf.TTF_OpenFont('./pytracker/Resources/DejaVuSans.ttf',
                                    fontSize)

    #initialize preview video
    sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO)
    previewWindow = sdl2.ext.Window("Preview",
                                    size=(camRes[0] / previewDownsize,
                                          camRes[1] / previewDownsize),
                                    position=previewLoc,
                                    flags=sdl2.SDL_WINDOW_SHOWN)
    previewWindowSurf = sdl2.SDL_GetWindowSurface(previewWindow.window)
    previewWindowArray = sdl2.ext.pixels3d(previewWindowSurf.contents)
    sdl2.ext.fill(previewWindowSurf.contents,
                  sdl2.pixels.SDL_Color(r=255, g=255, b=255, a=255))
    previewWindow.refresh()
    lastRefreshTime = getTime()

    #initialize the settings window
    settingsWindow = sdl2.ext.Window(
        "Settings",
        size=(camRes[0] / previewDownsize, camRes[1] / previewDownsize),
        position=[
            previewLoc[0] + camRes[0] / previewDownsize + 1, previewLoc[1]
        ])
    settingsWindowSurf = sdl2.SDL_GetWindowSurface(settingsWindow.window)
    settingsWindowArray = sdl2.ext.pixels3d(settingsWindowSurf.contents)
    sdl2.ext.fill(settingsWindowSurf.contents,
                  sdl2.pixels.SDL_Color(r=0, g=0, b=0, a=255))
    settingsWindow.hide()
    settingsWindow.refresh()

    #import the haar cascades
    faceCascade = cv2.CascadeClassifier(
        './pytracker/Resources/cascades/haarcascade_frontalface_alt2.xml')
    eyeLeftCascade = cv2.CascadeClassifier(
        './pytracker/Resources/cascades/LEye18x12.1.xml')
    eyeRightCascade = cv2.CascadeClassifier(
        './pytracker/Resources/cascades/REye18x12.1.xml')

    #create some settings
    settingsDict = {}
    settingsDict['blink'] = settingText(value=75,
                                        x=fontSize,
                                        y=fontSize,
                                        text='Blink (0-100) = ')
    settingsDict['blur'] = settingText(value=3,
                                       x=fontSize,
                                       y=fontSize * 2,
                                       text='Blur (0-; odd only) = ')
    settingsDict['filter'] = settingText(value=3,
                                         x=fontSize,
                                         y=fontSize * 3,
                                         text='Filter (0-; odd only) = ')
    settingsDict['saccade0'] = settingText(value=50,
                                           x=fontSize,
                                           y=fontSize * 4,
                                           text='Saccade (0-) = ')
    settingsDict['saccade'] = settingText(value=1,
                                          x=fontSize,
                                          y=fontSize * 5,
                                          text='Calibrated Saccade (0-) = ')

    #create some text UIs
    clickableTextDict = {}
    clickableTextDict['manual'] = clickableText(x=0, y=0, text='Manual')
    clickableTextDict['auto'] = clickableText(x=0, y=fontSize, text='Auto')
    clickableTextDict['calibrate'] = clickableText(x=0,
                                                   y=previewWindow.size[1] -
                                                   fontSize,
                                                   text='Calibrate')
    clickableTextDict['settings'] = clickableText(x=previewWindow.size[0],
                                                  y=0,
                                                  text='Settings',
                                                  rightJustified=True)
    clickableTextDict['lag'] = clickableText(x=previewWindow.size[0],
                                             y=previewWindow.size[1] -
                                             fontSize * 2,
                                             text='Lag: ',
                                             rightJustified=True)
    clickableTextDict['f2f'] = clickableText(x=previewWindow.size[0],
                                             y=previewWindow.size[1] -
                                             fontSize,
                                             text='Frame-to-frame: ',
                                             rightJustified=True)

    #initialize variables
    previewInFocus = True
    settingsInFocus = False
    lastTime = 0
    dotList = []
    lastLocs = [None, None]
    displayLagList = []
    frameToFrameTimeList = []
    doHaar = False
    clickingForDots = False
    calibrating = False
    doneCalibration = False
    doSounds = True
    queueDataToParent = False

    #set dummy calibration coefficients (yields untransformed pixel locs)
    calibrationCoefs = [[0, 1, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 1, 0]]

    ########
    # Initialize camera
    ########
    vc = cv2.VideoCapture(camIndex)
    vc.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, camRes[0])
    vc.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, camRes[1])
    imageNum = 0

    #start the loop
    while True:

        #poll the camera
        t1 = getTime()  #time right before requesting the image
        _, image = vc.read()  #request the image
        t2 = getTime()  #time right after requesting the image
        imageTime = t1 + (
            t2 - t1
        ) / 2.0  #timestamp the image as halfway between times before and after request
        image = image[:, :, 2]  #grab red channel (image is BGR)
        imageNum += 1  #iterate the image number

        #check for messages from the main process
        if not qTo.empty():
            message = qTo.get()
            if message == 'quit':
                exitSafely()

        #process input
        sdl2.SDL_PumpEvents()
        for event in sdl2.ext.get_events():
            if event.type == sdl2.SDL_WINDOWEVENT:
                targetWindow = sdl2.SDL_GetWindowFromID(event.window.windowID)
                title = sdl2.SDL_GetWindowTitle(targetWindow)
                # if event.window.event==sdl2.SDL_WINDOWEVENT_FOCUS_GAINED:
                # 	print title + "focused"
                # if event.window.event==sdl2.SDL_WINDOWEVENT_ENTER:
                # 	print title + " entered"
                # elif event.window.event==sdl2.SDL_WINDOWEVENT_FOCUS_LOST:
                # 	print title + " lost focus"
                if event.window.event == sdl2.SDL_WINDOWEVENT_LEAVE:
                    if title == 'Preview':
                        previewInFocus = False
                        settingsInFocus = True
                if (event.window.event == sdl2.SDL_WINDOWEVENT_FOCUS_GAINED
                    ) or (event.window.event == sdl2.SDL_WINDOWEVENT_ENTER):
                    if title == 'Preview':
                        previewInFocus = True
                        settingsInFocus = False
                    elif title == 'Settings':
                        previewInFocus = False
                        settingsInFocus = True
                elif (event.window.event == sdl2.SDL_WINDOWEVENT_CLOSE):
                    if title == 'Preview':
                        exitSafely()
                    elif title == 'Settings':
                        previewInFocus = True
                        settingsInFocus = False
                        settingsWindow.hide()
                        previewWindow.show()
            elif settingsInFocus:
                # if event.type==sdl2.SDL_MOUSEBUTTONUP:
                # 	if blinkTextButtonDown:
                # 		blinkTextButtonDown = False
                # if event.type==sdl2.SDL_MOUSEBUTTONDOWN:
                # 	if mouseInBlinkText:
                # 		blinkTextButtonDown = True
                if event.type == sdl2.SDL_MOUSEMOTION:
                    alreadyClicked = False
                    for setting in settingsDict:
                        if (settingsDict[setting].isActive) and (
                                settingsDict[setting].clicked):
                            alreadyClicked = True
                    if not alreadyClicked:
                        for setting in settingsDict:
                            settingsDict[setting].checkIfActive(event)
                elif event.type == sdl2.SDL_MOUSEBUTTONDOWN:
                    alreadyClicked = False
                    for setting in settingsDict:
                        if (settingsDict[setting].isActive) and (
                                settingsDict[setting].clicked):
                            alreadyClicked = True
                    if not alreadyClicked:
                        for setting in settingsDict:
                            if settingsDict[setting].isActive:
                                settingsDict[setting].clicked = True
                elif event.type == sdl2.SDL_KEYDOWN:
                    key = sdl2.SDL_GetKeyName(event.key.keysym.sym).lower()
                    if key == 'backspace':
                        for setting in settingsDict:
                            if (settingsDict[setting].isActive) and (
                                    settingsDict[setting].clicked):
                                settingsDict[setting].delValue()
                    elif key == 'return':
                        for setting in settingsDict:
                            if (settingsDict[setting].isActive) and (
                                    settingsDict[setting].clicked):
                                settingsDict[setting].finalizeValue()
                                settingsDict[setting].clicked = False
                    else:
                        for setting in settingsDict:
                            if (settingsDict[setting].isActive) and (
                                    settingsDict[setting].clicked):
                                settingsDict[setting].addValue(key)
            elif previewInFocus:
                if event.type == sdl2.SDL_KEYDOWN:
                    key = sdl2.SDL_GetKeyName(event.key.keysym.sym).lower()
                    if key == 'escape':  #exit
                        # exitSafely()
                        clickingForDots = False
                        clickingForFid = False
                        definingFidFinderBox = False
                        dotList = []
                if event.type == sdl2.SDL_MOUSEMOTION:
                    if clickingForDots:
                        clickableTextDict[
                            'manual'].isActive = True  #just making sure
                        if definingFidFinderBox:
                            fidFinderBoxSize = abs(fidFinderBoxX -
                                                   (previewWindow.size[0] -
                                                    event.button.x))
                    else:
                        for clickableText in clickableTextDict:
                            if not (clickableText in ['lag', 'f2f']):
                                clickableTextDict[clickableText].checkIfActive(
                                    event)
                if event.type == sdl2.SDL_MOUSEBUTTONDOWN:
                    if clickingForDots:
                        if clickingForFid:
                            if not definingFidFinderBox:
                                definingFidFinderBox = True
                                fidFinderBoxX = previewWindow.size[
                                    0] - event.button.x
                                fidFinderBoxY = event.button.y
                                fidFinderBoxSize = 0
                            else:
                                definingFidFinderBox = False
                                clickingForFid = False
                                fidFinderBoxSize = abs(fidFinderBoxX -
                                                       (previewWindow.size[0] -
                                                        event.button.x))
                                dotList.append(
                                    dotObj(
                                        name='fid',
                                        isFid=True,
                                        fid=None,
                                        xPixel=fidFinderBoxX * previewDownsize,
                                        yPixel=fidFinderBoxY * previewDownsize,
                                        radiusPixel=fidFinderBoxSize *
                                        previewDownsize,
                                        blinkCriterion=settingsDict['blink'].
                                        value / 100.0,
                                        blurSize=settingsDict['blur'].value,
                                        filterSize=settingsDict['filter'].value
                                    ))
                        else:
                            clickX = (previewWindow.size[0] - event.button.x)
                            clickY = event.button.y
                            if len(dotList) == 1:
                                dotList.append(
                                    dotObj(
                                        name='left',
                                        isFid=False,
                                        fid=dotList[0],
                                        xPixel=clickX * previewDownsize,
                                        yPixel=clickY * previewDownsize,
                                        radiusPixel=dotList[0].radiusPixel,
                                        blinkCriterion=settingsDict['blink'].
                                        value / 100.0,
                                        blurSize=settingsDict['blur'].value,
                                        filterSize=settingsDict['filter'].value
                                    ))
                            else:
                                dotList.append(
                                    dotObj(
                                        name='right',
                                        isFid=False,
                                        fid=dotList[0],
                                        xPixel=clickX * previewDownsize,
                                        yPixel=clickY * previewDownsize,
                                        radiusPixel=dotList[1].radiusPixel,
                                        blinkCriterion=settingsDict['blink'].
                                        value / 100.0,
                                        blurSize=settingsDict['blur'].value,
                                        filterSize=settingsDict['filter'].value
                                    ))
                                clickingForDots = False
                                manTextSurf = sdl2.sdlttf.TTF_RenderText_Blended_Wrapped(
                                    font, 'Manual',
                                    sdl2.pixels.SDL_Color(r=0,
                                                          g=0,
                                                          b=255,
                                                          a=255),
                                    previewWindow.size[0]).contents
                    else:
                        if clickableTextDict['settings'].isActive:
                            if (sdl2.SDL_GetWindowFlags(settingsWindow.window)
                                    & sdl2.SDL_WINDOW_SHOWN):
                                settingsWindow.hide()
                            else:
                                settingsWindow.show()
                        elif clickableTextDict['auto'].isActive:
                            waitingforHaar = False
                            doHaar = True  #triggers haar detection for next frame
                            dotList = []
                        elif clickableTextDict['manual'].isActive:
                            clickingForDots = True
                            clickingForFid = True
                            definingFidFinderBox = False
                            dotList = []
                        elif clickableTextDict['calibrate'].isActive:
                            doneCalibration = False
                            calibrationChild = fileForker.childClass(
                                childFile='calibrationChild')
                            calibrationChild.initDict[
                                'timestampMethod'] = timestampMethod
                            calibrationChild.initDict[
                                'viewingDistance'] = viewingDistance
                            calibrationChild.initDict[
                                'stimDisplayWidth'] = stimDisplayWidth
                            calibrationChild.initDict[
                                'stimDisplayRes'] = stimDisplayRes
                            calibrationChild.initDict[
                                'stimDisplayPosition'] = stimDisplayPosition
                            calibrationChild.initDict[
                                'mirrorDisplayPosition'] = mirrorDisplayPosition
                            calibrationChild.initDict[
                                'mirrorDownSize'] = mirrorDownSize
                            calibrationChild.initDict[
                                'calibrationDotSizeInDegrees'] = calibrationDotSizeInDegrees
                            calibrationChild.initDict[
                                'manualCalibrationOrder'] = manualCalibrationOrder
                            calibrationChild.start()
                            calibrating = True
                            checkCalibrationStopTime = False
                            queueDataToCalibrationChild = False

        #do haar detection if requested
        if doHaar:
            doHaar = False  #only enter this section once
            faceDetectionImage = cv2.resize(
                image,
                dsize=(image.shape[1] / faceDetectionScale,
                       image.shape[0] / faceDetectionScale),
                interpolation=cv2.INTER_NEAREST)
            detectedFaces = faceCascade.detectMultiScale(
                faceDetectionImage
            )  #,scaleFactor=1.1,minNeighbors=3,minSize=(10,10))
            if len(detectedFaces) == 0:  #no faces found!
                print 'no faces found!'  #do something here
            else:
                faceX, faceY, faceW, faceH = rescaleBiggestHaar(
                    detected=detectedFaces,
                    scale=faceDetectionScale,
                    addToX=0,
                    addToY=0)
                leftFaceImage = image[faceY:(faceY + faceH),
                                      faceX:(faceX + faceW / 2)]
                eyeLeftDetectionImage = cv2.resize(
                    leftFaceImage,
                    dsize=(leftFaceImage.shape[1] / eyeDetectionScale,
                           leftFaceImage.shape[0] / eyeDetectionScale),
                    interpolation=cv2.INTER_NEAREST)
                detectedEyeLefts = eyeLeftCascade.detectMultiScale(
                    eyeLeftDetectionImage
                )  #,minSize=(leftFaceImage.shape[0]/8,leftFaceImage.shape[0]/8))
                rightFaceImage = image[faceY:(faceY + faceH),
                                       (faceX + faceW / 2):(faceX + faceW)]
                eyeRightDetectionImage = cv2.resize(
                    rightFaceImage,
                    dsize=(rightFaceImage.shape[1] / eyeDetectionScale,
                           rightFaceImage.shape[0] / eyeDetectionScale),
                    interpolation=cv2.INTER_NEAREST)
                detectedEyeRights = eyeRightCascade.detectMultiScale(
                    eyeRightDetectionImage
                )  #,minSize=(rightFaceImage.shape[0]/8,rightFaceImage.shape[0]/8))
                if (len(detectedEyeLefts)
                        == 0) | (len(detectedEyeRights)
                                 == 0):  #at least one eye is missing!
                    if (len(detectedEyeLefts) == 0):
                        print 'left eye missing'  #do something here
                    else:
                        print 'right eye missing'  #do something here
                else:
                    eyeLeftX, eyeLeftY, eyeLeftW, eyeLeftH = rescaleBiggestHaar(
                        detected=detectedEyeLefts,
                        scale=eyeDetectionScale,
                        addToX=faceX,
                        addToY=faceY)
                    eyeRightX, eyeRightY, eyeRightW, eyeRightH = rescaleBiggestHaar(
                        detected=detectedEyeRights,
                        scale=eyeDetectionScale,
                        addToX=faceX + faceW / 2,
                        addToY=faceY)
                    #initialize fid
                    dotList.append(
                        dotObj(name='fid',
                               isFid=True,
                               fid=None,
                               xPixel=faceX + faceW / 2,
                               yPixel=(faceY + (eyeLeftY + eyeRightY) / 2) / 2,
                               radiusPixel=(eyeLeftH + eyeRightH) / 4,
                               blinkCriterion=settingsDict['blink'].value /
                               100.0,
                               blurSize=settingsDict['blur'].value,
                               filterSize=settingsDict['filter'].value))
                    #initialize left
                    dotList.append(
                        dotObj(name='left',
                               isFid=False,
                               fid=dotList[0],
                               xPixel=eyeLeftX + eyeLeftW / 2,
                               yPixel=eyeLeftY + eyeLeftH / 2,
                               radiusPixel=eyeLeftH / 2,
                               blinkCriterion=settingsDict['blink'].value /
                               100.0,
                               blurSize=settingsDict['blur'].value,
                               filterSize=settingsDict['filter'].value))
                    #initialize right
                    dotList.append(
                        dotObj(name='right',
                               isFid=False,
                               fid=dotList[0],
                               xPixel=eyeRightX + eyeRightW / 2,
                               yPixel=eyeRightY + eyeRightH / 2,
                               radiusPixel=eyeRightH / 2,
                               blinkCriterion=settingsDict['blink'].value /
                               100.0,
                               blurSize=settingsDict['blur'].value,
                               filterSize=settingsDict['filter'].value))

        #update the dots given the latest image
        for i in range(len(dotList)):
            dotList[i].update(img=image,
                              fid=dotList[0],
                              blinkCriterion=settingsDict['blink'].value /
                              100.0,
                              blurSize=settingsDict['blur'].value,
                              filterSize=settingsDict['filter'].value)
            # print 'ok'

        #some post-processing
        blinkHappened = False
        saccadeHappened = False
        if len(dotList) == 3:
            if dotList[0].lost:
                dotList = []
                print 'fid lost'
            elif (dotList[1].lostCount > 30) or (dotList[2].lostCount > 30):
                print "lost lots"
                if (not dotList[1].blinkHappened) and (
                        not dotList[2].blinkHappened
                ):  #only reset if not blinking
                    dotList = []
            elif dotList[1].blinkHappened and dotList[2].blinkHappened:
                blinkHappened = True
            else:
                #compute gaze location to check for saccades
                xCoefLeft, xCoefRight, yCoefLeft, yCoefRight = calibrationCoefs
                if dotList[1].lost:  #left missing, use right
                    xLoc = xCoefRight[0] + xCoefRight[1] * dotList[
                        2].x2 + xCoefRight[2] * dotList[2].y2 + xCoefRight[
                            3] * dotList[2].y2 * dotList[2].x2
                    yLoc = yCoefRight[0] + yCoefRight[1] * dotList[
                        2].x2 + yCoefRight[2] * dotList[2].y2 + yCoefRight[
                            3] * dotList[2].y2 * dotList[2].x2
                elif dotList[2].lost:  #right missing, use left
                    xLoc = xCoefLeft[0] + xCoefLeft[1] * dotList[
                        1].x2 + xCoefLeft[2] * dotList[1].y2 + xCoefLeft[
                            3] * dotList[2].y2 * dotList[1].x2
                    yLoc = yCoefLeft[0] + yCoefLeft[1] * dotList[
                        1].x2 + yCoefLeft[2] * dotList[1].y2 + yCoefLeft[
                            3] * dotList[2].y2 * dotList[1].x2
                elif dotList[1].lost and dotList[
                        2].lost:  #both missing, use last
                    xLoc = lastLocs[0]
                    yLoc = lastLocs[1]
                else:  #both present, use average
                    xLocLeft = xCoefLeft[0] + xCoefLeft[1] * dotList[
                        1].x2 + xCoefLeft[2] * dotList[1].y2 + xCoefLeft[
                            3] * dotList[1].y2 * dotList[1].x2
                    yLocLeft = yCoefLeft[0] + yCoefLeft[1] * dotList[
                        1].x2 + yCoefLeft[2] * dotList[1].y2 + yCoefLeft[
                            3] * dotList[1].y2 * dotList[1].x2
                    xLocRight = xCoefRight[0] + xCoefRight[1] * dotList[
                        2].x2 + xCoefRight[2] * dotList[2].y2 + xCoefRight[
                            3] * dotList[2].y2 * dotList[2].x2
                    yLocRight = yCoefRight[0] + yCoefRight[1] * dotList[
                        2].x2 + yCoefRight[2] * dotList[2].y2 + yCoefRight[
                            3] * dotList[2].y2 * dotList[2].x2
                    xLoc = (xLocLeft + xLocRight) / 2.0
                    yLoc = (yLocLeft + yLocRight) / 2.0
                if None not in lastLocs:
                    locDiff = (((xLoc - lastLocs[0])**2) +
                               ((yLoc - lastLocs[1])**2))**.5
                    if doneCalibration:
                        saccadeCriterion = settingsDict['saccade'].value
                    else:
                        saccadeCriterion = settingsDict[
                            'saccade0'].value / 100.0
                    if locDiff > saccadeCriterion:
                        saccadeHappened = True
                lastLocs = [xLoc, yLoc]
                if queueDataToParent:
                    qFrom.put([
                        'eyeData',
                        [
                            str.format('{0:.3f}', imageTime), xLoc, yLoc,
                            dotlist[1].radius2, dotlist[2].radius2,
                            saccadeHappened, blinkHappened, dotList[1].lost,
                            dotList[2].lost, dotList[1].blinkHappened,
                            dotList[2].blinkHappened
                        ]
                    ])

        #play sounds as necessary
        if doSounds:
            if (not saccadeSound.stillPlaying()) and (
                    not blinkSound.stillPlaying()):
                if blinkHappened:
                    blinkSound.play()
                elif saccadeHappened:
                    saccadeSound.play()

        #do drawing
        if previewDownsize != 1:
            image = cv2.resize(image,
                               dsize=previewWindow.size,
                               interpolation=cv2.INTER_NEAREST)
        image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
        if clickingForDots:
            if clickingForFid:
                if definingFidFinderBox:
                    cv2.circle(image, (fidFinderBoxX, fidFinderBoxY),
                               fidFinderBoxSize,
                               color=(255, 0, 0, 255),
                               thickness=1)
        for dot in dotList:
            ellipse = ((dot.ellipse[0][0] / previewDownsize,
                        dot.ellipse[0][1] / previewDownsize),
                       (dot.ellipse[1][0] / previewDownsize,
                        dot.ellipse[1][1] / previewDownsize), dot.ellipse[2])
            if dot.blinkHappened or dot.lost:
                dotColor = (0, 0, 255, 255)
            else:
                dotColor = (0, 255, 0, 255)
            cv2.ellipse(image, ellipse, color=dotColor, thickness=1)
        image = numpy.rot90(image)
        previewWindowArray[:, :, 0:3] = image
        frameToFrameTimeList.append(imageTime - lastTime)
        lastTime = imageTime
        displayLagList.append(getTime() - imageTime)
        if len(displayLagList) > 30:
            displayLagList.pop(0)
            frameToFrameTimeList.pop(0)
        clickableTextDict['lag'].valueText = str(
            int(numpy.median(displayLagList) * 1000))
        clickableTextDict['lag'].updateSurf()
        clickableTextDict['f2f'].valueText = str(
            int(numpy.median(frameToFrameTimeList) * 1000))
        clickableTextDict['f2f'].updateSurf()
        for clickableText in clickableTextDict:
            clickableTextDict[clickableText].draw(previewWindowSurf)
        previewWindow.refresh()
        thisRefreshTime = getTime()
        # print (thisRefreshTime - lastRefreshTime)*1000
        lastRefreshTime = thisRefreshTime
        if (sdl2.SDL_GetWindowFlags(settingsWindow.window)
                & sdl2.SDL_WINDOW_SHOWN):
            sdl2.ext.fill(settingsWindowSurf.contents,
                          sdl2.pixels.SDL_Color(r=0, g=0, b=0, a=255))
            for setting in settingsDict:
                settingsDict[setting].draw(settingsWindowSurf)
            settingsWindow.refresh()

        #calibration stuff
        if calibrating:
            if not calibrationChild.qFrom.empty():
                message = calibrationChild.qFrom.get()
                if message == 'startQueing':
                    queueDataToCalibrationChild = True
                elif message[0] == 'stopQueing':
                    calibrationStopTime = message[1]
                    checkCalibrationStopTime = True
                elif message[0] == 'calibrationCoefs':
                    calibrationCoefs = message[1]
                    calibrating = False
                    doneCalibration = True
                    calibrationChild.stop()
                    del calibrationChild
                    lastLocs = []
                    qFrom.put(['calibrationComplete', message])
                    queueDataToParent = True
                else:
                    print message
            if checkCalibrationStopTime:
                if imageTime > calibrationStopTime:
                    queueDataToCalibrationChild = False
                    calibrationChild.qTo.put('doneQueing')
                    checkCalibrationStopTime = False
            if queueDataToCalibrationChild:
                if len(dotList) > 0:
                    calibrationChild.qTo.put([
                        imageTime, dotList[1].x2, dotList[1].y2, dotList[2].x2,
                        dotList[2].y2
                    ])
示例#16
0
    def on_bind_key(self, widget, param, section, name, double):
        controller = None
        if self.parent.m64p_wrapper.ConfigGetParameter('name') == "Keyboard":
            device = "keyboard"
        else:
            device = "gamepad"
            stored_name = self.parent.m64p_wrapper.ConfigGetParameter('name')
            for joy_id, instance in self.active_gamepads.items():
                this_name = sdl.SDL_JoystickName(instance).decode("utf-8")
                if this_name == stored_name:
                    controller = self.active_gamepads[joy_id]

        # Now we start preparations for the dialog
        if double == True:
            # In case we have to bind twice in a single GUI button, e.g. for an axis of the controller
            if name == "X Axis":
                first_name = "X Axis (Left)"
                second_name = "X Axis (Right)"
            elif name == "Y Axis":
                first_name = "Y Axis (Up)"
                second_name = "Y Axis (Down)"

            first_value = self.binding(widget, param, device, first_name,
                                       controller, False)
            if first_value[1] != None:
                if first_value[0] != "" and first_value[1] != "empty":
                    if first_value[1] == "Naxis" or first_value[1] == "Paxis":
                        input_type = "axis"
                    else:
                        input_type = first_value[1]
                    different = True
                    while different:
                        # We give some time to the user to reset the control stick to zero.
                        time.sleep(0.2)
                        second_value = self.binding(widget, param, device,
                                                    second_name, controller,
                                                    False)
                        if second_value[1] == "Naxis" or second_value[
                                1] == "Paxis":
                            input_type2 = "axis"
                        elif second_value[1] == None or second_value[
                                1] == "empty":
                            break
                        else:
                            input_type2 = second_value[1]

                        if input_type == input_type2:
                            different = False
                    if second_value[1] != None:
                        if second_value[0] != "" and second_value[1] != "empty":
                            if input_type == "axis":
                                store = input_type + "(" + first_value[0] + ("+" if first_value[1] == "Paxis" else "-") + "," + second_value[0] + \
                                    ("+" if second_value[1] == "Paxis" else "-") + ")"
                                widget.set_label(store)
                                self.parent.m64p_wrapper.ConfigSetParameter(
                                    param, store)
                            elif input_type == "button":
                                store = input_type + "(" + first_value[
                                    0] + "," + second_value[0] + ")"
                                widget.set_label(store)
                                self.parent.m64p_wrapper.ConfigSetParameter(
                                    param, store)
                            elif input_type == "key":
                                widget.set_label(
                                    "(" + sdl.SDL_GetKeyName(
                                        int(first_value[0])).decode("utf-8") +
                                    ", " + sdl.SDL_GetKeyName(
                                        int(second_value[0])).decode("utf-8") +
                                    ")")
                        else:
                            widget.set_label("(empty)")
                            self.parent.m64p_wrapper.ConfigSetParameter(
                                param, second_value[0])

                else:
                    widget.set_label("(empty)")
                    self.parent.m64p_wrapper.ConfigSetParameter(
                        param, first_value[0])
        else:
            self.binding(widget, param, device, name, controller, True)
示例#17
0
def stamperChildFunction(qTo,
                         qFrom,
                         windowSize=[200, 200],
                         windowPosition=[0, 0],
                         windowColor=[255, 255, 255],
                         doBorder=True):
    import sdl2
    import sdl2.ext
    import sys
    import time
    try:
        import appnope
        appnope.nope()
    except:
        pass
    sdl2.SDL_Init(sdl2.SDL_INIT_TIMER)
    timeFreq = 1.0 / sdl2.SDL_GetPerformanceFrequency()
    sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO)
    if doBorder:
        flags = sdl2.SDL_WINDOW_SHOWN
    else:
        flags = sdl2.SDL_WINDOW_BORDERLESS | sdl2.SDL_WINDOW_SHOWN
    window = sdl2.ext.Window("pyStamper",
                             size=windowSize,
                             position=windowPosition,
                             flags=flags)
    windowID = sdl2.SDL_GetWindowID(window.window)
    windowSurf = sdl2.SDL_GetWindowSurface(window.window)
    red = sdl2.pixels.SDL_Color(r=255, g=0, b=0, a=255)
    green = sdl2.pixels.SDL_Color(r=0, g=255, b=0, a=255)
    black = sdl2.pixels.SDL_Color(r=0, g=0, b=0, a=255)
    white = sdl2.pixels.SDL_Color(r=255, g=255, b=255, a=255)
    if doBorder:
        sdl2.ext.fill(windowSurf.contents, green)
    else:
        sdl2.ext.fill(
            windowSurf.contents,
            sdl2.pixels.SDL_Color(r=windowColor[0],
                                  g=windowColor[1],
                                  b=windowColor[2],
                                  a=255))
    window.refresh()

    for i in range(10):
        sdl2.SDL_PumpEvents()  #to show the windows

    sdl2.SDL_Init(
        sdl2.SDL_INIT_JOYSTICK)  #uncomment if you want joystick input
    sdl2.SDL_JoystickOpen(0)  #uncomment if you want joystick input
    lostFocus = True
    lostColors = [red, black, red, white]
    lastRefreshTime = time.time()
    while True:
        if lostFocus and doBorder:
            if time.time() > (lastRefreshTime + (2.0 / 60)):
                sdl2.ext.fill(windowSurf.contents, lostColors[0])
                window.refresh()
                lostColors.append(lostColors.pop(0))
                lastRefreshTime = time.time()
        sdl2.SDL_PumpEvents()
        if not qTo.empty():
            message = qTo.get()
            if message == 'quit':
                sys.exit()
            elif message == 'raise':
                sdl2.SDL_RaiseWindow(window.window)
        for event in sdl2.ext.get_events():
            if event.type == sdl2.SDL_WINDOWEVENT:
                if event.window.windowID == windowID:
                    if (event.window.event == sdl2.SDL_WINDOWEVENT_CLOSE):
                        qFrom.put({
                            'type': 'key',
                            'time': event.window.timestamp * timeFreq,
                            'value': 'escape'
                        })
                        sys.exit()
                    elif event.window.event == sdl2.SDL_WINDOWEVENT_FOCUS_LOST:
                        lostFocus = True
                    elif event.window.event == sdl2.SDL_WINDOWEVENT_FOCUS_GAINED:
                        lostFocus = False
                        if doBorder:
                            sdl2.ext.fill(windowSurf.contents, green)
                            window.refresh()
            else:
                message = {}
                if event.type == sdl2.SDL_KEYDOWN:
                    message['type'] = 'key'
                    message['time'] = event.key.timestamp * timeFreq
                    message['value'] = sdl2.SDL_GetKeyName(
                        event.key.keysym.sym).lower()
                    message['keysym'] = event.key.keysym
                    qFrom.put(message)
                elif event.type == sdl2.SDL_JOYAXISMOTION:
                    message['type'] = 'axis'
                    message['axis'] = event.jaxis.axis
                    message['time'] = event.jaxis.timestamp * timeFreq
                    message['value'] = event.jaxis.value
                    qFrom.put(message)
                elif event.type == sdl2.SDL_JOYBUTTONDOWN:
                    message['type'] = 'button'
                    message['time'] = event.jbutton.timestamp * timeFreq
                    message['value'] = event.jbutton.button
                    qFrom.put(message)