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 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
|
#!/bin/bash
# Script to run JS8Call AppImage in Docker with X11 and audio support
#
# Usage: ./docker-run.sh [--rebuild] [--debug] [--help]
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Function to print colored output
print_status() {
echo -e "${GREEN}[*]${NC} $1"
}
print_error() {
echo -e "${RED}[!]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[!]${NC} $1"
}
print_info() {
echo -e "${BLUE}[i]${NC} $1"
}
# Check if Docker is installed
if ! command -v docker &> /dev/null; then
print_error "Docker is not installed. Please install Docker first."
exit 1
fi
# Parse command line arguments
REBUILD_IMAGE=false
DEBUG_MODE=false
while [[ $# -gt 0 ]]; do
case $1 in
--rebuild)
REBUILD_IMAGE=true
shift
;;
--debug)
DEBUG_MODE=true
shift
;;
--help)
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Options:"
echo " --rebuild Rebuild the runtime image"
echo " --debug Run bash instead of JS8Call for debugging"
echo " --help Show this help message"
echo ""
echo "Any additional arguments are passed to JS8Call"
exit 0
;;
*)
# Pass through to JS8Call
break
;;
esac
done
# Rebuild image if requested
if [ "$REBUILD_IMAGE" = true ]; then
print_status "Removing old runtime image..."
docker rmi js8call-runtime:ubuntu-24.04 2>/dev/null || true
print_status "Runtime image will be rebuilt"
fi
# Check if AppImage exists
APPIMAGE_PATH=""
if [ -f "output/js8call-x86_64.AppImage" ]; then
APPIMAGE_PATH="output/js8call-x86_64.AppImage"
elif [ -f "../output/js8call-x86_64.AppImage" ]; then
APPIMAGE_PATH="../output/js8call-x86_64.AppImage"
else
# Try to find it
APPIMAGE_PATH=$(find . -name "js8call*.AppImage" -type f | head -1)
if [ -z "$APPIMAGE_PATH" ]; then
print_error "JS8Call AppImage not found!"
print_info "Please build it first with: ./docker-build.sh"
exit 1
fi
fi
print_status "Found AppImage at: $APPIMAGE_PATH"
# Audio setup - use PulseAudio TCP for better container compatibility
print_info "Setting up PulseAudio TCP connection..."
# Load PulseAudio TCP module on the host
pactl load-module module-native-protocol-tcp port=4713 auth-anonymous=1 >/dev/null 2>&1 || true
# Configure container to use TCP connection
AUDIO_OPTS="-e PULSE_SERVER=tcp:host.docker.internal:4713 --add-host=host.docker.internal:host-gateway"
print_status "Using PulseAudio TCP connection (JS8Call will appear in pavucontrol)"
# Keep the temp variable for cleanup
PULSE_COOKIE_TEMP=""
# Build runtime image if it doesn't exist
if ! docker images | grep -q "js8call-runtime.*ubuntu-24.04"; then
print_status "Building runtime image..."
docker build -f Dockerfile.runtime -t js8call-runtime:ubuntu-24.04 .
fi
# Get the absolute path of the AppImage
APPIMAGE_ABS_PATH=$(realpath "$APPIMAGE_PATH")
# Make sure the AppImage is executable on the host
chmod +x "$APPIMAGE_ABS_PATH" 2>/dev/null || true
# Set up X11 forwarding
XSOCK=/tmp/.X11-unix
XAUTH=/tmp/.docker.xauth.$$
# Allow X connections from local Docker containers
print_info "Setting up X11 forwarding..."
xhost +local:docker 2>/dev/null || xhost +local: 2>/dev/null || true
# Create new Xauthority file
rm -f $XAUTH
# Since xhost +local:docker allows access, we don't strictly need xauth
# But we'll create an empty file to avoid warnings
touch $XAUTH
chmod 644 $XAUTH
print_status "Starting JS8Call with X11 and audio forwarding..."
# Create config directory if it doesn't exist
CONFIG_DIR="$(pwd)/config"
if [ ! -d "$CONFIG_DIR" ]; then
print_info "Creating config directory..."
mkdir -p "$CONFIG_DIR"
fi
# Create JS8Call.ini file if it doesn't exist
CONFIG_FILE="$CONFIG_DIR/JS8Call.ini"
if [ ! -f "$CONFIG_FILE" ]; then
touch "$CONFIG_FILE"
fi
# Make config directory writable
chmod 777 "$CONFIG_DIR"
chmod 666 "$CONFIG_FILE" 2>/dev/null || true
# Copy AppImage to a temp location for the container
TEMP_APPIMAGE="/tmp/js8call-${RANDOM}.AppImage"
cp "$APPIMAGE_ABS_PATH" "$TEMP_APPIMAGE"
# Choose command based on debug mode
if [ "$DEBUG_MODE" = true ]; then
print_info "Running in debug mode - starting bash shell"
else
print_info "Running JS8Call normally"
fi
# No need for audio group with TCP connection
AUDIO_GROUP_OPT=""
# Run the container
if [ "$DEBUG_MODE" = true ]; then
docker run --rm -it \
--name js8call-runtime \
-e DISPLAY=$DISPLAY \
-e XAUTHORITY=/tmp/.docker.xauth \
-e QT_X11_NO_MITSHM=1 \
-v $XSOCK:$XSOCK:rw \
-v $XAUTH:/tmp/.docker.xauth:rw \
-v "$TEMP_APPIMAGE:/tmp/js8call.AppImage:ro" \
-v "$CONFIG_DIR:/tmp/js8call-config" \
$AUDIO_OPTS \
--device /dev/dri \
$AUDIO_GROUP_OPT \
--network host \
--ipc=host \
--entrypoint /bin/bash \
js8call-runtime:ubuntu-24.04
else
docker run --rm -it \
--name js8call-runtime \
-e DISPLAY=$DISPLAY \
-e XAUTHORITY=/tmp/.docker.xauth \
-e QT_X11_NO_MITSHM=1 \
-v $XSOCK:$XSOCK:rw \
-v $XAUTH:/tmp/.docker.xauth:rw \
-v "$TEMP_APPIMAGE:/tmp/js8call.AppImage:ro" \
-v "$CONFIG_DIR:/tmp/js8call-config" \
$AUDIO_OPTS \
--device /dev/dri \
$AUDIO_GROUP_OPT \
--network host \
--ipc=host \
js8call-runtime:ubuntu-24.04 "$@"
fi
# Check exit code
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
print_error "Container exited with code $EXIT_CODE"
fi
# After JS8Call exits, show config location
if [ -f "$CONFIG_FILE" ] && [ -s "$CONFIG_FILE" ]; then
print_info "JS8Call configuration saved to: $CONFIG_FILE"
# Also create a symlink at js8call.ini in current directory for easy access
if [ ! -f "js8call.ini" ]; then
ln -sf "$CONFIG_FILE" "js8call.ini"
print_info "Created symlink: js8call.ini -> $CONFIG_FILE"
fi
else
print_warning "No configuration was saved (JS8Call may not have created settings yet)"
fi
# Cleanup function
cleanup() {
rm -f "$TEMP_APPIMAGE"
rm -f $XAUTH
[ -n "$PULSE_COOKIE_TEMP" ] && rm -f "$PULSE_COOKIE_TEMP"
xhost -local:docker 2>/dev/null || true
# Try to unload the PulseAudio TCP module
pactl unload-module module-native-protocol-tcp 2>/dev/null || true
}
# Set trap to cleanup on exit
trap cleanup EXIT
# Wait for container to finish
wait
|