1 Week Later
This should be the last retro-active post. The next post will be my “current” status post! Most of the work is the invisible back-end stuff. The UI has made some progress toward where I need it to be but there’s a whole lot of bugs and quirks that need to be sorted out.
I finally have the PAHO MQTT integration working how I want. I’ve tested out sending commands from a separate machine and receiving the subscribed topic/payload on the c# client.
Nothing revolutionary with the UI here. Device name is inserted into the topic at first level. This allows one to take the same config from one machine, change the device name, connect, and have a whole new set of topics so that machine can be controlled separately.
Beyond that you’ve just got the basic broker IP/port and authentication fields. Currently it’s set up to require authentication via username but I do hope to eventually incorporate the ability to use SSL cert instead (I’ll consider a no-authentication setting if someone really needs it but honestly think that’s a terrible idea).
Connect locks the fields so they cannot be edited (assuming it’s able to make a connection). I still don’t have UI set-up to indicate when connection fails - currently it just flickers for a second and then the connect button re-appears. (Obviously fake IP displaying but that is connected to the actual IP, etc.)
Non-UI MQTT Functionality
I’ve built in all the desired media control functionality (vol up, vol dwn, mute, play/pause, stop, track next, track prev). None of this is currently exposed via UI. I’ve just got some test topics that are auto subscribed on connect. Publishing to the topic triggers the event. Currently volume isn’t accepting payload (easy to code but just wanted to isolate and flesh out the mqtt stability).
Everything is surprisingly fast! It makes me question why there is so much latency in off the shelf IOT given that I’m getting so little latency it’s unnoticable from pressing pause on phone to having audio pause on the PC. Started off with simple test publishes and then built a simple media control interface in Home Assistant. Notice the “Show Volume OSD” - currently I can get this to be toggleable for vol up, dwn, and mute but not for play/pause, stop, or track next/prev. Fortunately not showing OSD for volume is really all I wanted to target anyway.
All of these buttons are simply publishing empty payloads to topics such as “COMPUTER-NAME/play” or “COMPUTER-NAME/vol-up” (which will eventually accept a numeric payload from 0-100 as well to allow for something like MAX-VOL buttons using the same topic publish).
Here are some screenshots below to help further clarify what exactly what I mean by not showing the OSD on volume controls. These are actually separate topics (“COMPUTER-NAME/vol-up-osd” vs “COMPUTER-NAME/vol-up” for example). Home Assistant toggle is just changing which topic is being published to.
Whenever you use the keyboard controls to change your volume on Windows 10 you most likely have noticed this little volume control display. When the vol-up-osd topic is used, the c# app sends keyboard commands same as your keyboard volume control which displays this OSD. While this was a controversial UI decision from M$ that has left tons of people trying to figure out how to make it go away forever, there are honestly situations where I don’t mind it (it actually will also show the “now playing” card info for media that sends the metadata to windows).
While this honestly can be useful in certain situations, there’s also situations where it is really really undesirable. Consider a virtual pinball cabinet or a dedicated arcade machine where you’re going out of your way to create the illusion that this fun stuff is all magic free of the typical computer UI. You may even have a rotated display configured such that the volume UI will display rotated.
So by having a separate topic without the OSD, I was able to hook directly into Windows Core Audio API and implement the bare minimum set of COM interfaces necessary to directly control volume level and mute status for the active audio device. Manipulating this directly vs. sending the key-press for volume controls will not display the windows metro style audio UI. This allows a best of both worlds situation!
Updated Controls Tab
MQTT media functionality aside, I did re-design the control layout for the UI. I made the interface collapsible, added some basic sort controls, added a status indicator, and ensured there were Enable/Disable and Delete buttons available. Also I styled the form controls as much as possible out-the-box to be darker. Those stupid dropdown buttons are not stylable without user custom paint and I don’t feel like mucking around with that at this point.
The control Enable button serves for validation. For example, duplicate topics/paths are forbidden. Also obviously you can’t have a control with no key actually selected so it will pop up a window alert saying “please select a key” (or “please enter a topic” if one is not present, etc.).
The validation layer tries it’s best to “make it work” when it comes to key mods. The way the UI works, you can select up to 3 modifiers + the actual control key. Modifiers can be pressed by themselves if there’s a need such as just pressing ctrl vs. doing ctrl+c. Since you select the number of mods and they appear blank by default if you were to select 3 mods but only populate 2, it will scrunch it together for you, change the # of mods, and enable. This seems better than harassing users needlessly.
Despite the progress there’s still a tone of work to go. Adding controls works correctly and there’s intelligent numbering, dictionaries being used to ensure resources are released properly / no memory leaks or resources held over. BUT tab indexing isn’t being dynamically assigned correctly yet so I do need to work on implementing that. Likewise, obviously controls should all lock down once enabled to simplify that whole workflow (vs. subscribing and un-subscribing from topics every time a user types a key into path or trying to use focus which involves other potential issues).
Saving the control sets is still a work in progress as well. They’re currently saving to XML fine but there’s some sort issues on saving that need to be addressed. I think I’m actually going to have to change from System.XML to the System.XML.LINQ as it will make the sorting procedures a lot easier to ensure sort order is saved corretly when items are deleted, etc. without needing to over-complicate the storage procedures.
That being said, it’s starting to become “almost functional” at this point. There’s only a few steps left until I can get a usable test build running for personal daily use while I work on developing out more of the desired functionality!