Saturday, July 26, 2025

Mint MATE Monitor Brightness

I ran into a rare but not unheard of problem this morning while working on my desktop computer (running Linux Mint with the MATE desktop, and using a Dell monitor). Due to a somewhat funky arrangement of solar position, clouds, and possibly other celestial entities, the natural light behind my monitor caused a glare that made my eyes hurt a bit and caused me to have trouble seeing the screen. (Some what I guess you might call after-images were messing with my vision.) To reduce the glare, I wanted to dial down the monitor brightness ... but could not figure out how. The buttons on the Dell monitor are unlabeled, and I was not overly excited about a bunch of trial-and-error button pushing. So I naturally went to the system's display controls ... which did not have a brightness setting.

When I had some free time, I started searching the web for how to adjust display brightness in MATE, where to find GUI tools or applets for display brightness, and so on. I found lots of seeming helpful posts that either (a) referred to controls that do not exist in my operating system, despite allegedly being specific to MATE and possibly to MATE on Linux Mint or (b) pointed me to an applet that did not work (in some cases possibly because it only works on laptops for some reason?).

So, bottom line, I eventually wrote a bash script with a primitive GUI to let me futz with the display brightness. It uses the xrandr  and zenity commands, either or both of which may need to be installed. (You can run "which xrandr" and "which zenity" in a terminal to see if you have them.) Once you have them, run "xrandr" in a terminal with no options to find out the name of your display (DP-2 in my case). Substitute that for DP-2 in the following script (and remember to make it executable with "chmod +x <your script>.sh", and you should be in business.

#!/bin/bash

# Adjust display brightness (1.0 being the default brightness).
# You can get the monitor name (DP-2 here) by running 'xrandr' in a terminal.

target=$(zenity --entry \
                --title="Set Display Brightness" \
                --text="Set a brightness level (base value = 1.0):" \
                --entry-text="1.0")
xrandr --output DP-2 --brightness $target
zenity --info --text="Click OK to close the terminal."


Monday, July 14, 2025

A Shinyvalidate Hack

Lately I've been coding a Shiny web application (in R) in which users are confronted by several forms. Since their inputs go into a database, some amount of input validation seems prudent (to put it mildly). I came across the shinyvalidate package, which is proving very useful. You can specify a variety of rules for input fields (starting with whether they are required and moving on to various filters on what is allowed). If the input fails to meet the validation rules, messages are printed in red under the input controls (something you've probably seen before if you ever tried to submit a web form with something missing or glaringly incorrect).

The remainder of this post probably won't make much sense unless you have some experience with shinyvalidate. (I'm not promising it will make sense if you do.) I ran into a bit of a snag with a few input fields where the validation rules involved a disjunction. In one case the fields was the URL of an organization's web site, and in the other it was their contact email address. Both fields are "required" in my application, with required in quotes because it is possible for an organization not to have a web site and/or not to have a contact email address. (For instance, some organizations have web sites but no email address, expecting people to use a contact form on their home page.) The approach I'm taking is to allow "none" as a valid response for both web and email addresses if there is none. So I want to enforce the rule that the input value is either "none" or a valid address.

The shinyvalidate package provides mechanisms for enforcing conjunctions of rules (satisfy all of these requirements) but apparently does not have an explicit mechanism for enforcing disjunctions (either this or that). It does let you create custom functions to validate inputs, but I wanted to use their built-in web (sv_url()) and email (sv_email()) functions so that I would not have to go down the regular expression rabbit hole. That meant writing a function that combined a simple test (x != "none", where x is the value submitted in a text field of the form) with their functions.

It took me a while to figure out that while sv_url and sv_email take a few arguments (including an optional customized error message), they do not actually take the form input (what I'm calling x) as an argument. Instead,  the output value of sv_url() or sv_email() is itself a function with the form input as its sole argument. Once that sank in, making the custom validators was trivial. Here is my URL validator.

urlOrNone <- function(x) {
  if (x != "none") sv_url("Please enter a valid URL, including the http/https prefix.")(x)

If x either equals "none" or satisfies the sv_url validator, the return value is NULL, which allows the input to pass validation. Otherwise, the user gets the custom error message and the input is disallowed. 

Tuesday, July 8, 2025

Android Silliness Part II

Last year I documented at great length a mess I went through when a very straightforward morning radio alarm I had set on my bedroom smart speaker had to be replaced by a Google "automation". That post ended with my having successfully implemented a solution.

Well, that was then and this is now. Google recently introduced Android 16 and I recently upgraded my phone from a Pixel 6a to a Pixel 9a. One or both of those events killed my morning alarm. Instead of hearing Google's voice telling me "streaming NPR on WKAR" (my local NPR radio station), I heard "OK, here's a playlist from YouTube Music" followed by some noises that I suspect are used to soften up presumed terrorist before interrogating them.

This was baffling in several ways, starting with the fact that I have never, ever instructed Google to play random music from YouTube Music early in the morning. More baffling is that when I went into the Google automation settings, my morning routine was still there, still marked enabled, and still listed as doing the same things: playing the radio (station = WKAR FM) on the bedroom speaker. Manually triggering it, however, did not work.

I have no idea what the problem was (is), but I eventually found a work around. I changed the "action" setting from playing the radio (one of a menu of possibilities controlled by a multiple select input) to a "custom" action (selected via "Try adding your own (Experiment with custom actions)". That opens a text input where you can type pretty much anything you might verbally ask Google Assistant to do. In my case that meant "Stream WKAR FM radio". To date, that has worked, which I assume means Google has engineers working on a fix for it.

If any Google engineers are reading this, may I recommend consulting the "Redneck Repair Manual" (page 1): "If it ain't broke, don't fix it."