- Новый модуль surround.py: генерация конфига в ~/.config/lgcompanion/, симлинк в pipewire.conf.d, перезапуск PipeWire, удаление устаревшего симлинка headset-companion - CLI: команда 'hrir apply [--no-restart]'; автоприменение в hrir add/ set-default/remove - install.sh использует 'lgcompanion hrir apply --no-restart' вместо inline-генерации в .generated/ - Тесты tests/test_surround.py
220 lines
9.1 KiB
Bash
Executable File
220 lines
9.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PYTHON="${PYTHON:-python3}"
|
|
|
|
# PREFIX: базовый префикс установки. По умолчанию ~/.local (пользовательская).
|
|
# DESTDIR: корень файловой системы для подготовки пакета (по умолчанию пустой).
|
|
PREFIX="${PREFIX:-${HOME}/.local}"
|
|
DESTDIR="${DESTDIR:-}"
|
|
|
|
# Определяем режим: пользовательский или системный.
|
|
USER_MODE=0
|
|
if [[ "${PREFIX}" == "${HOME}/.local" || "${PREFIX}" == "${HOME}"* ]]; then
|
|
USER_MODE=1
|
|
fi
|
|
|
|
echo "== Установщик LGCompanion =="
|
|
echo "PREFIX=${PREFIX}"
|
|
if [[ -n "${DESTDIR}" ]]; then
|
|
echo "DESTDIR=${DESTDIR}"
|
|
fi
|
|
if [[ "${USER_MODE}" -eq 1 ]]; then
|
|
echo "Режим: пользовательская установка"
|
|
else
|
|
echo "Режим: системная установка (пакетирование)"
|
|
fi
|
|
|
|
# 1. Проверка версии Python
|
|
PY_VERSION=$(${PYTHON} -c 'import sys; print(".".join(map(str, sys.version_info[:2])))')
|
|
PY_MAJOR=$(echo "${PY_VERSION}" | cut -d. -f1)
|
|
PY_MINOR=$(echo "${PY_VERSION}" | cut -d. -f2)
|
|
if [[ "${PY_MAJOR}" -lt 3 || ("${PY_MAJOR}" -eq 3 && "${PY_MINOR}" -lt 11) ]]; then
|
|
echo "ОШИБКА: требуется Python 3.11+ (найден ${PY_VERSION})"
|
|
exit 1
|
|
fi
|
|
|
|
# 2. Установка Python-пакета
|
|
if [[ "${USER_MODE}" -eq 1 ]]; then
|
|
if [[ -n "${VIRTUAL_ENV:-}" ]]; then
|
|
if command -v uv >/dev/null 2>&1; then
|
|
echo "Установка в активированное виртуальное окружение через uv..."
|
|
uv pip install -e "${SCRIPT_DIR}"
|
|
else
|
|
echo "Установка в активированное виртуальное окружение через pip..."
|
|
${PYTHON} -m pip install -e "${SCRIPT_DIR}"
|
|
fi
|
|
elif command -v pip3 >/dev/null 2>&1; then
|
|
echo "Установка через pip3 --user..."
|
|
pip3 install --user -e "${SCRIPT_DIR}"
|
|
export PATH="${HOME}/.local/bin:${PATH}"
|
|
else
|
|
echo "ОШИБКА: не найден pip3 и не активировано виртуальное окружение"
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "Установка Python-пакета в ${DESTDIR}${PREFIX} ..."
|
|
${PYTHON} -m pip install --root="${DESTDIR}" --prefix="${PREFIX}" --ignore-installed "${SCRIPT_DIR}"
|
|
fi
|
|
|
|
# 3. Применяем конфиг PipeWire виртуального surround
|
|
if [[ "${USER_MODE}" -eq 1 ]]; then
|
|
# Пользовательский режим: генерация и симлинк выполняются самим приложением,
|
|
# чтобы GUI/CLI могли повторять это автоматически при смене HRIR.
|
|
if ! lgcompanion hrir apply --no-restart; then
|
|
echo "ПРЕДУПРЕЖДЕНИЕ: активный HRIR не задан или файл не найден."
|
|
echo " Виртуальный surround sink не будет создан."
|
|
echo " Добавьте HRIR командой: lgcompanion hrir add <path.wav>"
|
|
fi
|
|
else
|
|
HRIR_PATH=$(lgcompanion hrir active 2>/dev/null || true)
|
|
if [[ -z "${HRIR_PATH}" || ! -f "${HRIR_PATH}" ]]; then
|
|
echo "ПРЕДУПРЕЖДЕНИЕ: активный HRIR не задан или файл не найден."
|
|
echo " Виртуальный surround sink не будет создан."
|
|
echo " Добавьте HRIR командой: lgcompanion hrir add <path.wav>"
|
|
HRIR_PATH=""
|
|
fi
|
|
|
|
if [[ -n "${HRIR_PATH}" ]]; then
|
|
# Для системного пакета копируем HRIR в /usr/share/lgcompanion/
|
|
DATA_DIR="${DESTDIR}${PREFIX}/share/lgcompanion"
|
|
mkdir -p "${DATA_DIR}"
|
|
cp "${HRIR_PATH}" "${DATA_DIR}/hrir.wav"
|
|
HRIR_PATH="${PREFIX}/share/lgcompanion/hrir.wav"
|
|
echo "Скопирован HRIR: ${DATA_DIR}/hrir.wav"
|
|
|
|
CONFIG_DIR="${DESTDIR}${PREFIX}/share/pipewire/pipewire.conf.d"
|
|
CONFIG_GENERATED="${CONFIG_DIR}/lgcompanion-virtual-surround.conf"
|
|
CONFIG_TEMPLATE="${SCRIPT_DIR}/src/lgcompanion/data/virtual-surround-7.1.conf.template"
|
|
if [[ ! -f "${CONFIG_TEMPLATE}" ]]; then
|
|
echo "ОШИБКА: шаблон PipeWire-конфига не найден: ${CONFIG_TEMPLATE}"
|
|
exit 1
|
|
fi
|
|
mkdir -p "${CONFIG_DIR}"
|
|
${PYTHON} - "${CONFIG_TEMPLATE}" "${HRIR_PATH}" "${CONFIG_GENERATED}" <<'PY'
|
|
import sys
|
|
from pathlib import Path
|
|
template_path, hrir_path, out_path = sys.argv[1:]
|
|
text = Path(template_path).read_text()
|
|
Path(out_path).write_text(text.replace("{hrir_path}", hrir_path))
|
|
PY
|
|
echo "Установлен системный конфиг PipeWire: ${CONFIG_GENERATED}"
|
|
fi
|
|
fi
|
|
|
|
# 5. Создаём конфиг по умолчанию (только в пользовательском режиме)
|
|
if [[ "${USER_MODE}" -eq 1 ]]; then
|
|
lgcompanion config show >/dev/null 2>&1 || true
|
|
fi
|
|
|
|
# 6. systemd user service
|
|
SERVICE_TEMPLATE="${SCRIPT_DIR}/install/lgcompanion.service"
|
|
if [[ ! -f "${SERVICE_TEMPLATE}" ]]; then
|
|
echo "ОШИБКА: шаблон сервиса не найден: ${SERVICE_TEMPLATE}"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "${USER_MODE}" -eq 1 ]]; then
|
|
if [[ -n "${VIRTUAL_ENV:-}" ]]; then
|
|
CLI_EXEC="${VIRTUAL_ENV}/bin/lgcompanion"
|
|
else
|
|
CLI_EXEC="${HOME}/.local/bin/lgcompanion"
|
|
fi
|
|
else
|
|
CLI_EXEC="${PREFIX}/bin/lgcompanion"
|
|
fi
|
|
|
|
if [[ "${USER_MODE}" -eq 1 ]]; then
|
|
SYSTEMD_USER_DIR="${HOME}/.config/systemd/user"
|
|
mkdir -p "${SYSTEMD_USER_DIR}"
|
|
SERVICE_FILE="${SYSTEMD_USER_DIR}/lgcompanion.service"
|
|
${PYTHON} - "${SERVICE_TEMPLATE}" "${CLI_EXEC}" "${SERVICE_FILE}" <<'PY'
|
|
import sys
|
|
from pathlib import Path
|
|
template_path, exec_path, out_path = sys.argv[1:]
|
|
text = Path(template_path).read_text()
|
|
Path(out_path).write_text(text.replace("{exec_path}", exec_path))
|
|
PY
|
|
chmod 644 "${SERVICE_FILE}" 2>/dev/null || true
|
|
systemctl --user daemon-reload 2>/dev/null || true
|
|
systemctl --user enable lgcompanion.service 2>/dev/null || true
|
|
echo "Установлен и включён user service: ${SERVICE_FILE}"
|
|
else
|
|
SYSTEMD_SYSTEM_DIR="${DESTDIR}${PREFIX}/lib/systemd/user"
|
|
mkdir -p "${SYSTEMD_SYSTEM_DIR}"
|
|
SERVICE_FILE="${SYSTEMD_SYSTEM_DIR}/lgcompanion.service"
|
|
${PYTHON} - "${SERVICE_TEMPLATE}" "${CLI_EXEC}" "${SERVICE_FILE}" <<'PY'
|
|
import sys
|
|
from pathlib import Path
|
|
template_path, exec_path, out_path = sys.argv[1:]
|
|
text = Path(template_path).read_text()
|
|
Path(out_path).write_text(text.replace("{exec_path}", exec_path))
|
|
PY
|
|
chmod 644 "${SERVICE_FILE}" 2>/dev/null || true
|
|
echo "Установлен системный user service: ${SERVICE_FILE}"
|
|
fi
|
|
|
|
# 7. Иконка приложения
|
|
ICON_SRC="${SCRIPT_DIR}/src/lgcompanion/data/icon.svg"
|
|
if [[ ! -f "${ICON_SRC}" ]]; then
|
|
echo "ОШИБКА: иконка приложения не найдена: ${ICON_SRC}"
|
|
exit 1
|
|
fi
|
|
if [[ "${USER_MODE}" -eq 1 ]]; then
|
|
ICON_DIR="${HOME}/.local/share/icons/hicolor/scalable/apps"
|
|
else
|
|
ICON_DIR="${DESTDIR}${PREFIX}/share/icons/hicolor/scalable/apps"
|
|
fi
|
|
mkdir -p "${ICON_DIR}"
|
|
cp "${ICON_SRC}" "${ICON_DIR}/lgcompanion.svg"
|
|
echo "Установлена иконка приложения: ${ICON_DIR}/lgcompanion.svg"
|
|
|
|
# 8. .desktop файл для меню приложений
|
|
DESKTOP_TEMPLATE="${SCRIPT_DIR}/install/lgcompanion.desktop"
|
|
if [[ "${USER_MODE}" -eq 1 ]]; then
|
|
if [[ -n "${VIRTUAL_ENV:-}" ]]; then
|
|
GUI_EXEC="${VIRTUAL_ENV}/bin/lgcompanion-gui"
|
|
else
|
|
GUI_EXEC="${HOME}/.local/bin/lgcompanion-gui"
|
|
fi
|
|
else
|
|
GUI_EXEC="${PREFIX}/bin/lgcompanion-gui"
|
|
fi
|
|
|
|
if [[ "${USER_MODE}" -eq 1 ]]; then
|
|
DESKTOP_DIR="${HOME}/.local/share/applications"
|
|
else
|
|
DESKTOP_DIR="${DESTDIR}${PREFIX}/share/applications"
|
|
fi
|
|
mkdir -p "${DESKTOP_DIR}"
|
|
DESKTOP_FILE="${DESKTOP_DIR}/lgcompanion.desktop"
|
|
${PYTHON} - "${DESKTOP_TEMPLATE}" "${GUI_EXEC}" "${DESKTOP_FILE}" <<'PY'
|
|
import sys
|
|
from pathlib import Path
|
|
template_path, exec_path, out_path = sys.argv[1:]
|
|
text = Path(template_path).read_text()
|
|
Path(out_path).write_text(text.replace("{exec_path}", exec_path))
|
|
PY
|
|
chmod 644 "${DESKTOP_FILE}" 2>/dev/null || true
|
|
echo "Создан .desktop файл: ${DESKTOP_FILE}"
|
|
|
|
if [[ "${USER_MODE}" -eq 1 ]]; then
|
|
echo ""
|
|
echo "Установка завершена."
|
|
echo "Перезапустите PipeWire, чтобы загрузить виртуальный surround sink:"
|
|
echo " systemctl --user restart pipewire pipewire-pulse wireplumber"
|
|
echo "Затем запустите демон:"
|
|
echo " systemctl --user start lgcompanion.service"
|
|
echo "Или вручную:"
|
|
echo " lgcompanion run -v"
|
|
echo ""
|
|
echo "Для запуска GUI:"
|
|
echo " lgcompanion-gui"
|
|
else
|
|
echo ""
|
|
echo "Системная установка завершена."
|
|
echo "Не забудьте обновить базу данных desktop-файлов:"
|
|
echo " update-desktop-database ${PREFIX}/share/applications"
|
|
fi
|