こんにちは、今回はちょっと珍しく作ってみた系のブログになります。
デスクトップの背景ってずっと同じだと飽きてきますよね。ただ頻繁に変えるのもめんどくさいです。
Steamとかには定期的に変えてくれるソフトがあったりしますが、なんかできそうな気がしたので自分で実装してみることにしました。
仕様
- Go(version 1.21)で実装する。
- フォルダを指定して、そこにある画像ファイルを定期的にデスクトップの背景に変更する。
- 2回連続で同じ画像は使用しない。
- Windowsで動作する。
Goを選んだ理由はGoを使いたいからです。それ以外は適当にほしい要素を入れました。
実装
以下が実際のコードになります。
package main
import (
"fmt"
"io/fs"
"os"
"os/signal"
"path/filepath"
"time"
"github.com/go-co-op/gocron/v2"
"github.com/reujab/wallpaper"
)
var envName = "bg"
func main() {
path, err := os.LookupEnv(envName)
if !err {
fmt.Printf("Env %s is not found.\n", envName)
os.Exit(1)
}
files, _ := os.ReadDir(path)
s, _ := gocron.NewScheduler()
// add a job to the scheduler
s.NewJob(
gocron.DurationJob(time.Hour),
gocron.NewTask(
func(dir []fs.DirEntry, base string) {
background, _ := wallpaper.Get()
index := 0
for i, file := range dir {
if file.Name() == filepath.Base(background) {
index = i + 1
break
}
}
wallpaper.SetFromFile(filepath.Join(base, dir[(index)%len(dir)].Name()))
wallpaper.SetMode(wallpaper.Crop)
},
files,
path,
),
)
// start the scheduler
s.Start()
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt)
<-stop
// when you're done, shut it down
s.Shutdown()
}
デスクトップの背景を変更するのはWindowsのAPI触ったりするのかなと思ってたら、"github.com/reujab/wallpaper"を使うと想像の10倍ぐらい簡単にできました。
何気に苦労したのが定期的に変更の部分で、無限ループとsleepでやってもいいのですがあんまりスマートじゃないのかなと思ったので"github.com/go-co-op/gocron/v2"というモジュールでやってみることにしました。
似たようなモジュールはいくつかあったのですが、実行時に引数を渡せるものがなかなか見つからなくて苦労しました。
ともかく、これでbgという環境変数で指定したフォルダに存在するファイルを順番に、1時間ごとに変更することができるようになりました。
go.modは省略してるので実際にこのコードでビルドする際は
go mod init プロジェクト名
go mod tidy
でモジュールをインストールしておいてください。
ビルドのコマンドは
go build -ldflags -H=windowsgui main.go
を使うとexeを実行したときにウインドウが出なくて済むのでおすすめです。
自動実行
ビルドされたバイナリのexeファイルは
%USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
に入れておけばログオンした際に自動で起動されます。
引数等が必要ない実行可能型式のファイルであれば、タスクスケジューラに登録するよりもこっちの方がお手軽でいいですね。
最後に
無事にデスクトップ背景のスライドショーを実現することができました。
ただ、当然といえば当然ですが動画等はデスクトップ背景にはできないので、それらがあるフォルダを指定すると真っ黒になってしまう場合があるので気をつけてください。
1時間毎に画像を変更する処理は、定期実行だからcronでしょ!と適当にモジュールを探したのですが、せっかくGoを使っているのでgoroutineとかchannelとかをうまく使えば、もっときれいにかけるんですかね。
できそうなら気が向いたときにごっそり書き直すかもしれません。
あとおまけで、画像ファイルのパス周りで区切り文字をハードコーディングせずにモジュールに任せているので、適切にビルドすればたぶんMacとかのWindows以外でも動くと思われます。