Advertisement
Thoughtcoder411

Autonomie v0.2

May 2nd, 2024
563
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 12.39 KB | Source Code | 0 0
  1. import tkinter as tk
  2. from pynput import mouse, keyboard
  3. import time
  4. import threading
  5. import shelve
  6. import os
  7. from tkinter import messagebox, simpledialog, Listbox
  8.  
  9. class MouseRecorderGUI:
  10.     def __init__(self, root):
  11.         self.root = root
  12.         self.recorded_events = []
  13.         self.recording = False
  14.         self.playback_thread = None
  15.         self.playback_stop_requested = False
  16.         self.loop_counter = 0
  17.         self.start_time = None
  18.         self.recordings_dir = self.get_recordings_dir()
  19.         self.create_gui()
  20.         self.create_hotkey_listener()
  21.  
  22.     def get_recordings_dir(self):
  23.         dir_name = "recordings"
  24.         os.makedirs(dir_name, exist_ok=True)
  25.         return dir_name
  26.  
  27.     def create_hotkey_listener(self):
  28.         # Define the hotkeys
  29.         self.hotkeys = {
  30.             'start': '<ctrl>+<alt>+s',
  31.             'stop': '<ctrl>+<alt>+t',
  32.             'save': '<ctrl>+<alt>+e',
  33.             'load': '<ctrl>+<alt>+l',
  34.             'playback': '<ctrl>+<alt>+p',
  35.             'record_mouse': '<ctrl>+<alt>+m',
  36.             'record_keyboard': '<ctrl>+<alt>+k',
  37.             'record_both': '<ctrl>+<alt>+b'
  38.         }
  39.         self.keyboard_listener = keyboard.GlobalHotKeys(self.create_hotkey_callbacks())
  40.         self.keyboard_listener.start()
  41.  
  42.     def create_gui(self):
  43.         # Create the GUI elements here
  44.         self.event_listbox = tk.Listbox(self.root, width=50, height=15)
  45.         self.start_button = tk.Button(self.root, text="Start Recording", command=self.start_recording)
  46.         self.stop_button = tk.Button(self.root, text="Stop Recording", state=tk.DISABLED, command=self.stop_recording)
  47.         self.playback_button = tk.Button(self.root, text="Playback", state=tk.DISABLED, command=self.start_playback)
  48.         self.save_button = tk.Button(self.root, text="Save", state=tk.DISABLED, command=self.save_events)
  49.         self.load_button = tk.Button(self.root, text="Load", command=self.load_events)
  50.         self.loop_counter_label = tk.Label(self.root, text="Loop Count: 0")
  51.         self.repeat_count_spinbox = tk.Spinbox(self.root, from_=1, to=100, width=5)
  52.         self.playback_speed_scale = tk.Scale(self.root, from_=0.1, to=2.0, resolution=0.1, orient=tk.HORIZONTAL)
  53.         self.configure_playback_button = tk.Button(self.root, text="Configure Playback", command=self.configure_playback)
  54.  
  55.         # Pack GUI elements here
  56.         self.event_listbox.pack()
  57.         self.start_button.pack()
  58.         self.stop_button.pack()
  59.         self.playback_button.pack()
  60.         self.save_button.pack()
  61.         self.load_button.pack()
  62.         self.loop_counter_label.pack()
  63.         self.repeat_count_spinbox.pack()
  64.         self.playback_speed_scale.pack()
  65.         self.configure_playback_button.pack()
  66.  
  67.     def create_hotkey_callbacks(self):
  68.         # Hotkey callbacks
  69.         return {
  70.             self.hotkeys['start']: self.start_recording,
  71.             self.hotkeys['stop']: self.stop_recording,
  72.             self.hotkeys['save']: self.save_events,
  73.             self.hotkeys['load']: self.load_events,
  74.             self.hotkeys['playback']: self.start_playback_from_hotkey,
  75.             self.hotkeys['record_mouse']: lambda: self.start_recording(record_mouse=True),
  76.             self.hotkeys['record_keyboard']: lambda: self.start_recording(record_keyboard=True),
  77.             self.hotkeys['record_both']: lambda: self.start_recording(record_mouse=True, record_keyboard=True)
  78.         }
  79.  
  80.     def start_recording(self, record_mouse=False, record_keyboard=False):
  81.         if not self.recording:
  82.             self.recording = True
  83.             self.recorded_events = []
  84.             self.start_time = time.time()
  85.             if record_mouse:
  86.                 self.mouse_listener = mouse.Listener(on_click=self.on_click, on_move=self.on_move)
  87.                 self.mouse_listener.start()
  88.             if record_keyboard:
  89.                 self.keyboard_listener = keyboard.Listener(on_press=self.on_press)
  90.                 self.keyboard_listener.start()
  91.             self.toggle_buttons_during_recording(True)
  92.  
  93.     def stop_recording(self):
  94.         if self.recording:
  95.             self.recording = False
  96.             if hasattr(self, 'mouse_listener'):
  97.                 self.mouse_listener.stop()
  98.             if hasattr(self, 'keyboard_listener'):
  99.                 self.keyboard_listener.stop()
  100.             self.toggle_buttons_during_recording(False)
  101.             self.update_event_listbox()
  102.  
  103.     def toggle_buttons_during_recording(self, recording):
  104.         # Enable/Disable buttons based on whether we are recording
  105.         state = tk.DISABLED if recording else tk.NORMAL
  106.         self.start_button.config(state=tk.DISABLED if recording else tk.NORMAL)
  107.         self.stop_button.config(state=tk.NORMAL if recording else tk.DISABLED)
  108.         self.playback_button.config(state=state)
  109.         self.save_button.config(state=state)
  110.         self.load_button.config(state=state)
  111.  
  112.     def on_click(self, x, y, button, pressed):
  113.         if self.recording:
  114.             event_time = time.time() - self.start_time
  115.             self.recorded_events.append(('click', x, y, button.name, pressed, event_time))
  116.  
  117.     def on_move(self, x, y):
  118.         if self.recording:
  119.             event_time = time.time() - self.start_time
  120.             self.recorded_events.append(('move', x, y, event_time))
  121.  
  122.     def on_press(self, key):
  123.         if self.recording:
  124.             try:
  125.                 char = key.char
  126.             except AttributeError:
  127.                 char = key.name
  128.             event_time = time.time() - self.start_time
  129.             self.recorded_events.append(('press', char, event_time))
  130.  
  131.     def start_playback_from_hotkey(self):
  132.         if self.playback_button['state'] == tk.NORMAL:
  133.             self.start_playback()
  134.  
  135.     def start_playback(self):
  136.         if not self.playback_thread or not self.playback_thread.is_alive():
  137.             repeat_count = int(self.repeat_count_spinbox.get())
  138.             playback_speed = self.playback_speed_scale.get()
  139.             self.playback_thread = threading.Thread(target=self.playback_events, args=(repeat_count, playback_speed))
  140.             self.playback_thread.start()
  141.  
  142.     def playback_events(self, repeat_count, playback_speed):
  143.         # Logic for playing back the events
  144.         try:
  145.             for i in range(repeat_count):
  146.                 if self.playback_stop_requested:
  147.                     break
  148.                 self.loop_counter = i + 1
  149.                 self.root.after(0, self.update_loop_counter_label)
  150.                 last_event_time = 0
  151.                 for event in self.recorded_events:
  152.                     if self.playback_stop_requested:
  153.                         break
  154.                     event_type = event[0]
  155.                     event_time = event[-1]  # Event time is always the last element
  156.                     time.sleep(max(0, (event_time - last_event_time) / playback_speed))
  157.                     last_event_time = event_time
  158.                     if event_type == 'click':
  159.                         _, x, y, button_name, pressed, _ = event
  160.                         button = getattr(mouse.Button, button_name) if button_name else None
  161.                         mouse_controller = mouse.Controller()
  162.                         mouse_controller.position = (x, y)
  163.                         if pressed:
  164.                             mouse_controller.press(button)
  165.                         else:
  166.                             mouse_controller.release(button)
  167.                     elif event_type == 'move':
  168.                         _, x, y, _ = event
  169.                         mouse_controller = mouse.Controller()
  170.                         mouse_controller.position = (x, y)
  171.                     elif event_type == 'press':
  172.                         _, char, _ = event
  173.                         keyboard_controller = keyboard.Controller()
  174.                         keyboard_controller.press(char)
  175.             self.playback_stop_requested = False
  176.         except Exception as e:
  177.             messagebox.showerror("Playback Error", str(e))
  178.  
  179.     def save_events(self):
  180.         recording_name = simpledialog.askstring("Save Recording", "Enter a name for the recording:")
  181.         if recording_name:
  182.             recording_dir = os.path.join(self.recordings_dir, recording_name.replace(' ', '_'))
  183.             os.makedirs(recording_dir, exist_ok=True)
  184.             filepath = os.path.join(recording_dir, 'events')
  185.             with shelve.open(filepath) as shelf:
  186.                 shelf['events'] = self.recorded_events
  187.             messagebox.showinfo("Success", "Events saved successfully.")
  188.  
  189.     def load_events(self):
  190.         recording_name = self.choose_recording()
  191.         if recording_name:
  192.             filepath = os.path.join(self.recordings_dir, recording_name, 'events')
  193.             with shelve.open(filepath) as shelf:
  194.                 self.recorded_events = shelf['events']
  195.             self.update_event_listbox()
  196.             # Enable playback button if events were loaded
  197.             self.playback_button.config(state=tk.NORMAL)
  198.             messagebox.showinfo("Success", "Events loaded successfully.")
  199.  
  200.     def choose_recording(self):
  201.         recordings = [d for d in os.listdir(self.recordings_dir) if os.path.isdir(os.path.join(self.recordings_dir, d))]
  202.         if not recordings:
  203.             messagebox.showinfo("Load Recording", "No recordings found.")
  204.             return None
  205.         recording_name = simpledialog.askstring("Load Recording", "Enter the recording name:")
  206.         if recording_name in recordings:
  207.             return recording_name
  208.         else:
  209.             messagebox.showerror("Error", "Recording not found.")
  210.             return None
  211.  
  212.     def update_event_listbox(self):
  213.         self.event_listbox.delete(0, tk.END)
  214.         for event in self.recorded_events:
  215.             event_type, *data, event_time = event
  216.             if event_type == 'press':
  217.                 key = data[0]
  218.                 event_str = f"{event_type}: {key}"
  219.             else:
  220.                 x, y = data
  221.                 event_str = f"{event_type} at ({x}, {y})"
  222.             self.event_listbox.insert(tk.END, event_str)
  223.  
  224.     def update_loop_counter_label(self):
  225.         self.loop_counter_label.config(text=f"Loop Count: {self.loop_counter}")
  226.  
  227.     def configure_playback(self):
  228.         config_window = tk.Toplevel(self.root)
  229.         config_window.title("Playback Configuration")
  230.  
  231.         # Create a listbox to list all recordings
  232.         recordings_listbox = Listbox(config_window, selectmode=tk.EXTENDED)
  233.         recordings_listbox.pack()
  234.  
  235.         # Populate the listbox with available recordings
  236.         for recording in os.listdir(self.recordings_dir):
  237.             recordings_listbox.insert(tk.END, recording)
  238.  
  239.         # Add buttons to add recordings to the playback queue
  240.         tk.Button(config_window, text="Add to Playback Queue",
  241.                   command=lambda: self.add_to_playback_queue(recordings_listbox)).pack()
  242.  
  243.         # Add buttons to remove recordings from the playback queue
  244.         tk.Button(config_window, text="Remove from Playback Queue",
  245.                   command=lambda: self.remove_from_playback_queue(recordings_listbox)).pack()
  246.  
  247.         # Add listbox to show current playback queue
  248.         self.playback_queue_listbox = Listbox(config_window)
  249.         self.playback_queue_listbox.pack()
  250.  
  251.         # Add playback controls for the queue
  252.         tk.Button(config_window, text="Play Queue",
  253.                   command=self.playback_queue).pack()
  254.  
  255.     def add_to_playback_queue(self, recordings_listbox):
  256.         selections = recordings_listbox.curselection()
  257.         for i in selections:
  258.             self.playback_queue_listbox.insert(tk.END, recordings_listbox.get(i))
  259.  
  260.     def remove_from_playback_queue(self, recordings_listbox):
  261.         selections = self.playback_queue_listbox.curselection()
  262.         # Must delete from the end to avoid index shifting issues
  263.         for i in reversed(selections):
  264.             self.playback_queue_listbox.delete(i)
  265.  
  266.     def playback_queue(self):
  267.         # Logic to playback the queue
  268.         queue = list(self.playback_queue_listbox.get(0, tk.END))
  269.         for recording_name in queue:
  270.             filepath = os.path.join(self.recordings_dir, recording_name, 'events')
  271.             with shelve.open(filepath) as shelf:
  272.                 self.recorded_events = shelf['events']
  273.             # Playback each recording
  274.             self.start_playback()
  275.  
  276. if __name__ == "__main__":
  277.     root = tk.Tk()
  278.     app = MouseRecorderGUI(root)
  279.     root.mainloop()
  280.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement