用Applescript 實現(xiàn)自定義的動態(tài)壁紙

用Applescript 實現(xiàn)自定義的動態(tài)壁紙

1. 動態(tài)壁紙 Dynamic Wallpaper

講到在蘋果上整動態(tài)壁紙,就得先聊聊他自家的方案。最早蘋果在macOS Mojave 里引入了這個概念,基于每天的不同時段去變化桌面的壁紙。其所用的技術(shù)是在設(shè)置壁紙時,用一個帶有時間信息的Heic 格式的圖片去設(shè)置成壁紙,里面包含了多張的tiff 圖片及時間信息。到了時間就切換一下里面應(yīng)用的圖片。這個技術(shù)整挺好,又不占用資源又實用。有那么段時間你甚至可以自已做這樣的圖片去實現(xiàn)這樣的功能,但現(xiàn)在,在Big Sur 上是不可能的啦。因為壁紙目錄在 /System/Library/Desktop\ Pictures 這里。整個系統(tǒng)目錄是只讀的,所以你是不能自已加的。

講到這里,能實現(xiàn)這個功能的 “官方渠道” 就已經(jīng) “此路不通” 了。得另想辦法。

在查找資料前我就想著有沒有可能用腳本去做這個事,畢竟Mac 是Unix 系的東西。有沒有可能可以用Bash 腳本 加一些事件勾子來實現(xiàn)動態(tài)壁紙呢。

經(jīng)查找,可以是可以的,但和想象中的有一點點不一樣。

可以使用Applescript 來做,并用Launchctl 來實現(xiàn)定時調(diào)用。理論上來說應(yīng)該也可以用Crontab+Bash 來實現(xiàn)調(diào)用,但在最新的系統(tǒng)上Cron 好像沒啥作用。即使給了全盤文件的訪問權(quán)限也不行。暫估計是因為蘋果的安全設(shè)計導(dǎo)致的。另外用Lauchctl 有Cron 所沒有的好處。下面再詳細(xì)說。如果你是Linux 類的機器那估計是可以用Crontab+Bash 實現(xiàn)這個效果的。但我沒試??

2. Applescript

那么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.

上面是蘋果開發(fā)官網(wǎng)的介紹?;旧峡梢岳斫獬伤褪翘O果系統(tǒng)下的一個專門為蘋果量身定制的腳本語言。

在有寫其他語言的基礎(chǔ)下,Applescript 的學(xué)習(xí)成本倒是不高。而且它非常類似英語的自然語言。所以總體上說還挺好學(xué)的。就是沒有IDE 有點?? 系統(tǒng)自帶有個Applescript 編輯器(Script Editor),可以說基本沒有Windows 下的記事本好用就是了。我學(xué)基本語法的時候就有過腳本的高亮卡Bug 了的情況,寫著寫著就不能寫了。但是由于Applescript 不能用Vim 之類的編輯器打開所以也沒啥選擇。

在開始前我們需要準(zhǔn)備好壁紙文件。我的想法是24小時每個小時變一次。一天由24張不一樣的壁紙組成。你可以自已在一個地方定機定時拍攝一組圖片或者在網(wǎng)上尋找別人的作品來做。

這里我是把文件放在了家目錄下的圖片里:

# Display X 就是指給第X個顯示器用的。
# 圖片名就是具體的小時數(shù)。
~/Pictures/Wallpapers/Display1/01.jpg

像這樣:

我們要用到的腳本如下:

(*

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

下面我一段一段講一下功能:

set useSameWallpaper to false

這句是個變量,如果你想在所有的顯示器上都用同一組圖片則可以改成true. 我想要每個都不一樣所以我用了false.

set currentPhoto to hours of (current date) as string

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

然后我們獲取到當(dāng)前的系統(tǒng)時間的小時數(shù),如果小時數(shù)的全長不到2位數(shù)就補全成2位,比如是兩點鐘就會是“02”,而不是“2”。

然后接下來我們用系統(tǒng)事件的方式,給廣播不同的設(shè)置圖片的事件。

tell every desktop

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

    set picture to POSIX file wallpaper

end tell

如果是要全部顯示器都顯示同一組圖片的。這里會全部采用第一組圖片。

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

這里我們獲取到所有的顯示器實例。并按先前準(zhǔn)備好的圖片路徑對每個不同的顯示器設(shè)置不同的圖片。

大致上,到這腳本就準(zhǔn)備好了。如果有圖片資源就可以試著手動跑一下了。在Applescript 編輯器里面直接運行就可以了。自帶的編輯器叫Script Editor. 用Spotlight 就能找到。

或者你已經(jīng)保存了腳本的話,也可以直接在命令行里用命令運行。

osascript ~/Pictures/Wallpapers/Wallpaper.scpt

如果運行有問題可以加個 log xxx 就可以打印日志調(diào)試。

現(xiàn)在我們有了圖片和腳本。接下來就是要讓他自已動起來??偛荒芪覀?nèi)斯さ馗粢欢螘r間就開個編輯器運行一下吧????

3. Launchctl

那么Lauchctl 是什么呢?

Launchctl 是Mac OS X 10.4 以后引進的一個統(tǒng)一的服務(wù)管理框架,可以啟動、停止和管理守護進程、應(yīng)用程序、進程和腳本等。他是通過plist 配置文件來指定執(zhí)行周期和任務(wù)的。

主要的放置plist 的地方有:

~/Library/LaunchAgents           # 當(dāng)前用戶定義的任務(wù)
 /Library/LaunchAgents           # 系統(tǒng)管理員定義的任務(wù)
 /Library/LaunchDaemons          # 管理員定義的系統(tǒng)守護進程任務(wù)
 /System/Library/LaunchAgents    # 蘋果定義的任務(wù)
 /System/Library/LaunchDaemons   # 蘋果定義的系統(tǒng)守護進程任務(wù)

如果你熟悉Crontab, 那總體上它們就是類似的。plist 文件的可設(shè)置內(nèi)容很多,用的是xml 語言。如果有興趣可以自行了解更多,下面我只講下我們在這個例子中需要用到的設(shè)置項。

我們到 ~/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唯一的標(biāo)識 -->
    <key>Label</key>
    <string>me.dynamic.wallpaper.plist</string>

    <!-- 指定要運行的腳本 -->
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/osascript</string>
        <string>/Users/pulsgarney/Pictures/Wallpapers/Wallpaper.scpt</string>
    </array>

    <!-- 指定運行的時間 -->
    <key>StartCalendarInterval</key>
    <dict>
        <key>Minute</key>
        <integer>0</integer>
    </dict>
</dict>
</plist>

上面我們這個文件定義了我們用osascript 去跑我們前面寫好的腳本。每個小時的第1分鐘開始時就跑一次,也就是一天24次。如果你的腳本有問題不能正常運行可以加上下面這兩句打下日志以方便調(diào)試。

    <!-- 標(biāo)準(zhǔn)輸出文件 -->
    <key>StandardOutPath</key>
    <string>/Users/pulsgarney/Pictures/Wallpapers/log/output.log</string>

    <!-- 標(biāo)準(zhǔn)錯誤輸出文件,錯誤日志 -->
    <key>StandardErrorPath</key>
    <string>/Users/pulsgarney/Pictures/Wallpapers/log/error.log</string>

如果你想要它刷新的頻率更高,可以加上這句讓它定時刷新,單位為秒:

    <!-- 時間間隔 -->
    <key>StartInterval</key>
    <integer>300</integer>

接下來,我們就可以在命令行下加載這個任務(wù)了。

# 加載任務(wù)
launchctl load me.dynamic.wallpaper.plist
# 卸載任務(wù)
launchctl unload me.dynamic.wallpaper.plist

# 不管文件的時間設(shè)置,馬上運行一次任務(wù)
launchctl start me.dynamic.wallpaper.plist

如果一切正常,那么在load 完后,每個小時都會自動更換壁紙。而且,用Lauchctl 比Crontab 有優(yōu)勢的一點就是:在你電腦沒有在工作時所觸發(fā)的任務(wù)它會在你重新運行電腦后整合成一個任務(wù)跑一次。

這個應(yīng)用場景主要是比如我用完了電腦合上了屏幕,下次我打開它時,無論什么時間,只要我屏幕一翻開它就會更新我的壁紙,可以避免你半夜凌晨打開電腦結(jié)果你壁紙顯示的是下午兩三點大太陽的壁紙一亮屏就把人給送走了的煩惱。

今天就聊到這,掰~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容