Skip to content

Instantly share code, notes, and snippets.

@qubbit
Last active May 26, 2018 02:52
Show Gist options
  • Select an option

  • Save qubbit/23c230e406ddb8553f58fb25b764e48c to your computer and use it in GitHub Desktop.

Select an option

Save qubbit/23c230e406ddb8553f58fb25b764e48c to your computer and use it in GitHub Desktop.
Periodically download images and set them as wallpaper from Unsplash
using Microsoft.Win32;
using System;
using System.Drawing;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Linq;
// A program that will periodically download an image from Unsplash and
// change your Windows desktop background to the downloaded image
// Compilation: csc /out:unsplash.exe /t:winexe .\Program.cs /nologo /o
// After compilation, drop the executable in a folder and run it with some command line args
// args[0] = minutes (how often to change the background image
// args[1] = search terms to find your desire type of wallpaper
// Example invocation:
// unsplash.exe 60 nature,scenary
// This will change the wallpaper every hour from category of nature and scenary
namespace Unsplash {
// Very simple logger implementation with a lock!
public class FileLogger {
protected readonly object locker = new object();
const string LOG_FILE_PATH = "application.log";
const bool ALSO_LOG_TO_STDOUT = true;
public void Log(string message) {
lock (locker) {
using (var streamWriter = new StreamWriter(LOG_FILE_PATH, append: true)) {
var line = string.Format("{0} \t {1}", DateTime.Now.ToString("MM/d/yyyy hh:mm:ss tt zzzz"), message);
streamWriter.WriteLine(line);
if (ALSO_LOG_TO_STDOUT) Console.WriteLine(line);
}
}
}
}
class Program {
const int ONE_HOUR_MS = 60 * 60 * 1000;
const int FIFTEEN_MINUTES_MS = ONE_HOUR_MS / 4;
const string IMAGE_DIR_NAME = "Unsplash";
const int DEFAULT_SEARCH_INTERVAL_MINUTES = 15;
const string DEFAULT_SEARCH_CATEGORY = "nature,scenary,landmarks";
// Arg 0 = width, Arg 1 = height, Arg 2 = search terms (comma separated)
const string SEARCH_URL_TEMPLATE = "https://source.unsplash.com/{0}x{1}/?{2}";
static string url;
static FileLogger logger = new FileLogger();
static uint timerCallCount = 0;
static void Main(string[] args) {
SetAppBasePath();
logger.Log("Application started");
if (args.Length < 2) {
logger.Log(String.Format("Setting default arguments since no arguments were specified. Interval = {0} minutes, search category = {1}",
DEFAULT_SEARCH_INTERVAL_MINUTES, DEFAULT_SEARCH_CATEGORY));
args = new string[] { DEFAULT_SEARCH_INTERVAL_MINUTES.ToString(), DEFAULT_SEARCH_CATEGORY };
}
var searchTerms = args[1];
var screenBounds = Screen.AllScreens.Where(x => x.Primary).First().Bounds;
logger.Log("Primary screen bounds: " + screenBounds.ToString());
url = string.Format(SEARCH_URL_TEMPLATE, screenBounds.Width, screenBounds.Height, searchTerms);
if (int.TryParse(args[0], out int interval)) {
interval *= 60 * 1000; // convert minutes to milliseconds
if (interval < FIFTEEN_MINUTES_MS) interval = FIFTEEN_MINUTES_MS;
}
else {
interval = ONE_HOUR_MS;
}
new System.Threading.Timer(Tick, null, 0, interval);
while (true) System.Threading.Thread.Sleep(1000);
}
private static void SetAppBasePath() {
string imageDownloadDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, IMAGE_DIR_NAME);
if (!Directory.Exists(imageDownloadDir)) { Directory.CreateDirectory(imageDownloadDir); }
Directory.SetCurrentDirectory(imageDownloadDir);
}
private static void Tick(object state) {
string imageFileName = ImageDownloader.Download(url);
var logMessage = string.Format("Tick count: {0}. Setting wallpaper to {1}", ++timerCallCount, imageFileName);
logger.Log(logMessage);
Wallpaper.Set(imageFileName, Wallpaper.Style.Fill);
}
}
class ImageDownloader {
private static string Extension(string mimeType) {
switch (mimeType) {
case "image/jpeg":
return ".jpg";
case "image/png":
return ".png";
default:
return "";
}
}
public static string Download(string url) {
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var request = (HttpWebRequest)WebRequest.Create(url);
var response = (HttpWebResponse)request.GetResponse();
var responseUri = response.ResponseUri;
string imageFileName = new FileInfo(response.ResponseUri.LocalPath).Name + Extension(response.ContentType);
using (Stream receiveStream = response.GetResponseStream())
using (Stream outputStream = File.OpenWrite(imageFileName)) {
byte[] buffer = new byte[4096];
int bytesRead;
do {
bytesRead = receiveStream.Read(buffer, 0, buffer.Length);
outputStream.Write(buffer, 0, bytesRead);
} while (bytesRead != 0);
}
return imageFileName;
}
}
public sealed class Wallpaper {
const int SPI_SETDESKWALLPAPER = 20;
const int SPIF_UPDATEINIFILE = 0x01;
const int SPIF_SENDWININICHANGE = 0x02;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);
public enum Style : int {
Fill,
Fit,
Span,
Tile,
Center,
Stretch
}
public static void Set(string filename, Style style) {
Image img = Image.FromFile(filename);
string tempPath = Path.Combine(Path.GetTempPath(), "wallpaper.bmp");
img.Save(tempPath, System.Drawing.Imaging.ImageFormat.Bmp);
RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Control Panel\Desktop", true);
if (style == Style.Fill) {
key.SetValue(@"WallpaperStyle", "10");
key.SetValue(@"TileWallpaper", "0");
}
if (style == Style.Fit) {
key.SetValue(@"WallpaperStyle", "6");
key.SetValue(@"TileWallpaper", "0");
}
if (style == Style.Span) // Windows 8 or newer only!
{
key.SetValue(@"WallpaperStyle", "22");
key.SetValue(@"TileWallpaper", "0");
}
if (style == Style.Stretch) {
key.SetValue(@"WallpaperStyle", "2");
key.SetValue(@"TileWallpaper", "0");
}
if (style == Style.Tile) {
key.SetValue(@"WallpaperStyle", "0");
key.SetValue(@"TileWallpaper", "1");
}
if (style == Style.Center) {
key.SetValue(@"WallpaperStyle", "0");
key.SetValue(@"TileWallpaper", "0");
}
SystemParametersInfo(SPI_SETDESKWALLPAPER,
0,
tempPath,
SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment