Technology Update 2021

@dsteinschneider. Very funny :slight_smile:

Routing table looking more normal:

as is the bindings panel:

I think tomorrow’s job is going to be a clean up of the theme file. Since GuiKit’s theme support is brand new (and despite the fact that I designed it) I’m still learning the best ways to use it. I’ve changed approaches a couple of times and GuiKit and GTL support has been improving since the first parts were written. Now seems like a good time to take advantage of that and clean things up.

12 Likes

As mentioned, today was a major reworking on the theme file. It’s not finished but going well… you can see the current state of it here.

Also, spent about an hour figuring out why one splitter divider was slightly wider than all the others:

And… merged in a bunch of fixes from GuiKit that I’ve been working on at nights and it’s all starting to feel a little more stable.

This has turned into way more work than I thought but I’m getting there slowly and it’ll be worth it once it’s all done.

14 Likes

Today, finished off reworking the theme and now everything except a few edge cases that I’m not going to bother with is now fully vector based. Also, over the weekend more fixes and tuning to GuiKit so it’s getting better and better by the day.

Wiring diagram is now working…

Tomorrow’s job will be show notes and set list grid.

11 Likes

Planned progress for today came true - Set List Grid and Show Notes Panel both up and running again:

10 Likes

More good progress today:

  • Quick Controller Popup
  • Midi Monitor Window
  • Profiler Window

Which means I’m dreading tomorrow’s job - the plugin editor.


8 Likes

How it started / How it’s going:

8 Likes

Today’s job was plugin GUI hosting:

This area has always been complicated by Cantabile’s support for hidpi monitors. When I originally wrote this, Windows 10 only supported upscaling an entire top-level window. For the plugin editor this meant the plugin GUI, Cantabile’s toolbar just above it and the window frame were all in lo-dpi mode when up-scaling was enabled.

To enable upscaling everything about the plugin needs to be sandboxed in such a way that the thread’s “DPI Awareness Context” is correctly set on every call into the plugin. Previously the boundaries of that “sandbox” was essentially the plugin editor window.

With newer versions of Windows 10, they’ve added support for upscaling a child window - ie: I no longer need to sandbox the entire plugin editor window - just the plugin view itself.

The meant that I could tighten the sandbox and move all that code to the C++ side of things and remove all the messy handling of dpi-awareness context transitions from the C# code.

The result is cleaner code, and it works better because the window frame and the toolbar are all now in hi-res mode which solves a whole bunch of geometry conversions for mixed scale factors. The only downside is you’ll need one of the newer versions of Windows 10 for this to work, but that’s been out for a while now so for most this should just work.

And with that all the major areas of Cantabile’s GUI have now been ported to the new version of GuiKit. The next job will be all the dialog boxes - it looks like most of them are working fine but there’s some layout issues that need tweaking, some keyboard actions that aren’t working correctly and a couple are crashing. But that’s next weeks job and I feel like I’m past the bulk of the hard work.

16 Likes

Today’s job: “Fix a bunch of stuff”

I’ve been random ad-hoc testing through all the dialogs fixing things as I go…

  • All the options dialog pages
  • The midi filter settings for every filter type
  • The insert plugin dialog,
  • The licensing dialogs
  • All dialogs available from the main menu

…are all working well.

The main thing I haven’t tested are the various popup dialogs from the binding slots.

Still have a lot more testing to do, but I’m really pleased that this finally feels like it’s all coming together.

8 Likes

More random acts of fixing stuff today:

  • Fixed exception when using variables in show notes
  • Fixed left/right keyboard navigation in main table view
  • Fixed popups larger than screen not shrinking and adding scrollbar
  • Fixed missing reset icon on rack slot preset selector button
  • Fixed fixed pitch text areas
  • Fixed theming of delay load and learn transpose/key range popups
  • Fixed Ctrl+Up/Down both re-ordering items and moving selection
  • Fixed saved window placements incompatible with old versions of Cantabile
  • Fixed first item in menu bar incorrectly highlighting when popup shown
  • Fixed list incorrectly stealing keys that it didn’t want.
  • Fixed text views not remeasuring when text changed
  • Fixed popup’s no placing oversized content correctly
  • Fixed some items not redrawing when theme changes
  • Fixed left/right arrow keys incorrectly wrapping at end of row
  • Fixed popups incorrectly flipping to other side of invoking button
  • Fixed menu items not drawing some short cut keys correctly

Also, first attempt at light theme… inherits everything from dark theme and basically works but just need to redefine some color constants:

And now I’m off to celebrate Mitch’s birthday! :slightly_smiling_face: :birthday: :tada:

13 Likes

Congrats to your son, have a nice party! :blush: :tropical_drink:

1 Like

Light theme finished.

Dark vs Light:

9 Likes

It’s the dark side (of the moon) for me…

1 Like

Perhaps a bit silly question: only Dark or Light?

Yep, most people prefer the Dark and that’s been the default for a long time but I still see fairly regularly screen shots from users with light mode so some people prefer it.

Cantabile will come with Dark and Light like it always has. But… you can build your own (as simple as tweaking the colors in a text file, or as complex as redesigning the whole theme with new graphics if you’re keen).

Also, you’ll be able to share your custom themes just like happens with the current Cantabile release (eg: see here).

1 Like

Today I started on something I’ve wanted for Cantabile for a long time - some automated UI testing.

As a first step I thought I just put together some test scripts to take a bunch of screenshots. This will serve two purposes:

  1. it’s something I can run before each release as a simple confidence test to make sure things are basically working.
  2. I can quickly step through all those screen shots and look for anything out of the ordinary - this will be particularly handy in the coming days as I refine and touch up the layout of all the different screens.

I would have done this a long time ago but GuiKit 2 didn’t have great support for UIAutomation. GuiKit3’s support is much better - not perfect, but definitely enough for these kinds of tests.

You can see what I’m talking about in this video where I’m using Visual Studio’s Test runner to run a test suite that:

  1. starts Cantabile
  2. takes screen shots of all the options pages
  3. takes screen shots of all the MIDI filter pages
  4. shuts down Cantabile

The output is a folder full of screenshots.

When writing these test scripts it always feels like it takes too long, but the payback comes in the weeks and months that follow. ie: I feel like I didn’t accomplish much today, but I know it’s important.

Currently I’m only taking screenshots, but as I get more used to the UIAutomation interfaces and better at writing the test scripts I hope to automate exercising as much of Cantabile as I can.

10 Likes

UI test automation is always the hardest…

2 Likes

Today:

  • More automated capturing of screen shots
  • Started adding Automation Ids to various UI elements in Cantabile to make it easier to locate in invoke different actions.
  • Lots of tweaks to the scripts and utility library I’m using to make it easier and more programmatic (ie: more “do exactly this” and less “send these keys”)
  • Now capturing nearly 60 screen shots of different UI screens.

Tedious work, but I’m going to persevere with trying getting screenshots of everything in Cantabile.

About UIAutomation

I’ve mentioned UIAutomation a few times now and thought I’d provide a little explainer for those who don’t know what this is.

In GuiKit the entire UI is manually drawn to a big bitmap (image) and then copied to the screen. This allows for nice composition of various views and elements and a very flexible UI framework.

The downside is the content of that bitmap is opaque to Windows and to other programs. Without additional support, screen readers don’t work and utilities programs like AutoHotKey, FlaUI, WinAppDriver have no visibility as to what’s inside a particular window.

That’s where UIAutomation comes in… it’s a separate interface into a window that lets other programs find out about things inside it. eg: a screen reader can ask “what’s at this point”, to which the UIAutomation interface might say “a button” to which the screen reader can ask “what’s the text on the button” to which the app might return “OK”… and the screen reader can highlight the button and speak the word “OK” so a vision impaired user can hear what’s on the screen.

That’s the basic idea, but the UIAutomation interfaces also provide the ability to programatically control a program. eg: instead of a screen reader interacting with the app, perhaps a script program might run a set of actions like… find the File menu, click it, find the Open command, click it, type “MySong”, find the OK button, click it.

So that’s what I’m doing with this automated UI testing - writing script programs that run externally to Cantabile, but drive it to do various actions and then take screenshots of the relevant parts of the screen.

As an example, here’s a script which captures the audio port dialog boxes:

// Use the Edit Find command to find the mda plugin 
_fixture.InvokeCommand("edit.globalFind");
var w = _fixture.Session.FindWindow(x => x.Name == "Find");
w.FindById("textSearch").Value = "mda";
w.FindById("buttonOK").Click();

// Open audio ports window
_fixture.InvokeCommand("edit.audioPorts");
var window = _fixture.Session.FindWindow(x => x.Name.StartsWith("Edit Ports - "));
window.CaptureScreenshot("AudioPorts");

// Get all the list items
var list = window.FindById("listPortsAndChannels");
var items = list.FindAll(x => x.ControlType == ControlType.ListItem);

// Select the port, edit and capture
items[0].Select();
window.FindById("buttonEdit").Invoke();
var wPortName = _fixture.Session.FindWindow(x => x.Name.StartsWith("Audio ") && x.Name.EndsWith(" Port"));
wPortName.CaptureScreenshot("AudioPortName");
wPortName.Close();

// Select channel, edit and capture
items[1].Select();
window.FindById("buttonEdit").Invoke();
var wPort = _fixture.Session.FindWindow(x => x.Name.StartsWith("Edit ") && x.Name.EndsWith(" Channel"));
wPort.CaptureScreenshot("AudioPort");
wPort.Close();

// Close audio ports dialog
window.Close();

And here’s what it captured:

AudioPortName

Brad

10 Likes

After several days of work I’ve not got pretty much every screen in Cantabile captured by my UI test scripts. In total Cantabile has about 125 dialog boxes.

As mentioned this felt like a waste of time but it turned up half dozen or so bugs and I’ve now got a good platform to exercise large chunks of Cantabile UI before every release. All up I think this will be a positive, but I’m exhausted because this kind of work is sooo tedious.

Time to get on with getting this project finished.

11 Likes

Testing can seem like not being productive, but once you have them, they are good. For my Java Synth Librarians I have test scripts for doing file read/writes to ensure I do not screw up any data, and very occasionally you do a change that does break things, and the tests have always saved me.

My background is in high integrity software you have to achieve full code coverage in testing or justify the exceptions. Now that is a real ball ache, but you do see the difference between the software tested to this level and software that isn’t.

2 Likes