-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.py
More file actions
157 lines (133 loc) · 6.3 KB
/
Copy pathinstall.py
File metadata and controls
157 lines (133 loc) · 6.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import os
import sys
import subprocess
import platform
import shutil
def run_command(command, shell=True):
try:
subprocess.check_call(command, shell=shell)
return True
except subprocess.CalledProcessError:
return False
def bootstrap_venv():
print("Setting up virtual environment...")
venv_dir = "venv"
# Detect if we are on Windows or Linux/Mac
if os.name == "nt":
pip_path = os.path.join(venv_dir, "Scripts", "pip.exe")
python_path = os.path.join(venv_dir, "Scripts", "python.exe")
else:
pip_path = os.path.join(venv_dir, "bin", "pip")
python_path = os.path.join(venv_dir, "bin", "python")
# 1. Try standard venv creation
if not run_command(f"{sys.executable} -m venv {venv_dir}"):
print("Standard venv creation failed. Trying without pip...")
if not run_command(f"{sys.executable} -m venv {venv_dir} --without-pip"):
print("CRITICAL ERROR: Could not create virtual environment.")
return False
# 2. Check if pip exists. If not, try to ensure it.
if not os.path.exists(pip_path):
print("Pip missing from venv. Attempting to bootstrap with ensurepip...")
if not run_command(f"{python_path} -m ensurepip --default-pip"):
print("ensurepip failed. Attempting to download get-pip.py...")
import urllib.request
try:
urllib.request.urlretrieve("https://bootstrap.pypa.io/get-pip.py", "get-pip.py")
run_command(f"{python_path} get-pip.py")
os.remove("get-pip.py")
except Exception as e:
print(f"Failed to download/run get-pip.py: {e}")
return False
# 3. Final verification and requirements install (Lightweight Default)
print("Installing lightweight cloud requirements...")
run_command(f"{pip_path} install --upgrade pip")
return run_command(f"{pip_path} install -r requirements.txt")
def setup_linux():
print("Setting up for Linux...")
# System dependencies derived from codebase analysis:
# - python3-dev/devel: General headers
# - wl-clipboard: Clipboard support
# - libportaudio2 / portaudio: sounddevice
# - libasound2-dev: Sound hardware interface
# - libxcb-cursor0 / libxcb-xinerama0: PyQt6 dependencies
# - libxkbcommon-x11-0: PyQt6 dependencies
distro = ""
if os.path.exists("/etc/fedora-release"):
distro = "fedora"
elif os.path.exists("/etc/debian_version") or os.path.exists("/etc/lsb-release"):
distro = "debian"
print(f"Detected distro: {distro}")
if distro == "fedora":
run_command("sudo dnf install -y python3-devel python3-venv wl-clipboard libnotify portaudio alsa-lib-devel libxkbcommon-x11 xcb-util-cursor xcb-util-image xcb-util-keysyms xcb-util-renderutil xcb-util-wm")
elif distro == "debian":
run_command("sudo apt update && sudo apt install -y python3-dev python3-venv wl-clipboard libnotify-bin libportaudio2 libasound2-dev libxcb-cursor0 libxcb-xinerama0 libxkbcommon-x11-0")
# Double check venv is actually available now
if not run_command("python3 -m venv --help > /dev/null 2>&1"):
print("\nERROR: 'venv' module is still missing.")
if distro == "fedora": print("Please run: sudo dnf install python3-venv")
elif distro == "debian": print("Please run: sudo apt install python3-venv")
return False
# 2. Setup permissions (based on fix_permissions.sh)
print("Configuring permissions for Wayland/evdev...")
run_command("sudo usermod -aG input $USER")
udev_rule = 'KERNEL=="uinput", GROUP="input", MODE="0660", OPTIONS+="static_node=uinput"'
with open("99-voice-typer.rules", "w") as f:
f.write(udev_rule)
run_command("sudo mv 99-voice-typer.rules /etc/udev/rules.d/")
run_command("sudo udevadm control --reload-rules && sudo udevadm trigger")
run_command("sudo chgrp input /dev/uinput && sudo chmod 660 /dev/uinput")
# 3. Bootstrap Venv
if not bootstrap_venv():
return False
# 4. Install Launcher
print("Installing desktop launcher...")
desktop_dir = os.path.expanduser("~/.local/share/applications")
icon_dir = os.path.expanduser("~/.local/share/icons")
os.makedirs(desktop_dir, exist_ok=True)
os.makedirs(icon_dir, exist_ok=True)
# Use paths relative to the script location
script_dir = os.path.dirname(os.path.abspath(__file__))
project_path = script_dir
svg_src = os.path.join(script_dir, "launchers", "voice-typer.svg")
desktop_src = os.path.join(script_dir, "launchers", "voice-typer.desktop")
if os.path.exists(svg_src):
shutil.copy(svg_src, os.path.join(icon_dir, "voice-typer.svg"))
if os.path.exists(desktop_src):
with open(desktop_src, "r") as f:
content = f.read()
# Update Icon path
content = content.replace("Icon=/home/frey/.local/share/icons/voice-typer.svg", f"Icon={icon_dir}/voice-typer.svg")
import re
if "Exec=" in content:
content = re.sub(r"Exec=.*", f'Exec=bash -c "cd {project_path} && ./run.sh"', content)
else:
content += f'\nExec=bash -c "cd {project_path} && ./run.sh"\n'
with open(os.path.join(desktop_dir, "voice-typer.desktop"), "w") as f:
f.write(content)
run_command(f"chmod +x {os.path.join(desktop_dir, 'voice-typer.desktop')}")
print("\nSUCCESS! Logout and login again for permissions to take effect.")
print("NOTE: Local AI transcription is DISABLED by default to save space.")
print("To enable it, run: ./venv/bin/pip install -r requirements_local.txt")
print("\nYou can then find 'Voice Typer' in your application menu.")
def setup_windows():
print("Setting up for Windows...")
if not bootstrap_venv():
return False
print("Virtual environment ready. Use 'run_windows.bat' to start.")
def setup_macos():
print("Setting up for macOS...")
if not bootstrap_venv():
return False
print("Virtual environment ready. Use 'launchers/run_macos.sh' to start.")
def main():
system = platform.system().lower()
if "linux" in system:
setup_linux()
elif "windows" in system:
setup_windows()
elif "darwin" in system:
setup_macos()
else:
print(f"Unsupported system: {system}")
if __name__ == "__main__":
main()