Advertisement
egor230

volce game contol for linux.py

Apr 20th, 2025
130
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 18.07 KB | Source Code | 0 0
  1. from libs_voice import *
  2. from tkinter import *
  3. from tkinter.ttk import Combobox  # импортируем только то что надо
  4. from tkinter import messagebox
  5. from pynput.keyboard import Key, Controller
  6. from pynput import *
  7. import keyboard as keybord_from # Управление мышью
  8. def on_release(key):
  9.     if key == keyboard.Key.shift_l:
  10.         keyb = Controller()
  11.         keyb.press(Key.shift)  # отпустить клавишу
  12.         return False
  13.     if key == keyboard.Key.ctrl_r:
  14.         keyb = Controller()
  15.         keyb.press(Key.ctrl_l)  # отпустить клавишу
  16.         return False
  17.     if key != keyboard.Key.shift_r and key != keyboard.Key.ctrl and key != keyboard.Key.up \
  18.             and key != keyboard.Key.down and key != keyboard.Key.left and key != keyboard.Key.right:
  19.         keyb = Controller()
  20.         keyb.release(Key.shift)
  21.         keyb.release(Key.ctrl_l)
  22.         return False
  23.  
  24. KEYS = {" ": 0x0,"LBUTTON": 'mouse left', "RBUTTON": 'mouse right', "WHEEL_MOUSE_BUTTON": "mouse middle",
  25.         "WHEEL_MOUSE_UP" : "WHEEL_MOUSE_UP", "MBUTTON": 0x04, "SCROLL_UP": "scroll_up",
  26.         "SCROLL_DOWN" : "scroll_down", "XBUTTON1": 0x05, "XBUTTON2": 0x06, "BACKSPACE": "BackSpace",
  27.         "TAB": "Tab", "CLEAR": 0x0C, "RETURN": "Return", "KP_Enter" : "KP_Enter",
  28.         "SHIFT": 0x10, "CONTROL": 0x11, "MENU": 0x12, "PAUSE": 0x13, "CAPITAL": 0x14,
  29.         "KANA": 0x15, "JUNJA": 0x17, "FINAL": 0x18, "KANJI": 0x19, "ESCAPE": 0x1B,
  30.         "CONVERT": 0x1C, "NONCONVERT": 0x1D, "ACCEPT": 0x1E, "MODECHANGE": 0x1F, "SPACE": "space",
  31.         "PRIOR": 0x21, "NEXT": 0x22, "END": "0x23", "HOME": "Home", "LEFT": 0x25, "UP": 0x26,
  32.         "RIGHT": 0x27, "DOWN": 0x28, "SELECT": 0x29, "PRINT": 0x2A, "EXECUTE": 0x2B, "SNAPSHOT": 0x2C,
  33.         "INSERT": 0x2D, "DELETE": "Delete", "HELP": 0x2F,  "LWIN": "Super_L", "RWIN": "Super_R",
  34.  
  35.         "KEY0": 0, "KEY1": 1, "KEY2": 2, "KEY3": 3, "KEY4": 4, "KEY5": 5, "KEY6": 6,
  36.         "KEY7": 7, "KEY8": 8, "KEY9": 9, "A": "A", "B": "B", "C": "C", "D": "D", "E": "E", "F": "F",
  37.         "G": "G", "H": "H", "I": "I", "J": "J", "K": "K", "L": "L", "M": "M", "N": "N", "O": "O",
  38.         "P": "P", "Q": "Q", "R": "R", "S": "S", "T": "T", "U": "U", "V": "V", "W": "W", "X": "X", "Y": "Y",
  39.         "Z": "Z",
  40.  
  41.         "APPS": 0x5D, "SLEEP": 0x5F, "NUMPAD0": 0x60, "NUMPAD1": 79,
  42.         "NUMPAD2": 80, "NUMPAD3": 81, "NUMPAD4": 82, "NUMPAD5": 83, "NUMPAD6": 84, "NUMPAD7": 85,
  43.         "NUMPAD8": 86, "NUMPAD9": 87, "MULTIPLY": 0x6A, "ADD": 78, "SEPARATOR": 0x6C, "SUBTRACT": 0x6D,
  44.         "DECIMAL": 0x6E, "DIVIDE": 0x6F, "F1": "F1", "F2": "F2", "F3": "F3", "F4": "F4", "F5": "F5",
  45.         "F6": "F6", "F7": "F7", "F8": "F8", "F9": "F9", "F10": "F10", "F11": "F11", "F12": "F12",
  46.  
  47.         "F13": 0x7C, "F14": 0x7D, "F15": 0x7E, "F16": 0x7F, "F17": 0x80, "F18": 0x81, "F19": 0x82, "F20": 0x83, "F21": 0x84,
  48.         "F22": 0x85, "F23": 0x86, "F24": 0x87,"NUMLOCK": "Num_Lock", "SCROLL": "Scroll_Lock",
  49.          "OEM_FJ_JISHO": 0x92, "OEM_FJ_MASSHOU": 0x93,
  50.         "OEM_FJ_TOUROKU": 0x94, "OEM_FJ_LOYA": 0x95, "OEM_FJ_ROYA": 0x96, "LSHIFT": "Shift_L", "RSHIFT": "Shift_R", "LCONTROL": "ISO_Next_Group",
  51.         "RCONTROL": "Control_R",  "LMENU": 0xA4, "RMENU": 0xA5, "BROWSER_BACK": 0xA6,
  52.         "BROWSER_FORWARD": 0xA7, "BROWSER_REFRESH": 0xA8, "BROWSER_STOP": 0xA9, "BROWSER_SEARCH": 0xAA, "BROWSER_FAVORITES": 0xAB, "BROWSER_HOME": 0xAC, "VOLUME_MUTE": 0xAD, "VOLUME_DOWN": 0xAE,
  53.         "VOLUME_UP": 0xAF, "MEDIA_NEXT_TRACK": 0xB0, "MEDIA_PREV_TRACK": 0xB1, "MEDIA_STOP": 0xB2, "MEDIA_PLAY_PAUSE": 0xB3, "LAUNCH_MAIL": 0xB4, "LAUNCH_MEDIA_SELECT": 0xB5, "LAUNCH_APP1": 0xB6,
  54.         "LAUNCH_APP2": 0xB7, "OEM_1": 0xBA, "OEM_PLUS": 0xBB, "OEM_COMMA": 0xBC, "OEM_MINUS": 0xBD, "OEM_PERIOD": 0xBE, " OEM_2": 0xBF, "OEM_3": 0xC0, "ABNT_C1": 0xC1, "ABNT_C2": 0xC2, "OEM_4": 0xDB,
  55.         "OEM_5": 0xDC, "OEM_6": 0xDD, "OEM_7": 0xDE, "OEM_8": 0xDF, "OEM_AX": 0xE1,
  56.         "OEM_102": 0xE2, "ICO_HELP": 0xE3, "PROCESSKEY": 0xE5, "ICO_CLEAR": 0xE6, "PACKET": 0xE7, "OEM_RESET": 0xE9, "OEM_JUMP": 0xEA, "OEM_PA1": 0xEB, "OEM_PA2": 0xEC, "OEM_PA3": 0xED,
  57.         "OEM_WSCTRL": 0xEE, "OEM_CUSEL": 0xEF, "OEM_ATTN": 0xF0, "OEM_FINISH": 0xF1, "OEM_COPY": 0xF2, "OEM_AUTO": 0xF3, "OEM_ENLW": 0xF4, "OEM_BACKTAB": 0xF5, "ATTN": 0xF6, "CRSEL": 0xF7, "EXSEL": 0xF8, " EREOF": 0xF9, "PLAY": 0xFA, "ZOOM": 0xFB, "PA1": 0xFD, " OEM_CLEAR": 0xFE
  58.         }
  59.  
  60. def check(driver):
  61.   url = driver.current_url
  62.   driver.implicitly_wait(3)
  63.   try:
  64.     return 0
  65.   except Exception as ex:
  66.     check(driver)
  67. class work_key:
  68.   def __init__(self):
  69.     self.keys_list = ["1", "2", "3", "4",'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'a', 's', 'd', 'f', 'g',
  70.                       'h', 'j', 'k', 'l', 'z', 'x', 'c', 'v', 'b', 'n', 'm', 'BackSpace', 'Tab', 'Return', 'KP_Enter', 'Escape', 'Delete', 'Home', 'End', 'Page_Up',
  71.    'Page_Down', 'F1', 'Up', 'Down', 'Left', 'Right', 'Control_L', 'ISO_Next_Group', 'Control_R', 'Shift_L', 'Shift_R', 'Alt_L', 'Alt_R', 'Super_L',
  72.     'Super_R', 'Caps_Lock', 'Num_Lock', 'Scroll_Lock', 'space', 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12']
  73.  
  74.   def mouse_wheel_up(self):  #
  75.     mouse_wheel = '''#!/bin/bash
  76.        xdotool click  {0}    '''.format(4)
  77.     subprocess.call(['bash', '-c', mouse_wheel])
  78.   def mouse_wheel_donw(self):  #
  79.     mouse_wheel = '''#!/bin/bash
  80.        xdotool click  {0}    '''.format(5)
  81.     subprocess.call(['bash', '-c', mouse_wheel])
  82.   def mouse_right_donw(self):  #
  83.       mouse_wheel = '''#!/bin/bash
  84.          xdotool click  {0}    '''.format(3)
  85.       subprocess.call(['bash', '-c', mouse_wheel])
  86.   def mouse_middle_donw(self):  #
  87.       mouse_wheel = '''#!/bin/bash
  88.          xdotool click  {0}    '''.format(2)
  89.       subprocess.call(['bash', '-c', mouse_wheel])
  90.   def key_press(self, key, number_key = 0):# Нажать.
  91.     if key in self.keys_list:
  92.        key=key
  93.     if key.upper() in ['F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12']:
  94.       key=key.upper() #    print(key)
  95.     press = '''#!/bin/bash
  96.      xte \"keydown {0}\"
  97.      sleep 0.3
  98.      xte \"keyup {0}\"'''.format(key)
  99.     subprocess.call(['bash', '-c', press])
  100.     return 0
  101. def prease_on_key(driver, d): #
  102.  pres12= work_key()
  103.  timestamp = time.time()
  104.  while 1:
  105.   try:
  106.    text = driver.find_element(By.ID, "speech-text").text
  107.    text = str(text).lower()
  108.    if len(text) != 0 and text != None:       #     print(text)
  109.     for key in d:
  110.      word1=str(d[key])
  111.      words=word1.rsplit(",")
  112.      x=[ i.lstrip() for i in words]
  113.      for word1 in x:
  114.       word= str(word1).lower()
  115.       if word == text:
  116.        key1=key.upper()
  117.        key2=str(KEYS[key1]).lower()
  118.        driver.find_element("id", "mic").click()
  119.        pres12.key_press(key2)
  120.        time.sleep(0.5)
  121.        # driver.find_element("class","p_edit dir_LTR").clear()  # удалить старый текст.
  122.        driver.find_element("id", "mic").click()
  123.    if time.time() - timestamp > 10:     #   print(time.time())
  124.     driver.find_element("id", "mic").click()
  125.     time.sleep(0.35)
  126.     driver.find_element("id", "mic").click()  #
  127.     timestamp = time.time()
  128.   except Exception as ex:
  129.      # print(ex)
  130.      pass
  131.  
  132. def web():
  133.   option = get_option()  # Включить настройки.# option.add_argument("--headless")  # Включение headless-режима
  134.   try:
  135.     driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=option)
  136.     driver.set_window_position(600, 650)
  137.     driver.set_window_size(624, 368) # optiol
  138.     driver.get("https://www.speechtexter.com")# открыть сайт
  139.     check(driver)
  140.     driver.minimize_window()
  141.     driver.find_element("id", "mic").click()# включить запись голоса
  142.     return driver
  143.  
  144.   except Exception as ex:     #print(ex)
  145.      pass
  146.   finally:
  147.      pass
  148. # добавление нового элемента
  149. list_profiles = ["default"]  # список профилей.
  150.  
  151. def start_voice():
  152.  try:
  153.   driver = web()# запуск браузер.
  154.   d = {}
  155.   for i in range(len(arg)):
  156.    value = (str(arg[i].get()))
  157.    key = str(values[i].get())
  158.    d[key] = value
  159.    try:
  160.      if key == "":
  161.        messagebox.showerror("Erorr", "key emrty")
  162.        dict_save.kill_chromedrive_id()  # Убить текущей процесс.
  163.        break
  164.        return
  165.      if value == "":
  166.        messagebox.showerror("Erorr", "Value emrty")
  167.        dict_save.kill_chromedrive_id()  # Убить текущей процесс.
  168.        break
  169.        return
  170.    except Exception as ex:
  171.       pass
  172.    app_thread = threading.Thread(target=prease_on_key, args=(driver, d,))
  173.    app_thread.start()
  174.  except Exception as ex:
  175.      pass
  176.  
  177. class save_dict:
  178.   def __init__(self):
  179.     self.d = {}
  180.     self.jnson = {}
  181.   def add_dict(self, second_dict):
  182.     self.d= self.d | second_dict
  183.   def return_dict(self):
  184.     return self.d
  185.  
  186.   def save_jnson(self, jn):
  187.    self.jnson= jn
  188.  
  189.   def return_jnson(self):
  190.     return self.jnson
  191.  
  192. def save_keys_and_values(event=0):
  193.  d,d1={},{}
  194.  d=dict_save.return_jnson()# старый словарь.
  195.  d["last_pfofile"]=str(profile_current.get())
  196.  d["start_startup"]=start_startup.get()
  197.  d1=d["profiles"]
  198.  d=d1[str(profile_current.get())]
  199.  d.clear()
  200.  for i in range(len(arg)):
  201.         key = str(arg[i].get())
  202.         value = str(values[i].get())
  203.         d[key]=value# обновления словаря.
  204.  d1[str(profile_current.get())]=d
  205. def on_close():
  206.     new_data={"last_pfofile" : profile_current.get(),
  207.     "profiles" : dict_save.return_dict()} # новые значения настроек.
  208.     old_data= dict_save.return_jnson()# старые значения настроек.
  209.     if new_data != old_data:
  210.      if messagebox.askokcancel("Quit", "Do you want to save the changes?"):
  211.        json_string = json.dumps(new_data, ensure_ascii=False, indent=2)
  212.        with open("settings volce game contol for linux.json", "w", encoding="cp1251") as w:
  213.         w.write(json_string)# сохранить изменения в файле настроек.
  214.     root.destroy()
  215.  
  216. # удаления записи и значения.
  217. def remove_box_and_entry(ent_arr, box_arr):
  218.  if len(values)>0:
  219.     r = len(arg)
  220.     values[r-1].set("")
  221.     arg[r-1].set("")
  222.     ent_arr[r-1].destroy()
  223.     box_arr[r-1].destroy()
  224.     ent_arr.pop()
  225.     box_arr.pop()
  226.     values.pop()
  227.     arg.pop()
  228.     return ent_arr, box_arr
  229.  else:
  230.     return ent_arr, box_arr
  231.  
  232. class iter_counter:
  233.   def __init__(self):
  234.      self._value = -1
  235.      self.box_arr = []
  236.      self.ent_arr = []
  237.   def add_new_command(self, scrollable_frame, entry_value=0, box_value=0):
  238.     self._value += 1
  239.     value= self._value  # print(value)
  240.     a = list(KEYS.keys()), arg.append(StringVar()), values.append(StringVar())
  241.     entry = Entry(scrollable_frame, width=17, textvariable=arg[value])  # текстовое поле и кнопка для добавления в список
  242.     entry.grid(column=0, row=value+1, padx=(3, 0), pady=8)
  243.     box = Combobox(scrollable_frame, width=10, textvariable=values[value], values=a[0])
  244.     box.grid(column=1, row=value+1, padx=38, pady=0)  # поле со списком
  245.     key=str(profile_current.get())
  246.     if entry_value != 0 and box_value != 0:
  247.         arg[value].set(entry_value)
  248.         values[value].set(box_value)
  249.     else:
  250.         arg[value].set("")
  251.         values[value].set("")
  252.     return self.ent_arr.append(entry), self.box_arr.append(box),self._value,
  253.   def del_command(self):
  254.        value = self._value
  255.        ent_arr, box_arr= self.box_arr, self.ent_arr
  256.        ent_arr, box_arr=remove_box_and_entry(ent_arr, box_arr)
  257.  
  258.        self._value -= 1
  259.        return self._value, self.box_arr, self.ent_arr
  260.   def remove_all_command(self, scrollable_frame):
  261.        self._value=-1
  262.        ent_arr, box_arr, value = self.box_arr, self.ent_arr, self._value
  263.        for i in range(len(box_arr)):
  264.         ent_arr, box_arr = remove_box_and_entry(ent_arr, box_arr)
  265.        new.add_new_command(scrollable_frame)
  266.        return self._value, self.box_arr, self.ent_arr
  267.   def remove_all_command_without_adding(self):
  268.        value = self._value
  269.        ent_arr, box_arr= self.box_arr, self.ent_arr
  270.        for i in range(len(box_arr)):
  271.         ent_arr, box_arr = remove_box_and_entry(ent_arr, box_arr)
  272.        self._value=-1
  273.        return self._value, self.box_arr, self.ent_arr
  274.  
  275. def filling_fields(dict_save, last_pfofile):
  276.   d=dict_save.return_dict()# получить словарь со всеми значениями.  
  277.   for k, v in d.items():
  278.    if k not in list_profiles:
  279.      list_profiles.append(k)
  280.    if k== last_pfofile:
  281.     for k1, v1 in v.items():
  282.      v1=v[k1]
  283.      new.add_new_command(scrollable_frame,k1,v1)
  284.  
  285. def update(event):
  286.     d=dict_save.return_dict()
  287.     d=d[str(profile_current.get())]
  288.     new.remove_all_command_without_adding()
  289.     filling_fields(dict_save, profile_current.get())
  290. def c(event):
  291.  d=dict_save.return_dict()
  292.  d=d[str(profile_current.get())]
  293.  for i in range(len(arg) - 1):
  294.         key = str(arg[i].get())
  295.         value = str(values[i].get())
  296.         d[key]=value
  297.  d1=dict_save.return_dict()
  298.  
  299.  d1[str(profile_current.get())]=d
  300.  return 0
  301. def create_box():
  302.     box = Combobox(root, width=10, textvariable=profile_current, values=list_profiles, state='readonly')
  303.     box.grid(column=1, row=0, padx=3, pady=0)  # поле со списком.
  304.     box.bind('<Button-1>', c)  # при нажатии на выпадающий список.
  305.     box.bind('<<ComboboxSelected>>', update)# при изменения профиля.
  306.     return box
  307. def add1(root,window, new, scrollable_frame):
  308.     value= new_profile.get()
  309.     if value != '':
  310.      list_profiles.append(str(value))
  311.      box = Combobox(root, width=10, textvariable=profile_current, values=list_profiles, state='readonly')
  312.      box.bind('<<ComboboxSelected>>', update)
  313.      box.grid(column=1, row=0, padx=3, pady=0)  # поле со списком
  314.      add_button = Button(text="Добавить профиль", command= lambda:add_new_profile(root, box)).grid(column=2, row=0, padx=10, pady=6)
  315.      box.current(len(list_profiles)-1)
  316.  
  317.      window.destroy()
  318.      new_profile.set('')
  319.      new.remove_all_command(scrollable_frame)
  320.  
  321. def add_new_profile(root,box,new,scrollable_frame):
  322.     window = Toplevel(root)# основа
  323.     window.title("add new profile")  # заголовок
  324.     window.geometry("500x150+750+400")  # Первые 2 определяют ширину высоту. Пос 2 x и y координаты на экране.
  325.     window.configure(bg='DimGray')  # Цвет фона окна
  326.  
  327.     e=Entry(window, width=30, textvariable=new_profile) #строка ввода профиля.
  328.     e.grid(column=2, row=0, padx=50, pady=5)
  329.     e.focus_set()
  330.     Button(window, text="Добавить профиль", command= lambda:add1(root,window,new,scrollable_frame))\
  331.         .grid(column=2, row=1, padx=50, pady=30) # кнопка добавить профиль, откроется новое окно.
  332.  
  333. def start(new, scrollable_frame,box):
  334.   data ="settings volce game contol for linux.json"  # файл настроек.
  335.   if os.path.exists(data):  # есть ли этот файл.
  336.     with open(data, encoding='windows-1251') as json_file:
  337.       res= json.load(json_file)
  338.     start_startup.set(res["start_startup"])
  339.     dict_save.save_jnson(res)# соранить начальные настройки.
  340.     last_pfofile = res['last_pfofile'] # последний исполь профиль.
  341.     if not last_pfofile in list_profiles:
  342.      list_profiles.append(last_pfofile)
  343.     box =create_box() # Создания выпадающего списка.
  344.     box.current(len(list_profiles) - 1)
  345.     d=res['profiles']
  346.     dict_save.add_dict(d)
  347.     filling_fields(dict_save, last_pfofile)# запол полей
  348.   else:
  349.      new.add_new_command(scrollable_frame)
  350. def delayed_launch(start_startup):
  351.   if start_startup.get():  # Запуск при открытий.
  352.      start_voice()
  353. dict_save=save_dict()
  354. root = Tk()
  355. root.geometry("680x250+650+400")
  356. profile_current, new_profile=StringVar(),StringVar()
  357.  
  358. start_startup = BooleanVar()
  359. lb = Label(root, text="Голосовое управления в играх",width=28).grid(column=0, row=0)  # текстовое поле и кнопка для добавления в список
  360.  
  361. arg, values = [], []# списки для слов и значений.
  362.  
  363. container = Frame(root)
  364. canvas = Canvas(container,width=320, height=200)
  365. scrollbar = Scrollbar(container, orient="vertical", command=canvas.yview)
  366. scrollable_frame = Frame(canvas)
  367. scrollable_frame.bind( "<Configure>",
  368.     lambda e: canvas.configure( scrollregion=canvas.bbox("all")
  369.     ))
  370. canvas.create_window((0, 0), window=scrollable_frame, anchor="n")
  371. canvas.configure(yscrollcommand=scrollbar.set)
  372. container.grid()
  373. canvas.grid(sticky=N+S)
  374. scrollbar.grid(column=0, row=0,sticky=N+S+E)# полоса прокрутки.
  375.  
  376. box = create_box() # Создания выпадающего списка.
  377.  
  378. new=iter_counter()# объект класса.
  379.  
  380. add_button = Button(text="Добавить профиль", command= lambda:add_new_profile(root, box, new,scrollable_frame))\
  381.     .grid(column=2, row=0, padx=10, pady=6)
  382.  
  383. add_key_button = Button(text="Добавить команду", command= lambda:new.add_new_command(scrollable_frame))\
  384.     .grid(column=1, row=1, padx=1, pady=30,sticky=N)
  385.  
  386. del_key_button_1 = Button(text="Удалить команду", command= lambda:new.del_command())\
  387.     .grid(column=1, row=1,padx=1,pady=90,sticky=N)
  388.  
  389. go_button_2 = Button(text="  Старт  ", command= lambda:start_voice())\
  390.     .grid(column=2, row=1,padx=0,pady=20,sticky=SE)# Запуск управления.
  391. root.protocol("WM_DELETE_WINDOW", on_close)
  392.  
  393. box.grid(column=1, row=0, padx=3, pady=0)  # поле со списком
  394. start(new, scrollable_frame,box)# запуск всего.
  395. r1 = Checkbutton(text='Запускать при открытий',  variable=start_startup, command=lambda:save_keys_and_values())
  396.  
  397. r1.place(x=323, y=190)
  398. t2 = threading.Thread(target=delayed_launch, args=(start_startup,))
  399. t2.start()
  400. root.mainloop()
  401.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement