Last active
May 26, 2018 02:52
-
-
Save qubbit/23c230e406ddb8553f58fb25b764e48c to your computer and use it in GitHub Desktop.
Periodically download images and set them as wallpaper from Unsplash
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.Win32; | |
using System; | |
using System.IO; | |
using System.Net; | |
using System.Runtime.InteropServices; | |
using System.Windows.Forms; | |
using System.Linq; | |
using System.Collections.Generic; | |
using System.ComponentModel; | |
using System.Dynamic; | |
// 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 command line args: | |
// time = minutes (how often to change the background image) | |
// category = search terms to find your desired type of wallpaper | |
// fit = wallpaper fit, one of fill, fit, span, tile, center, stretch | |
// Example: | |
// unsplash.exe time=60 category=nature,scenary fit=stretch | |
// 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 string IMAGE_DIR_NAME = "Unsplash"; | |
const string SEARCH_URL_TEMPLATE = "http://source.unsplash.com/{0}x{1}/?{2}"; | |
static string url; | |
static FileLogger logger = new FileLogger(); | |
static uint timerCallCount = 0; | |
public static string imageDownloadDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, IMAGE_DIR_NAME); | |
static dynamic ParseCommandLine(string[] args) { | |
var typeDictionary = new Dictionary<string, Type>() { | |
{ "time", typeof(int)}, | |
{ "category", typeof(string)}, | |
{ "fit", typeof(Wallpaper.Style)} | |
}; | |
dynamic o = new ExpandoObject(); | |
var options = (IDictionary<string, object>)o; | |
foreach (var x in args) { | |
var segments = x.Split('='); | |
var key = segments[0]; | |
var value = segments[1]; | |
var converter = TypeDescriptor.GetConverter(typeDictionary[key]); | |
var result = converter.ConvertFrom(value); | |
options.Add(key, result); | |
} | |
return o; | |
} | |
static dynamic options; | |
static void Main(string[] args) { | |
SetAppBasePath(); | |
logger.Log("Application started"); | |
if (args.Length < 3) args = new string[] { "time=15", "category=cities", "fit=stretch" }; | |
options = ParseCommandLine(args); | |
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, options.category); | |
int intervalMilliseconds = options.time * 60 * 1000; | |
new System.Threading.Timer(Tick, null, 0, intervalMilliseconds); | |
while (true) System.Threading.Thread.Sleep(1000); | |
} | |
private static void SetAppBasePath() { | |
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, options.fit); | |
} | |
} | |
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 = Program.imageDownloadDir + "\\" + 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 | |
} | |
private static Dictionary<Style, Tuple<string, string>> wallpaperStyles = new Dictionary<Style, Tuple<string, string>> { | |
{ Style.Fill, new Tuple<string, string>("10", "0") }, | |
{ Style.Fit, new Tuple<string, string>("6", "0") }, | |
{ Style.Span, new Tuple<string, string>("22", "0") }, | |
{ Style.Stretch, new Tuple<string, string>("2", "0") }, | |
{ Style.Tile, new Tuple<string, string>("0", "1") }, | |
{ Style.Center, new Tuple<string, string>("0", "0") } | |
}; | |
public static void Set(string filename, Style style) { | |
RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Control Panel\Desktop", true); | |
var reg = wallpaperStyles[style]; | |
key.SetValue("WallpaperStyle", reg.Item1); | |
key.SetValue("TileWallpaper", reg.Item1); | |
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, filename, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment