Posted on 07-25-2024 05:10 PM
This script automates the configuration of display settings on macOS by checking the system architecture, downloading and installing the correct version of `displayplacer`, and setting up display mirroring with specified parameters. It ensures compatibility with ARM64 and Intel systems while optimizing display settings such as resolution, refresh rate, color depth, and scaling. The script uses JAMF parameters to adjust these settings dynamically.
Feel free to adjust the description if you have any specific points you'd like to highlight!
DisplayPlacer: https://github.com/jakehilborn/displayplacer
#!/bin/bash
# -----------------------------------------------------------------------------
# Script Name: DisplayPlacer.sh
# Author: [Muhammad Hasib]
# Created: 25Jul2024
# Last Modified: 25Jul2024
# Description: This script checks the system architecture, downloads and
# installs the appropriate version of displayplacer, and
# configures display settings for mirroring built-in and
# external screens with specified resolution, refresh rate,
# color depth, and scaling.
# It will 'OPTIMISE FOR' with an external display.
# -----------------------------------------------------------------------------
# Define variables for display settings
RESOLUTION="1920x1080"
HZ="60"
COLOR_DEPTH="8"
SCALING="off"
# Define paths
DISPLAYPLACER_PATH="/usr/local/bin/displayplacer"
DISPLAYPLACER_URL_APPLE="https://github.com/jakehilborn/displayplacer/releases/download/v1.4.0/displayplacer-apple-v140"
DISPLAYPLACER_URL_INTEL="https://github.com/jakehilborn/displayplacer/releases/download/v1.4.0/displayplacer-intel-v140"
# Determine the architecture
ARCH=$(uname -m)
if [[ "$ARCH" == "arm64" ]]; then
DISPLAYPLACER_URL="$DISPLAYPLACER_URL_APPLE"
else
DISPLAYPLACER_URL="$DISPLAYPLACER_URL_INTEL"
fi
# Download and install displayplacer if not found
if [ ! -f "$DISPLAYPLACER_PATH" ]; then
echo "displayplacer not found. Downloading and installing..."
curl -L "$DISPLAYPLACER_URL" -o /tmp/displayplacer
chmod +x /tmp/displayplacer
sudo mv /tmp/displayplacer "$DISPLAYPLACER_PATH"
echo "displayplacer installed at $DISPLAYPLACER_PATH."
fi
# List current display configurations and store the output
DISPLAY_CONFIG=$($DISPLAYPLACER_PATH list)
# Initialize arrays
BUILT_IN_ID=""
EXTERNAL_ID=""
# Process the display configurations
while read -r line; do
if [[ "$line" =~ Persistent\ screen\ id:\ ([^ ]+) ]]; then
PERSISTENT_ID="${BASH_REMATCH[1]}"
elif [[ "$line" =~ Type:\ (.+) ]]; then
TYPE="${BASH_REMATCH[1]}"
# Assign persistent ID based on screen type
if [[ "$TYPE" == *"built in"* ]]; then
BUILT_IN_ID="$PERSISTENT_ID"
else
EXTERNAL_ID="$PERSISTENT_ID"
fi
fi
done <<< "$DISPLAY_CONFIG"
# Check if both screen IDs are found
if [ -z "$BUILT_IN_ID" ] || [ -z "$EXTERNAL_ID" ]; then
echo "Could not find both built-in and external screens."
exit 1
fi
# Debug: print extracted persistent ids
echo "Built-in screen ID: $BUILT_IN_ID"
echo "External screen ID: $EXTERNAL_ID"
# Construct the displayplacer command for mirroring
CMD="$DISPLAYPLACER_PATH"
CMD+=" \"id:$EXTERNAL_ID+${BUILT_IN_ID} res:$RESOLUTION hz:$HZ color_depth:$COLOR_DEPTH enabled:true scaling:$SCALING\""
# Debug: print the command that will be executed
echo "Executing command: $CMD"
# Execute the constructed command
eval $CMD
Posted on 09-04-2024 08:54 AM
This works great! Though I did have to make a small addition to the script as the path "/usr/local/bin" doesn't usually exist in a clean state (at least not in Sonoma). So I added a mkdir /usr/local/bin line
mkdir /usr/local/bin
Modified script:
#!/bin/bash
# -----------------------------------------------------------------------------
# Script Name: DisplayPlacer.sh
# Author: [Muhammad Hasib]
# Created: 25Jul2024
# Last Modified: 25Jul2024
# Description: This script checks the system architecture, downloads and
# installs the appropriate version of displayplacer, and
# configures display settings for mirroring built-in and
# external screens with specified resolution, refresh rate,
# color depth, and scaling.
# It will 'OPTIMISE FOR' with an external display.
# -----------------------------------------------------------------------------
# Define variables for display settings
RESOLUTION="1920x1080"
HZ="60"
COLOR_DEPTH="8"
SCALING="off"
# Define paths
DISPLAYPLACER_PATH="/usr/local/bin/displayplacer"
DISPLAYPLACER_URL_APPLE="https://github.com/jakehilborn/displayplacer/releases/download/v1.4.0/displayplacer-apple-v140"
DISPLAYPLACER_URL_INTEL="https://github.com/jakehilborn/displayplacer/releases/download/v1.4.0/displayplacer-intel-v140"
# Determine the architecture
ARCH=$(uname -m)
if [[ "$ARCH" == "arm64" ]]; then
DISPLAYPLACER_URL="$DISPLAYPLACER_URL_APPLE"
else
DISPLAYPLACER_URL="$DISPLAYPLACER_URL_INTEL"
fi
# Download and install displayplacer if not found
if [ ! -f "$DISPLAYPLACER_PATH" ]; then
echo "displayplacer not found. Downloading and installing..."
curl -L "$DISPLAYPLACER_URL" -o /tmp/displayplacer
chmod +x /tmp/displayplacer
mkdir /usr/local/bin
sudo mv /tmp/displayplacer "$DISPLAYPLACER_PATH"
echo "displayplacer installed at $DISPLAYPLACER_PATH."
fi
# List current display configurations and store the output
DISPLAY_CONFIG=$($DISPLAYPLACER_PATH list)
# Initialize arrays
BUILT_IN_ID=""
EXTERNAL_ID=""
# Process the display configurations
while read -r line; do
if [[ "$line" =~ Persistent\ screen\ id:\ ([^ ]+) ]]; then
PERSISTENT_ID="${BASH_REMATCH[1]}"
elif [[ "$line" =~ Type:\ (.+) ]]; then
TYPE="${BASH_REMATCH[1]}"
# Assign persistent ID based on screen type
if [[ "$TYPE" == *"built in"* ]]; then
BUILT_IN_ID="$PERSISTENT_ID"
else
EXTERNAL_ID="$PERSISTENT_ID"
fi
fi
done <<< "$DISPLAY_CONFIG"
# Check if both screen IDs are found
if [ -z "$BUILT_IN_ID" ] || [ -z "$EXTERNAL_ID" ]; then
echo "Could not find both built-in and external screens."
exit 1
fi
# Debug: print extracted persistent ids
echo "Built-in screen ID: $BUILT_IN_ID"
echo "External screen ID: $EXTERNAL_ID"
# Construct the displayplacer command for mirroring
CMD="$DISPLAYPLACER_PATH"
CMD+=" \"id:$EXTERNAL_ID+${BUILT_IN_ID} res:$RESOLUTION hz:$HZ color_depth:$COLOR_DEPTH enabled:true scaling:$SCALING\""
# Debug: print the command that will be executed
echo "Executing command: $CMD"
# Execute the constructed command
eval $CMD
probably could have made the new mkdir part a conditional statement but if the directory already exists then mkdir wont do anything
a week ago
Hi guys,
Just wanted to make sure I'm correctly understanding how this works, since it seems awesome but when I looked in the instructions on github, there seem to be some additional manual steps?
I need a tool that allows mac minis that are in classrooms and connected to other monitors and projectors in the class, to have display settings locked on "mirrored" so that professors don't have to go into settings to change from "extended display" to "mirrored display".
From what I'm understanding I have to manually change settings on the device each time? Or is this wrong? This is what I read in the instructions.
displayplacer list
to print your current layout's args, so you can create profiles for scripting/hotkeys with Automator, BetterTouchTool, etc.a week ago
So I implement this exact mirroring request using displayplacer for one of our iMacs connected to a monitor in a classroom lab.
This way it always mirrors everytime a professors log into their specific profile.
Even if the prof changes the display settings, once someone else logs in, the display settings get set back to mirroring. I have a Jamf policy that I ran once that installs the displayplacer binary and sets the script.
I put displayplacer in a directory that I created called /Library/Payloads/
So displayplacer will have a path of:
/Library/Payloads/displayplacer
I do also as it installs run a line to remove any quarantine bits (could be optional depending on how you package it and deploy):
xattr -d -r com.apple.quarantine "/Library/Payloads/displayplacer"
To that Jamf policy I then run the following script in the script section which sets up everything including the launchagent that runs each time anybody logs into the computer:
#!/bin/sh
if [ -d "/Library/Scripts/MyCompanyScripts" ]
then
echo "directory /Library/Scripts/MyCompanyScripts already exist. Continuing..."
else
echo "creating directory /Library/Scripts/MyCompanyScripts since it does not already exist..."
mkdir /Library/Scripts/MyCompanyScripts
fi
echo "creating plist file com.MyCompany.displayplacerAddendum.plist LaunchAgent..."
cat <<'EOM' > "/Library/LaunchAgents/com.MyCompany.displayplacerAddendum.plist"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN http://www.apple.com/DTDs/PropertyList-1.0.dtd >
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.MyCompany.displayplacerAddendum.plist</string>
<key>ProgramArguments</key>
<array>
<string>/Library/Scripts/MyCompanyScripts/displayplacerAddendum.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>LaunchOnlyOnce</key>
<true/>
</dict>
</plist>
EOM
echo "setting 755 permissions on com.MyCompany.displayplacerAddendum.plist directory..."
chmod 755 "/Library/LaunchAgents/com.MyCompany.displayplacerAddendum.plist"
echo "creating script displayplacerAddendum.sh..."
cat <<'EOM' > /Library/Scripts/MyCompanyScripts/displayplacerAddendum.sh
#!/bin/sh
# -----------------------------------------------------------------------------
# Script Name: DisplayPlacer.sh
# Author: [Muhammad Hasib]
# Created: 25Jul2024
# Last Modified: 25Jul2024
# Description: This script checks the system architecture, downloads and
# installs the appropriate version of displayplacer, and
# configures display settings for mirroring built-in and
# external screens with specified resolution, refresh rate,
# color depth, and scaling.
# It will 'OPTIMISE FOR' with an external display.
# Additional Modification: Fernando Gonzalez
# -----------------------------------------------------------------------------
# Define variables for display settings
RESOLUTION="1920x1080"
HZ="60"
COLOR_DEPTH="8"
SCALING="off"
# Define paths
DISPLAYPLACER_PATH="/Library/Payloads/displayplacer"
# List current display configurations and store the output
DISPLAY_CONFIG=$($DISPLAYPLACER_PATH list)
# Initialize arrays
BUILT_IN_ID=""
EXTERNAL_ID=""
# Process the display configurations
while read -r line; do
if [[ "$line" =~ Persistent\ screen\ id:\ ([^ ]+) ]]; then
PERSISTENT_ID="${BASH_REMATCH[1]}"
elif [[ "$line" =~ Type:\ (.+) ]]; then
TYPE="${BASH_REMATCH[1]}"
# Assign persistent ID based on screen type
if [[ "$TYPE" == *"built in"* ]]; then
BUILT_IN_ID="$PERSISTENT_ID"
else
EXTERNAL_ID="$PERSISTENT_ID"
fi
fi
done <<< "$DISPLAY_CONFIG"
# Check if both screen IDs are found
if [ -z "$BUILT_IN_ID" ] || [ -z "$EXTERNAL_ID" ]; then
echo "Could not find both built-in and external screens."
exit 1
fi
# Debug: print extracted persistent ids
echo "Built-in screen ID: $BUILT_IN_ID"
echo "External screen ID: $EXTERNAL_ID"
# Construct the displayplacer command for mirroring
CMD="$DISPLAYPLACER_PATH"
CMD+=" \"id:$EXTERNAL_ID+${BUILT_IN_ID} res:$RESOLUTION hz:$HZ color_depth:$COLOR_DEPTH enabled:true scaling:$SCALING\""
# Debug: print the command that will be executed
echo "Executing command: $CMD"
# Execute the constructed command
eval $CMD
EOM
echo "settings 755 permissions on displayplacerAddendum.sh..."
chmod 755 /Library/Scripts/MyCompanyScripts/displayplacerAddendum.sh
exit
a week ago
Fantastic!! This is exactly what I was looking to implement as well. Thank you so very much, you made my week! 🙏 I will test this out and see if I run into any issues and then deploy it to our podiums.
Thank you!