Initial commit: FaceTime HD camera driver and OBS performance scripts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
28allday 2026-03-28 18:15:22 +00:00
commit 4d04b06d41
2 changed files with 556 additions and 0 deletions

451
facetimehd-installer.sh Executable file
View file

@ -0,0 +1,451 @@
#!/bin/bash
# FaceTime HD Camera Installation Script for Linux Kernel 6.8+
# Compatible with MacBook Air A1466 EMC 3178 and similar models
# Author: System Script
# Version: 1.0
# Last Updated: 2025
set -e
# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Script name for logging
SCRIPT_NAME=$(basename "$0")
LOG_FILE="/tmp/facetimehd-install-$(date +%Y%m%d-%H%M%S).log"
# Function to print colored output
print_status() {
echo -e "${BLUE}[${SCRIPT_NAME}]${NC} $1" | tee -a "$LOG_FILE"
}
print_success() {
echo -e "${GREEN}[✓]${NC} $1" | tee -a "$LOG_FILE"
}
print_error() {
echo -e "${RED}[✗]${NC} $1" | tee -a "$LOG_FILE"
}
print_warning() {
echo -e "${YELLOW}[!]${NC} $1" | tee -a "$LOG_FILE"
}
# Function to check if running as root
check_root() {
if [[ $EUID -eq 0 ]]; then
print_error "This script should not be run as root!"
print_status "Please run without sudo: ./$SCRIPT_NAME"
exit 1
fi
}
# Function to detect distribution
detect_distro() {
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$NAME
VER=$VERSION_ID
else
print_error "Cannot detect distribution"
exit 1
fi
}
# Function to check kernel version
check_kernel() {
KERNEL_VERSION=$(uname -r)
KERNEL_MAJOR=$(echo $KERNEL_VERSION | cut -d. -f1)
KERNEL_MINOR=$(echo $KERNEL_VERSION | cut -d. -f2)
print_status "Detected kernel version: $KERNEL_VERSION"
if [[ $KERNEL_MAJOR -lt 5 ]] || ([[ $KERNEL_MAJOR -eq 5 ]] && [[ $KERNEL_MINOR -lt 7 ]]); then
print_warning "Kernel version is older than 5.7, using legacy installation method"
USE_LEGACY=true
else
USE_LEGACY=false
fi
}
# Function to check if camera is already working
check_camera() {
if [ -e /dev/video0 ] || [ -e /dev/video1 ]; then
if lsmod | grep -q facetimehd; then
print_warning "FaceTime HD camera driver appears to be already installed"
read -p "Do you want to reinstall? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
print_status "Exiting..."
exit 0
fi
fi
fi
}
# Function to check and disable Secure Boot if needed
check_secure_boot() {
if command -v mokutil &> /dev/null; then
if mokutil --sb-state 2>&1 | grep -q "SecureBoot enabled"; then
print_warning "Secure Boot is enabled. The camera driver may not load."
print_status "You have three options:"
echo " 1. Disable Secure Boot in BIOS/UEFI (recommended)"
echo " 2. Sign the kernel module (advanced)"
echo " 3. Continue anyway (module may not load)"
read -p "Choose option (1-3): " -n 1 -r
echo
case $REPLY in
1)
print_status "Please reboot and disable Secure Boot in BIOS/UEFI settings"
print_status "Then run this script again"
exit 0
;;
2)
SIGN_MODULE=true
;;
3)
print_warning "Continuing with Secure Boot enabled..."
;;
esac
fi
fi
}
# Function to install dependencies
install_dependencies() {
print_status "Installing required dependencies..."
if [[ "$OS" == "Ubuntu" ]] || [[ "$OS" == "Linux Mint" ]] || [[ "$OS" == "Debian"* ]]; then
sudo apt update
sudo apt install -y \
git \
curl \
xz-utils \
cpio \
make \
gcc \
linux-headers-$(uname -r) \
libssl-dev \
checkinstall \
build-essential \
dkms \
v4l-utils || {
print_error "Failed to install dependencies"
exit 1
}
elif [[ "$OS" == "Fedora" ]]; then
sudo dnf install -y \
git \
curl \
xz \
cpio \
make \
gcc \
kernel-devel-$(uname -r) \
openssl-devel \
dkms \
v4l-utils || {
print_error "Failed to install dependencies"
exit 1
}
else
print_error "Unsupported distribution: $OS"
exit 1
fi
print_success "Dependencies installed successfully"
}
# Function to remove old installations
cleanup_old_installation() {
print_status "Cleaning up old installations..."
# Unload module if loaded
if lsmod | grep -q facetimehd; then
sudo modprobe -r facetimehd 2>/dev/null || true
fi
# Remove old DKMS installations
if dkms status | grep -q facetimehd; then
sudo dkms remove facetimehd/0.6.13 --all 2>/dev/null || true
sudo dkms remove facetimehd/0.1 --all 2>/dev/null || true
fi
# Remove old files
sudo rm -rf /usr/src/facetimehd* 2>/dev/null || true
sudo rm -f /lib/modules/*/extra/facetimehd.ko* 2>/dev/null || true
print_success "Cleanup completed"
}
# Function to download and install firmware
install_firmware() {
print_status "Downloading and installing camera firmware..."
WORK_DIR=$(mktemp -d)
cd "$WORK_DIR"
# Clone firmware repository
git clone https://github.com/patjak/facetimehd-firmware.git || {
print_error "Failed to download firmware repository"
exit 1
}
cd facetimehd-firmware
# Build and install firmware
make || {
print_error "Failed to build firmware"
exit 1
}
sudo make install || {
print_error "Failed to install firmware"
exit 1
}
# Verify firmware installation
if [ ! -f /lib/firmware/facetimehd/firmware.bin ]; then
print_warning "Firmware not found in expected location, creating symlink..."
sudo mkdir -p /lib/firmware/facetimehd
if [ -f /usr/lib/firmware/facetimehd/firmware.bin ]; then
sudo ln -sf /usr/lib/firmware/facetimehd/firmware.bin /lib/firmware/facetimehd/firmware.bin
else
print_error "Firmware installation failed"
exit 1
fi
fi
print_success "Firmware installed successfully"
cd ~
rm -rf "$WORK_DIR"
}
# Function to install driver for kernel 6.8+
install_driver() {
print_status "Downloading and installing FaceTime HD driver..."
WORK_DIR=$(mktemp -d)
cd "$WORK_DIR"
# For kernel 6.8+, try the updated repository first
if [[ $KERNEL_MAJOR -ge 6 ]] && [[ $KERNEL_MINOR -ge 8 ]]; then
print_status "Using updated driver for kernel 6.8+"
# Try multiple repositories in order of compatibility
REPOS=(
"https://github.com/patjak/facetimehd.git"
"https://github.com/kekrby/facetimehd.git"
"https://github.com/bartkessels/facetimehd.git"
)
CLONED=false
for repo in "${REPOS[@]}"; do
print_status "Trying repository: $repo"
if git clone "$repo" facetimehd 2>/dev/null; then
CLONED=true
break
fi
done
if [ "$CLONED" = false ]; then
print_error "Failed to download any driver repository"
exit 1
fi
else
# For older kernels, use the standard repository
git clone https://github.com/patjak/facetimehd.git || {
print_error "Failed to download driver repository"
exit 1
}
fi
cd facetimehd
# Apply patches for kernel 6.8+ if needed
if [[ $KERNEL_MAJOR -ge 6 ]]; then
print_status "Applying kernel 6.x compatibility patches..."
# Fix for VFL_TYPE_GRABBER deprecation
if grep -q "VFL_TYPE_GRABBER" fthd_v4l2.c 2>/dev/null; then
sed -i 's/VFL_TYPE_GRABBER/VFL_TYPE_VIDEO/g' fthd_v4l2.c
fi
# Fix for other kernel 6.x API changes
if grep -q "v4l2_device_release" fthd_v4l2.c 2>/dev/null; then
sed -i 's/v4l2_device_release/video_device_release/g' fthd_v4l2.c
fi
fi
# Install via DKMS
print_status "Installing driver via DKMS..."
DRIVER_VERSION="0.6.13"
sudo cp -r . "/usr/src/facetimehd-$DRIVER_VERSION"
# Create DKMS configuration if it doesn't exist
if [ ! -f "/usr/src/facetimehd-$DRIVER_VERSION/dkms.conf" ]; then
sudo tee "/usr/src/facetimehd-$DRIVER_VERSION/dkms.conf" > /dev/null <<EOF
PACKAGE_NAME="facetimehd"
PACKAGE_VERSION="$DRIVER_VERSION"
BUILT_MODULE_NAME[0]="facetimehd"
DEST_MODULE_LOCATION[0]="/extra"
AUTOINSTALL="yes"
MAKE="make -C \${kernel_source_dir} M=\${dkms_tree}/\${PACKAGE_NAME}/\${PACKAGE_VERSION}/build modules"
CLEAN="make -C \${kernel_source_dir} M=\${dkms_tree}/\${PACKAGE_NAME}/\${PACKAGE_VERSION}/build clean"
EOF
fi
sudo dkms add -m facetimehd -v "$DRIVER_VERSION" || {
print_error "Failed to add driver to DKMS"
exit 1
}
sudo dkms build -m facetimehd -v "$DRIVER_VERSION" || {
print_error "Failed to build driver with DKMS"
exit 1
}
sudo dkms install -m facetimehd -v "$DRIVER_VERSION" || {
print_error "Failed to install driver with DKMS"
exit 1
}
print_success "Driver installed successfully"
cd ~
rm -rf "$WORK_DIR"
}
# Function to configure module loading
configure_module() {
print_status "Configuring module loading..."
# Blacklist conflicting modules
echo 'blacklist bdc_pci' | sudo tee /etc/modprobe.d/blacklist-facetimehd.conf > /dev/null
# Add facetimehd to modules
if ! grep -q "^facetimehd$" /etc/modules 2>/dev/null; then
echo 'facetimehd' | sudo tee -a /etc/modules > /dev/null
fi
# Load the module
print_status "Loading FaceTime HD module..."
sudo modprobe -r bdc_pci 2>/dev/null || true
sudo modprobe facetimehd || {
print_error "Failed to load module"
print_status "Check dmesg for errors: sudo dmesg | tail -20"
exit 1
}
print_success "Module configured and loaded"
}
# Function to verify installation
verify_installation() {
print_status "Verifying installation..."
# Check if module is loaded
if ! lsmod | grep -q facetimehd; then
print_error "Module is not loaded"
return 1
fi
# Check for video device
if [ ! -e /dev/video0 ] && [ ! -e /dev/video1 ] && [ ! -e /dev/video2 ]; then
print_error "No video device found"
return 1
fi
# Get video device
VIDEO_DEVICE=$(ls /dev/video* 2>/dev/null | head -1)
if [ -n "$VIDEO_DEVICE" ]; then
print_success "Camera device found at: $VIDEO_DEVICE"
# Show camera information
print_status "Camera information:"
v4l2-ctl -d "$VIDEO_DEVICE" --info 2>/dev/null || true
fi
return 0
}
# Function to test camera
test_camera() {
print_status "Would you like to test the camera now? (y/N): "
read -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
VIDEO_DEVICE=$(ls /dev/video* 2>/dev/null | head -1)
if command -v cheese &> /dev/null; then
print_status "Starting Cheese..."
cheese &
elif command -v guvcview &> /dev/null; then
print_status "Starting guvcview..."
guvcview &
else
print_warning "No camera application found. Install cheese or guvcview to test."
print_status "You can install with: sudo apt install cheese"
fi
fi
}
# Main installation flow
main() {
clear
echo "======================================"
echo "FaceTime HD Camera Installation Script"
echo "======================================"
echo
print_status "Log file: $LOG_FILE"
echo
# Pre-installation checks
check_root
detect_distro
check_kernel
check_camera
check_secure_boot
# Installation
install_dependencies
cleanup_old_installation
install_firmware
install_driver
configure_module
# Post-installation
if verify_installation; then
print_success "Installation completed successfully!"
echo
print_status "Camera should now be working."
print_status "You can test it with applications like:"
echo " - cheese"
echo " - guvcview"
echo " - Google Chrome/Chromium"
echo " - Firefox"
echo
test_camera
else
print_error "Installation completed but verification failed"
print_status "Please check the log file: $LOG_FILE"
print_status "And kernel messages: sudo dmesg | grep -i facetime"
fi
echo
print_status "If you encounter issues, please check:"
echo " 1. Secure Boot status (disable if enabled)"
echo " 2. Kernel messages: sudo dmesg | grep -i facetime"
echo " 3. Module status: lsmod | grep facetimehd"
echo " 4. Log file: $LOG_FILE"
}
# Run main function
main "$@"

105
obs-performance-script.sh Executable file
View file

@ -0,0 +1,105 @@
#!/bin/bash
# OBS Performance Script for Linux Mint Cinnamon
# Fixed version for newer Cinnamon versions
# Color codes for output
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color
echo -e "${GREEN}OBS Performance Optimizer for Linux Mint Cinnamon${NC}"
echo "=================================================="
# Check if OBS is installed
if ! command -v obs-studio &> /dev/null && ! command -v flatpak run com.obsproject.Studio &> /dev/null; then
echo -e "${RED}Error: OBS Studio not found!${NC}"
echo "Install with: sudo apt install obs-studio"
echo "Or: flatpak install flathub com.obsproject.Studio"
exit 1
fi
# Detect OBS installation type
if command -v obs-studio &> /dev/null; then
OBS_COMMAND="obs-studio"
elif flatpak list | grep -q "com.obsproject.Studio"; then
OBS_COMMAND="flatpak run com.obsproject.Studio"
else
OBS_COMMAND="obs" # fallback
fi
# Store original settings (using correct keys for newer Cinnamon)
echo -e "${YELLOW}Saving current desktop settings...${NC}"
# Check Cinnamon version and use appropriate settings
if gsettings list-keys org.cinnamon.desktop.wm.preferences | grep -q "compositor-manager"; then
# Newer Cinnamon
ORIGINAL_COMPOSITOR=$(gsettings get org.cinnamon.desktop.wm.preferences compositor-manager 2>/dev/null || echo "true")
COMPOSITOR_KEY="org.cinnamon.desktop.wm.preferences compositor-manager"
else
# Try muffin settings
ORIGINAL_COMPOSITOR="true"
COMPOSITOR_KEY=""
fi
ORIGINAL_UNREDIRECT=$(gsettings get org.cinnamon.muffin unredirect-fullscreen-windows 2>/dev/null || echo "false")
echo "Unredirect: $ORIGINAL_UNREDIRECT"
# Apply performance settings
echo -e "\n${YELLOW}Applying performance optimizations...${NC}"
# Disable effects using available methods
if [ -n "$COMPOSITOR_KEY" ]; then
gsettings set $COMPOSITOR_KEY false 2>/dev/null && echo -e "${GREEN}✓ Compositor disabled${NC}"
else
# Alternative: disable effects
gsettings set org.cinnamon enable-effects false 2>/dev/null && echo -e "${GREEN}✓ Desktop effects disabled${NC}"
fi
# Set unredirect for fullscreen
gsettings set org.cinnamon.muffin unredirect-fullscreen-windows true 2>/dev/null && echo -e "${GREEN}✓ Fullscreen unredirect enabled${NC}"
# Alternative compositor control for Cinnamon
if command -v cinnamon-settings &> /dev/null; then
# Try to disable vsync through muffin dconf settings
dconf write /org/cinnamon/muffin/sync-to-vblank false 2>/dev/null
fi
# Set CPU governor to performance if available
if [ -f /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor ]; then
echo -e "\n${YELLOW}Setting CPU to performance mode (may require password)${NC}"
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo -e "${GREEN}✓ CPU performance mode set${NC}"
fi
fi
# Launch OBS with optimized environment
echo -e "\n${GREEN}Launching OBS with optimized settings...${NC}"
echo "==========================================="
echo "Using command: $OBS_COMMAND"
# Run OBS with performance environment variables
env vblank_mode=0 \
__GL_SYNC_TO_VBLANK=0 \
__GL_THREADED_OPTIMIZATIONS=1 \
PULSE_LATENCY_MSEC=30 \
$OBS_COMMAND
# Restore original settings after OBS closes
echo -e "\n${YELLOW}OBS closed. Restoring original settings...${NC}"
if [ -n "$COMPOSITOR_KEY" ]; then
gsettings set $COMPOSITOR_KEY "$ORIGINAL_COMPOSITOR" 2>/dev/null
else
gsettings set org.cinnamon enable-effects true 2>/dev/null
fi
gsettings set org.cinnamon.muffin unredirect-fullscreen-windows "$ORIGINAL_UNREDIRECT" 2>/dev/null
# Restore vsync if it was modified
dconf write /org/cinnamon/muffin/sync-to-vblank true 2>/dev/null
echo -e "${GREEN}✓ Desktop settings restored${NC}"
echo -e "${GREEN}Done!${NC}"