From 8b2c9715ae495daac69ef1cede4244d33bf50480 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sat, 13 Sep 2025 15:00:39 +0000 Subject: [PATCH 1/5] feat: Add option to display photo location from EXIF data This commit introduces a new feature to the screensaver that allows the user to display the geographical location of a photo. The key changes include: - A new utility method in `Utils.cs` to perform reverse geocoding using the Nominatim OpenStreetMap API. This method converts GPS coordinates (latitude and longitude) from the photo's EXIF data into a human-readable location name. It includes parsing for the DMS format. - The `Monitor.cs` file is updated to call this new utility. When a photo with GPS data is displayed, its location is fetched and passed to the frontend. - A new checkbox is added to the configuration screen (`config.html`) allowing users to enable or disable this feature for each monitor. - The screensaver display (`monitor.html` and `monitor.js`) is updated to include a new element that shows the location information when it's available and the setting is enabled. --- RPS 4/Monitor.cs | 7 +++++++ RPS 4/Utils.cs | 39 +++++++++++++++++++++++++++++++++++++++ RPS 4/data/config.html | 1 + RPS 4/data/js/monitor.js | 5 +++++ RPS 4/data/monitor.html | 1 + 5 files changed, 53 insertions(+) diff --git a/RPS 4/Monitor.cs b/RPS 4/Monitor.cs index 62bf5dd..1a34a97 100644 --- a/RPS 4/Monitor.cs +++ b/RPS 4/Monitor.cs @@ -97,6 +97,7 @@ public Monitor(IntPtr previewHwnd, int id, Screensaver screensaver): this(id, sc public void defaultShowHide() { this.InvokeScript("setBackgroundColour", new string[] { Convert.ToString(this.screensaver.config.getPersistant("backgroundColour")) }); this.InvokeScript("toggle", new string[] { "#quickMetadata", Convert.ToString(this.screensaver.config.getPersistantBool("showQuickMetadataM" + (this.id + 1))) }); + this.InvokeScript("toggle", new string[] { "#location", Convert.ToString(this.screensaver.config.getPersistantBool("showLocationM" + (this.id + 1))) }); this.InvokeScript("toggle", new string[] { "#filename", Convert.ToString(this.screensaver.config.getPersistantBool("showFilenameM" + (this.id + 1))) }); this.InvokeScript("toggle", new string[] { "#filename .root", Convert.ToString(this.screensaver.config.getPersistantBool("showPathRoot")) }); this.InvokeScript("toggle", new string[] { "#filename .subfolders", Convert.ToString(this.screensaver.config.getPersistantBool("showPathSubfolders")) }); @@ -440,6 +441,12 @@ public void readMetadataImage() { } if (rawMetadata != null && rawMetadata != "") { this.quickMetadata = new MetadataTemplate(rawMetadata, Utils.HtmlDecode(this.screensaver.config.getPersistantString("quickMetadata"))); + if (this.quickMetadata.metadata.ContainsKey("gpslatitude") && this.quickMetadata.metadata.ContainsKey("gpslongitude")) { + string location = Utils.GetLocationFromGps(this.quickMetadata.metadata["gpslatitude"], this.quickMetadata.metadata["gpslongitude"]); + if (location != null) { + this.imageSettings["location"] = location; + } + } this.imageSettings["metadata"] = this.quickMetadata.fillTemplate(); } this.imageSettings["mediatype"] = "image"; diff --git a/RPS 4/Utils.cs b/RPS 4/Utils.cs index dc57dbb..516bc77 100644 --- a/RPS 4/Utils.cs +++ b/RPS 4/Utils.cs @@ -11,9 +11,48 @@ using System.Globalization; using System.Collections; using System.Collections.Concurrent; +using System.Net; +using Newtonsoft.Json.Linq; namespace RPS { class Utils { + private static double ConvertDmsToDd(string dms) { + string[] parts = dms.Split(new char[] { ' ', '°', '\'', '"' }, StringSplitOptions.RemoveEmptyEntries); + if (parts.Length >= 3) { + double deg = double.Parse(parts[0], CultureInfo.InvariantCulture); + double min = double.Parse(parts[1], CultureInfo.InvariantCulture); + double sec = double.Parse(parts[2], CultureInfo.InvariantCulture); + return deg + (min / 60.0) + (sec / 3600.0); + } else if (parts.Length == 1) { + return double.Parse(parts[0], CultureInfo.InvariantCulture); + } + return 0; + } + + public static string GetLocationFromGps(string latitudeStr, string longitudeStr) { + if (latitudeStr == null || longitudeStr == null) return null; + try { + double latitude = ConvertDmsToDd(latitudeStr); + double longitude = ConvertDmsToDd(longitudeStr); + + if (latitudeStr.ToUpper().Contains("S")) latitude = -latitude; + if (longitudeStr.ToUpper().Contains("W")) longitude = -longitude; + + string url = $"https://nominatim.openstreetmap.org/reverse?format=json&lat={latitude.ToString(CultureInfo.InvariantCulture)}&lon={longitude.ToString(CultureInfo.InvariantCulture)}&accept-language=en"; + + using (WebClient wc = new WebClient()) { + wc.Headers.Add("User-Agent", "RPS/4.0 (a screensaver)"); // Per Nominatim requirements + string json = wc.DownloadString(url); + JObject data = JObject.Parse(json); + if (data["error"] == null && data["display_name"] != null) { + return (string)data["display_name"]; + } + } + } catch (Exception ex) { + Debug.WriteLine("Error in GetLocationFromGps: " + ex.Message); + } + return null; + } public struct MSG { IntPtr hwnd; uint message; diff --git a/RPS 4/data/config.html b/RPS 4/data/config.html index 54fe275..4947d12 100644 --- a/RPS 4/data/config.html +++ b/RPS 4/data/config.html @@ -473,6 +473,7 @@