Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

can you stop the recording of mouse events with a keyboard event? #5

Closed
reckoner opened this issue Nov 12, 2017 · 7 comments
Closed

Comments

@reckoner
Copy link

The keyboard project is a related project. Can mouse event recording be stopped with a keyboard?

@boppreh
Copy link
Owner

boppreh commented Nov 12, 2017

Not with the record function, but record is so simple that you can just reimplement it:

def record(button=RIGHT, target_types=(DOWN,)):

My suggestion:

import mouse, keyboard
recorded = []
mouse.hook(recorded.append)
keyboard.wait('esc, esc')
mouse.unhook(recorded.append)
print(recorded)

@boppreh
Copy link
Owner

boppreh commented Nov 12, 2017

If this solves your problem, I'll add to the examples directory.

@reckoner
Copy link
Author

reckoner commented Nov 12, 2017

It does! Thanks!

Along these lines, is it possible to simultaneously record both mouse and keyboard interactions? I have tried the following:

mouse_recorded = []
keyboard_recorded = []
mouse.hook(mouse_recorded.append)
keyboard.hook(keyboard_recorded.append)
keyboard.wait('esc, esc')
mouse.unhook(mouse_recorded.append)
keyboard.unhook(keyboard_recorded.append)
print(mouse_recorded)
print keyboard_recorded

However there is no time-alignment between the two lists, so I don't know the sequential order of the mouse and keyboard interactions.

Any ideas here?

@boppreh
Copy link
Owner

boppreh commented Nov 12, 2017

You can sort them together using lambda i: i.timeas key, or just append both to the same list. But that's not very useful because you still need to split them later to replay.

Thats something still missing from the libraries, but I intent to fix in the future. You can still replay them in separate threads.

@boppreh boppreh closed this as completed Nov 12, 2017
@reckoner
Copy link
Author

class Recorder(object):
    def __init__(self):
        self.mouse_recorded=[]
        self.keyboard_recorded=[]

    def record(self,key_abort_seq='esc, esc'):
        self.mouse_recorded[:] = [] # reset upon new recording
        self.keyboard_recorded[:] = []
        mouse.hook(self.mouse_recorded.append)
        keyboard.hook(self.keyboard_recorded.append)
        keyboard.wait(key_abort_seq)
        mouse.unhook(self.mouse_recorded.append)
        keyboard.unhook(self.keyboard_recorded.append)

    def playmouse(self,**kwds):
        '''
        play only mouse events
        '''
        mouse.play(self.mouse_recorded,**kwds)

    def playkeyboard(self,**kwds):
        '''
        play only keyboard events
        '''
        keyboard.play(self.mouse_recorded,**kwds)

    def play(self,key_speed_factor=1.0, mouse_speed_factor=1.0, **kwds):
        '''
        play both mouse and keyboard events in order
        '''
        k=sorted(self.mouse_recorded+ self.keyboard_recorded,key=lambda i:i.time)
        for c,m in it.groupby(k,key=lambda i:isinstance(i,keyboard.KeyboardEvent)):
            if c:
                speed_factor = kwds.pop('speed_factor',key_speed_factor)
                keyboard.play(m,speed_factor=speed_factor,**kwds)
            else:
                speed_factor = kwds.pop('speed_factor',mouse_speed_factor)
                mouse.play(m,speed_factor=speed_factor,**kwds)

Then, you can do

r = Recorder()
r.record()

Thanks for the headstart!

@boppreh
Copy link
Owner

boppreh commented Nov 13, 2017

Thanks @reckoner for the script. To simplify this process in the future, I'll add an event.replay(speed_factor) method to both keyboard and mouse events. This would allow a simple for event in events: event.replay(). Unfortunately it requires merging the events into the main file for each module to avoid circular dependencies, which breaks compatibility or requires hackish aliases, so I'll wait until the next breaking changeset.

@QiangF
Copy link

QiangF commented Mar 21, 2019

When I call

r = Recorder()
r.record()

I get this error:

File "keyboard/__init__.py", line 465, in hook
    _hooks[callback] = _hooks[remove_] = remove_
TypeError: unhashable type: 'list'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants