Advertisement
Thoughtcoder411

Autonomie

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