1. Dynamic Wallpaper
When it comes to the whole dynamic wallpaper on apple, we have to talk about his own scheme first. Apple first introduced this concept in macOS Mojave, which changes the desktop wallpaper at different times of the day. The technology used is to set the wallpaper with a Heic format picture with time information, which contains multiple tiff pictures and time information. When it's time, switch the pictures in the application. This technology is very good, does not occupy resources and is practical. For some time, you can even make such pictures to realize such functions, but now, it's impossible on Big Sur. Because the wallpaper directory is here in / System/Library/Desktop\ Pictures. The whole system directory is read-only, so you can't add it yourself.
At this point, the "official channel" that can realize this function has been "blocked". We have to find another way.
Before looking up the information, I thought about whether it was possible to use scripts to do this. After all, Mac is Unix. Is it possible to use Bash script with some event hooks to realize dynamic wallpaper.
After searching, it can be, but it is a little different from what you think.
You can use Applescript to do this, and use Launchctl to implement timed calls. Theoretically, cronab + bash should also be used to implement the call, but Cron seems to have little effect on the latest system. Even if you give access to the entire file. It is temporarily estimated that it is due to Apple's security design. In addition, using Lauchctl has advantages that Cron does not have. Let's talk about it in detail. If you are a Linux machine, you can use cronab + bash to achieve this effect. But I didn't try 🤔
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 automate repetitive tasks, combine features from multiple scriptable applications, and create complex workflows.
The above is an introduction to Apple's official website. Basically, it can be understood as a script language specially tailored for apple under the apple system.
On the basis of writing other languages, the learning cost of Applescript is not high. And it is very similar to the natural language of English. So on the whole, it's good to learn. It's just that there's no IDE 🌚 The system has an Applescript editor. It can be said that there is no Notepad under Windows. When I learned basic grammar, there was a Bug in the highlight card of the script. I can't write when I write. However, because Applescript cannot be opened with an editor such as Vim, there is no choice.
We need to have the wallpaper ready before we start. My idea is to change every 24 hours. A day consists of 24 different wallpapers. You can take a group of pictures at a fixed time in a place, or look for other people's works on the Internet.
Here I put the file in the picture under the home directory:
# Display X refers to the X-th display. # The picture name is the specific number of hours. ~/Pictures/Wallpapers/Display1/01.jpg
The script we want to 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
Let me talk about the following functions paragraph by paragraph:
set useSameWallpaper to false
This sentence is a variable. If you want to use the same set of pictures on all monitors, you can change it to true. I want each 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
Then we get the hours of the current system time. If the total length of the hours is less than 2 digits, it will be filled into 2 digits. For example, it will be "02" instead of "2" at two o'clock.
Next, we use the system event method to broadcast different events of setting pictures.
tell every desktop set wallpaper to wallpaperPath & "1/" & currentPhoto & ".jpg" set picture to POSIX file wallpaper end tell
If you want all monitors to display the same set of pictures. The first set of pictures will be used 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
Here we get all the display instances. And set different pictures for each different display according to the previously prepared picture path.
By and large, the script is ready. If you have picture resources, you can try to run it manually. Just run it directly in the Applescript editor. The built-in editor is called Script Editor. You can find it with Spotlight.
Or if you have saved the script, you can run it directly from the command line.
If there is a problem with the operation, you can add a log xxx to print the log debugging.
Now we have pictures and scripts. The next thing is to make him move. We can't manually open an editor and run it every once in a while 🤣🤣
So what is Lauchctl?
Launchctl is a unified service management framework introduced after Mac OS X 10.4. It can start, stop and manage daemons, applications, processes and scripts. It specifies the execution cycle and tasks through the plist configuration file.
The main places to place plist are:
~/Library/LaunchAgents # Current user-defined task /Library/LaunchAgents # System administrator defined tasks /Library/LaunchDaemons # Administrator defined system daemon tasks /System/Library/LaunchAgents # Apple defined tasks /System/Library/LaunchDaemons # Apple defined system daemon tasks
If you are familiar with Crontab, they are similar in general. There are many settable contents in plist file, which uses xml language. If you are interested, you can learn more by yourself. Next, I will only talk about the settings we need in this example.
Let's create a new file under ~ / Library/LaunchAgents:
<!-- ~/Library/LaunchAgents/me.dynamic.wallpaper.plist --> <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <!-- Label Unique identification --> <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 when to run --> <key>StartCalendarInterval</key> <dict> <key>Minute</key> <integer>0</integer> </dict> </dict> </plist>
The above file defines that we use osascript to run the script we wrote earlier. Run once at the beginning of the first minute of each hour, that is, 24 times a day. If your script has problems and can't run normally, you can add the following two sentences to make a log for 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>
If you want it to refresh more frequently, you can add this sentence to refresh it regularly. The unit is seconds:
<!-- time interval --> <key>StartInterval</key> <integer>300</integer>
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 once, regardless of the time setting of the file launchctl start me.dynamic.wallpaper.plist
If everything is normal, the wallpaper will be automatically changed every hour after load ing. Moreover, the advantage of using launchctl over cronab is that when your computer does not have the task triggered when it is working, it will be integrated into a task to run once after you re run the computer.
This application scenario is mainly for example, when I use up the computer and close the screen, the next time I open it, whenever I open the screen, it will update my wallpaper, which can avoid the trouble that you open the computer in the middle of the night and the morning. As a result, your wallpaper shows that the wallpaper in the sun at two or three o'clock in the afternoon will send people away as soon as the screen is on.
That's all for today. Break it~