Sundpood v1.3

- Using pynput instead keyboard module (better working)
- Add settings of overlay control
This commit is contained in:
Ninnjah 2020-10-28 00:40:07 +03:00 committed by GitHub
parent a72c4d88a1
commit 3c30a81585
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

247
main.py
View file

@ -2,15 +2,16 @@ import os
import sys
import json
import threading
import keyboard
from pynput.keyboard import Listener
import soundfile as sf
import sounddevice as sd
from pynput.keyboard import Listener
from PyQt5 import QtWidgets, QtGui, QtCore
import ui_preferences
import ui_sundpood
import ui_overlay
import keys
###! UI !###
class OverlayUi(QtWidgets.QMainWindow, ui_overlay.Ui_MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
@ -21,6 +22,11 @@ class OverlayUi(QtWidgets.QMainWindow, ui_overlay.Ui_MainWindow):
self.hide()
win.show()
class PreferencesUi(QtWidgets.QMainWindow, ui_preferences.Ui_MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
class MainUi(QtWidgets.QMainWindow, ui_sundpood.Ui_MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
@ -28,9 +34,13 @@ class MainUi(QtWidgets.QMainWindow, ui_sundpood.Ui_MainWindow):
def keyPressEvent(self, e):
if e.key() == QtCore.Qt.Key_F1:
pref.close()
self.hide()
over.show()
def closeEvent(self, event):
pref.close()
###! JSON !###
def jsonread(file): ## Чтение JSON
@ -44,15 +54,29 @@ def jsonwrite(file, data): ## Запись JSON
###! FUNCTIONS !###
def found_device(list_): # Поиск микшера VoiceMeeter
def find_device(list_): # Поиск микшера VoiceMeeter
msg = QtWidgets.QMessageBox()
msg.setIcon(QtWidgets.QMessageBox.Critical)
msg.setText("You don't install VoiceMeeter")
msg.setInformativeText('install VoiceMetter from "redist" folder or download it from \nvb-audio.com/Voicemeeter')
msg.setWindowTitle('Error')
index = 0
device = 'VoiceMeeter Input'
found = False
for i in list_:
if 'VoiceMeeter Input' in i['name']:
break
if device not in i['name']:
index += 1
elif device in i['name']:
found = True
break
if found == False:
msg.exec_()
exit()
return index
def sound_get(mode): # Сбор файлов
def sound_get(): # Сбор файлов
def check_format(name, format_): # Проверка слова до точки с конца строки
suf = ''
while name[-1] != '.':
@ -71,14 +95,14 @@ def sound_get(mode): # Сбор файлов
return False
def sound_convert(path, name, format_): # Конвертация из форматов 'mp3' 'm4a' в format_
if os.path.exists('ffmpeg.exe'):
old_name = name
if check_format(name, ['mp3', 'm4a']):
while name[-1] != '.':
name = name[:-1]
name += format_
os.system(f'''ffmpeg.exe -i "{os.path.join(path, old_name)}"
"{os.path.join(path, name)}"''')
os.system(f'ffmpeg.exe -i "{os.path.join(path, old_name)}" "{os.path.join(path, name)}"')
os.remove(f'{os.path.join(path, old_name)}')
return name
@ -88,28 +112,43 @@ def sound_get(mode): # Сбор файлов
msg.setInformativeText('download sound in .wav / .mp3 / .m4a format')
msg.setWindowTitle('Error')
if os.path.exists('settings.json') and mode == False:
sounds_list = jsonread('settings.json')
ffmsg = QtWidgets.QMessageBox()
ffmsg.setIcon(QtWidgets.QMessageBox.Warning)
ffmsg.setText("You don't have ffmpeg.exe in the program root folder")
ffmsg.setInformativeText('download ffmpeg from ffmpeg.org for converting sound files')
ffmsg.setWindowTitle('Error')
elif not os.path.exists('settings.json') or mode == True:
if os.path.exists('sound'):
if len(os.listdir('sound')) == 0:
msg.exec_()
exit()
menu = []
sounds_list = ['sound\\']
for i in os.listdir('sound'):
if os.path.exists('ffmpeg.exe') or not ffmsg:
if os.path.isfile(os.path.join('sound', i)):
i = sound_convert('sound', i, 'wav')
name = sound_convert('sound', i, 'wav')
if name == None:
sounds_list.append(i)
else:
sounds_list.append(name)
else:
sounds_list_cat = [os.path.join('sound', i)]
for x in os.listdir(os.path.join('sound', i)):
if os.path.isfile(os.path.join('sound', i, x)):
x = sound_convert(os.path.join('sound', i), x, 'wav')
name = sound_convert(os.path.join('sound', i), x, 'wav')
if name == None:
sounds_list_cat.append(x)
else:
sounds_list_cat.append(name)
menu.append(sounds_list_cat)
else:
print('else')
try:
ffmsg.exec_()
ffmsg = False
except AttributeError:
pass
menu.append(sounds_list)
sounds = []
@ -120,42 +159,65 @@ def sound_get(mode): # Сбор файлов
if os.path.exists('settings.json'):
hotkeys = jsonread('settings.json')['hotkeys']
sounds_list = {'sound':sounds,
KEYS_CMD = jsonread('settings.json')['KEYS_CMD']
sounds_list = { 'sounds':sounds,
'hotkeys':hotkeys,
'menu':menu}
'menu':menu,
'KEYS_CMD':KEYS_CMD}
else:
sounds_list = {'sounds':sounds,
sounds_list = { 'sounds':sounds,
'hotkeys':{'Push button':''},
'menu':menu}
'menu':menu,
'KEYS_CMD':{
'select_move_up' :' ',# вверх
'select_move_down' :' ',# вниз
'select_move_left' :' ',# влево
'select_move_right' :' ',# вправо
'play_sound' :' ',# Играть
'stop_sound' :' ',# Остановить
}}
for i in COMBOS:
i.addItems(sounds)
jsonwrite('settings.json', sounds_list)
else:
sounds_list = { 'sounds':'',
'hotkeys':{'Push button':''},
'menu':'',
'KEYS_CMD':{
'select_move_up' :' ',# вверх
'select_move_down' :' ',# вниз
'select_move_left' :' ',# влево
'select_move_right' :' ',# вправо
'play_sound' :' ',# Играть
'stop_sound' :' ',# Остановить
}}
jsonwrite('settings.json', sounds_list)
os.mkdir('sound')
msg.exec_()
exit()
return sounds_list
def save(): # Сохранение списка хоткеев
hotkeys = {}
sounds = sound_get(False)
sounds = jsonread('settings.json')['sounds']
for i in range(len(COMBOS)):
hotkeys.setdefault(HOTKEYS[i].text(), COMBOS[i].currentText())
sounds_list = {'sounds':sounds, 'hotkeys':hotkeys, 'menu':menu}
KEYS_JSON = {}
for i in KEYS_CMD.keys():
KEYS_JSON.setdefault(COMMAND_DICT[i], KEYS_CMD[i])
sounds_list = {'sounds':sounds, 'hotkeys':hotkeys, 'menu':menu, 'KEYS_CMD':KEYS_JSON}
jsonwrite('settings.json', sounds_list)
sounds = None
KEYS_JSON = None
hotkeys = None
sounds = None
def play_sound(index): # Проигрываение звука
print(index)
try:
filename = COMBOS[index].currentText()
try:
data, fs = sf.read(os.path.join('sound', filename), dtype='float32')
sd.play(data, fs)
keyboard.wait(sd.play())
sd.wait()
except:
pass
except:
@ -163,19 +225,20 @@ def play_sound(index): # Проигрываение зву
try:
data, fs = sf.read(os.path.join(menu[select[0]][0], filename), dtype='float32')
sd.play(data, fs)
keyboard.wait(sd.play())
sd.wait()
except:
pass
def hotkey_remap(btn): # Переназначение хоткеев
def check(key):
button = HOTKEYS[btn]
key = str(key)
key = str(key).replace("'",'')
if key not in keys.forbidden:
print(key)
COMMANDS[COMMANDS.index(button.text())] = key.replace("'",'')
button.setText(key.replace("'",''))
HOTKEYS_CMD[HOTKEYS_CMD.index(button.text())] = keys.dict_[key]
button.setText(keys.dict_[key])
elif key == 'Key.backspace':
HOTKEYS_CMD[HOTKEYS_CMD.index(button.text())] = ' '
button.setText(' ')
for i in HOTKEYS:
if i != HOTKEYS[btn]:
i.setEnabled(True)
@ -189,10 +252,36 @@ def hotkey_remap(btn): # Переназначение хо
on_release=check)
hotkey_remap_Listener.start()
def pref_remap(btn, func_):
def check(key):
key = str(key).replace("'",'')
if key not in keys.forbidden:
func = find_key(COMMAND_DICT, func_)
KEYS_CMD.update({func : key})
btn.setText(keys.dict_[key])
elif key == 'Key.backspace':
func = find_key(COMMAND_DICT, func_)
KEYS_CMD.update({func : ' '})
btn.setText(' ')
for i in PREF_BTN:
i.setEnabled(True)
return False
for i in PREF_BTN:
i.setEnabled(False)
hotkey_remap_Listener = Listener(
on_release=check)
hotkey_remap_Listener.start()
save()
def find_key(dict, val):
return next(key for key, value in dict.items() if value == val)
###! CONTROL !###
def key_check(key): # Хоткеи
def select_move(mode):
def select_move(mode):
select[1] += mode[1]
select[0] += mode[0]
if select[0] > len(menu)-1 or select[0] < -len(menu)+1:
@ -204,22 +293,29 @@ def key_check(key): # Хоткеи
over.label.setText(menu[select[0]][select[1]])
win.select_label.setText(menu[select[0]][select[1]])
key = str(key)
if key.replace("'",'') in COMMANDS:
play_sound(COMMANDS.index(key.replace("'",'')))
keyboard.add_hotkey(72, select_move, args=[[0, -1]])
keyboard.add_hotkey(80, select_move, args=[[0, 1]])
keyboard.add_hotkey(77, select_move, args=[[1, 0]])
keyboard.add_hotkey(75, select_move, args=[[-1, 0]])
keyboard.add_hotkey(76, play_sound, args=[''])
keyboard.add_hotkey(73, sd.stop)
def key_check(key): # Хоткеи
key_n = ''
key = str(key).replace("'",'')
try:
key_n = keys.dict_[key]
except KeyError:
pass
print(f'{key_n} in {HOTKEYS_CMD} -- {key_n in HOTKEYS_CMD}')
if key_n in HOTKEYS_CMD:
play_sound(HOTKEYS_CMD.index(key_n))
elif key in KEYS_CMD.values():
find_key(KEYS_CMD, key)()
def main(): # Интерфейс
win.show()
key_check_Listener = Listener(
on_release=key_check)
key_check_Listener.start()
win.save_button.clicked.connect(save)
win.actionpreferences.triggered.connect(pref.show)
win.hotkey_1.clicked.connect(lambda: hotkey_remap(0))
win.hotkey_2.clicked.connect(lambda: hotkey_remap(1))
win.hotkey_3.clicked.connect(lambda: hotkey_remap(2))
@ -233,16 +329,25 @@ def main(): # Интерфейс
win.hotkey_11.clicked.connect(lambda: hotkey_remap(10))
win.hotkey_12.clicked.connect(lambda: hotkey_remap(11))
pref.play_sound.clicked.connect(
lambda: pref_remap(pref.play_sound, 'play_sound'))
pref.stop_sound.clicked.connect(
lambda: pref_remap(pref.stop_sound, 'stop_sound'))
pref.select_move_up.clicked.connect(
lambda: pref_remap(pref.select_move_up, 'select_move_up'))
pref.select_move_down.clicked.connect(
lambda: pref_remap(pref.select_move_down, 'select_move_down'))
pref.select_move_left.clicked.connect(
lambda: pref_remap(pref.select_move_left, 'select_move_left'))
pref.select_move_right.clicked.connect(
lambda: pref_remap(pref.select_move_right, 'select_move_right'))
if __name__ == '__main__':
### Поиск устроства ввода ###
list_ = list(sd.query_devices())
index = found_device(list_)
sd.default.device = list_[index]['name']
### Создание окна ###
app = QtWidgets.QApplication([])
over = OverlayUi()
pref = PreferencesUi()
win = MainUi()
COMBOS = [
win.combo0,
@ -270,22 +375,53 @@ if __name__ == '__main__':
win.hotkey_10,
win.hotkey_11,
win.hotkey_12,]
PREF_BTN = [
pref.select_move_up,
pref.select_move_down,
pref.select_move_left,
pref.select_move_right,
pref.play_sound,
pref.stop_sound,]
sound_get_dict = sound_get(True)
### Поиск устроства ввода ###
list_ = list(sd.query_devices())
index = find_device(list_)
sd.default.device = list_[index]['name']
sound_get()
### Глобальные переменные ###
sounds = sound_get_dict['hotkeys']
sound_get_dict = jsonread('settings.json')
hotkeys = sound_get_dict['hotkeys']
menu = sound_get_dict['menu']
select = [0, 0]
COMMAND_DICT = {
lambda: select_move([0, -1]):'select_move_up', # вверх
lambda: select_move([0, 1]) :'select_move_down', # вниз
lambda: select_move([-1, 0]):'select_move_left', # влево
lambda: select_move([1, 0]) :'select_move_right', # вправо
lambda: play_sound('') :'play_sound', # Играть
lambda: sd.stop() :'stop_sound', # Остановить
}
KEYS_CMD = COMMAND_DICT.copy()
KEYS_JSON = sound_get_dict['KEYS_CMD']
for i in KEYS_CMD.keys():
KEYS_CMD.update({i:KEYS_JSON[COMMAND_DICT[i]]})
KEYS_JSON = None
combo = 0
for i in sounds.items():
for i in KEYS_CMD.values():
PREF_BTN[combo].setText(keys.dict_[i])
combo += 1
combo = 0
for i in hotkeys.items():
index = COMBOS[combo].findText(i[1])
COMBOS[combo].setCurrentIndex(index)
HOTKEYS[combo].setText(i[0])
combo += 1
combo = None
COMMANDS = [
HOTKEYS_CMD = [
HOTKEYS[0].text(),
HOTKEYS[1].text(),
HOTKEYS[2].text(),
@ -299,8 +435,5 @@ if __name__ == '__main__':
HOTKEYS[10].text(),
HOTKEYS[11].text(),]
key_check_Listener = Listener(
on_release=key_check)
main()
sys.exit(app.exec())