Implement custom dynamic wallpaper with Applescript

B: Dynamic Wallpaper

When it comes to the whole dynamic wallpaper on Apple, we have to talk about his own solution. Apple first introduced the concept in macOS Mojave to change the desktop wallpaper based on the time of day. The technology used is to set up the wallpaper with a Heic format image with time information to set up the wallpaper, which contains a number of TIFF images and time information. When it’s time to switch the app’s image. It’s a nice technology, it’s resource – free and it’s practical. There was a time when you could even make your own images to do this, but now that’s not possible on Big Sur. Because the wallpaper directory is in /System/Library/Desktop\ Pictures. The entire system directory is read-only, so you can’t add it yourself.

At this point, the “official channels” that enable this function are “blocked.” We have to find another way.

Before I looked it up, I wondered if it was possible to use a script to do this, since the Mac is Unix. Is it possible to use Bash scripts with event hooks to implement dynamic wallpapers?

Classics search, can be ok, but there is a bit different with imagination.

You can do this using Applescript and using Launchctl for timed calls. In theory it should be possible to do this with Crontab+Bash, but Cron doesn’t seem to work on the latest systems. Not even if you give access to the entire file. I guess it’s because of Apple’s security design. In addition, using Lauchctl has benefits that Cron does not. More on that below. If you are a Linux-based machine, you can probably do this with Crontab+Bash. But I didn’t try 🤔

2. Applescript

So what is Applescript?

AppleScript is a scripting language created by Apple. It allows users to directly control scriptable Macintosh applications, As well as parts of macOS itself. You can create scripts — sets of written instructions — to repetitive tasks, combine features from multiple scriptable applications, and create complex workflows.

The above is the introduction of the Apple development website. Basically, it’s a scripting language for Apple.

Applescript is cheap to learn when you have written in other languages. And it’s very similar to the natural language of English. So on the whole it’s pretty easy to learn. There is no IDE a bit 🌚 system comes with an Applescript Editor (Script Editor), can be said to be basically no Windows notepad to use is. When I was learning basic syntax, THERE was a Bug in the script highlighting card, which made it impossible to write. But since Applescript can’t be opened with an editor like Vim, there’s not much choice.

We need to prepare the wallpaper file before we start. My idea is to change every hour of the day for 24 hours. A day consists of 24 different wallpapers. You can take a set of pictures in one place or find someone else’s work on the Internet.

Here I put the file in a picture in my home directory:

# Display X is for the X - th Display.
The name of the image is the specific number of hours.
~/Pictures/Wallpapers/Display1/01.jpg
Copy the code

Like this:

The script we will use is as follows:

(* Script By: Puls Garney 08.11.2021 The Idea Came From: https://github.com/pipwerks/OS-X-Wallpaper-Changer Picture Locations: ~/Pictures/Wallpapers/Display1/01.jpg ~/Pictures/Wallpapers/Display2/03.jpg ~/Pictures/Wallpapers/Display3/24.jpg *)

set useSameWallpaper to false

set wallpaperPath to "~/Pictures/Wallpapers/Display"

set currentPhoto to hours of (current date) as string

if ((the length of currentPhoto) < 2) then
    set currentPhoto to "0" & currentPhoto
end if

tell application "System Events"
    
    if (useSameWallpaper) then
        
        tell every desktop
            
            set wallpaper to wallpaperPath & 1 "/" & currentPhoto & ".jpg"
            
            set picture to POSIX file wallpaper
            
        end tell
        
    else
        
        set displays to a reference to every desktop
        
        repeat with counter from 1 to (count displays)
            
            try
                
                set wallpaper to (wallpaperPath & counter as string) & "/" & currentPhoto & ".jpg"
                
                set picture of item counter of displays to POSIX file wallpaper
                
            end try
            
        end repeat
        
    end if
    
end tell
Copy the code

Now I will talk about the functions one by one:

set useSameWallpaper to false
Copy the code

This is a variable and can be changed to true if you want to use the same set of images on all monitors. I want them all to be different so I used false.

set currentPhoto to hours of (current date) as string

if ((the length of currentPhoto) < 2) then
    set currentPhoto to "0" & currentPhoto
end if
Copy the code

Then we get the number of hours of the current system time. If the total number of hours is less than 2 digits, we complete 2 bits. For example, if it is 2 o ‘clock, it will be “02” instead of “2”.

And then next we broadcast different set image events as system events.

tell every desktop

    set wallpaper to wallpaperPath & 1 "/" & currentPhoto & ".jpg"

    set picture to POSIX file wallpaper

end tell
Copy the code

If it is to all display the same group of pictures. The first set of images will be used entirely here.

set displays to a reference to every desktop

repeat with counter from 1 to (count displays)
    
    try
        
        set wallpaper to (wallpaperPath & counter as string) & "/" & currentPhoto & ".jpg"
        
        set picture of item counter of displays to POSIX file wallpaper
        
    end try
    
end repeat
Copy the code

Here we get all the display instances. And set a different picture for each different monitor according to the previously prepared picture path.

Basically, the script is ready at this point. If you have pictures you can try running. Just run it from inside the Applescript editor. It comes with an Editor called Script Editor. You can find it in Spotlight.

Or if you have saved the script, you can run it directly from the command line.

osascript ~/Pictures/Wallpapers/Wallpaper.scpt
Copy the code

If running problems can be added a log XXX can print log debugging.

Now we have images and scripts. The next step is to get him moving on his own. Total can’t we manually open a period of time to run an editor 🤣🤣

3. Launchctl

So what is Lauchctl?

Launchctl is a unified service management framework introduced after Mac OS X 10.4 that can start, stop, and manage daemons, applications, processes, and scripts. The execution cycles and tasks are specified through the PList configuration file.

The main places to place plist are:

~/Library/LaunchAgents # Current user defined task /Library/LaunchAgents # System administrator defined task /Library/LaunchDaemons # System daemon task defined by administrator / System/Library/LaunchAgents # apple defined tasks/System/Library/LaunchDaemons # apple defined System daemon tasksCopy the code

If you are familiar with Crontab, they are similar in general. The PList file has a lot of configurable content and is in XML. Feel free to read more if you’re interested, but I’ll just cover the Settings we need to use in this example.

Go to ~/Library/LaunchAgents and create a new file:

<! -- ~/Library/LaunchAgents/me.dynamic.wallpaper.plist -->

      
<! DOCTYPEplist PUBLIC "- / / / / DTD PLIST Apple 1.0 / / EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <! -- Label unique identifier -->
    <key>Label</key>
    <string>me.dynamic.wallpaper.plist</string>

    <! -- Specify the script to run -->
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/osascript</string>
        <string>/Users/pulsgarney/Pictures/Wallpapers/Wallpaper.scpt</string>
    </array>

    <! -- Specify running time -->
    <key>StartCalendarInterval</key>
    <dict>
        <key>Minute</key>
        <integer>0</integer>
    </dict>
</dict>
</plist>
Copy the code

Above we have a file that defines how we run our script using OSAScript. Run once at the first minute of every hour, or 24 times a day. If your script has a problem and does not work properly, you can add the following sentences to the log to facilitate debugging.

    <! -- Standard output file -->
    <key>StandardOutPath</key>
    <string>/Users/pulsgarney/Pictures/Wallpapers/log/output.log</string>

    <! -- Standard error output file, error log -->
    <key>StandardErrorPath</key>
    <string>/Users/pulsgarney/Pictures/Wallpapers/log/error.log</string>
Copy the code

If you want it to refresh more often, you can add this sentence to make it refresh regularly in seconds:

    <! -- Time interval -->
    <key>StartInterval</key>
    <integer>300</integer>
Copy the code

Next, we can load the task from the command line.

Load task
launchctl load me.dynamic.wallpaper.plist
# uninstall task
launchctl unload me.dynamic.wallpaper.plist

Run the task immediately, regardless of the file time Settings
launchctl start me.dynamic.wallpaper.plist
Copy the code

If all is well, the wallpaper will automatically change every hour after the load is finished. Also, Lauchctl has one advantage over Crontab: if your computer doesn’t trigger a task while it’s working, it will run the task once you restart the computer.

This application scenario is closed out my computer screen, for example, next time when I open it, no matter what time, as long as I turn the screen it will update my wallpaper, can avoid you turned on the computer results in the morning in the middle of the night you wallpaper shows a 3 PM the wallpaper of a bright sun screen to give off the trouble people.

That’s all for today