tg icon indicating copy to clipboard operation
tg copied to clipboard

GTK+ 3

Open wahlstedt opened this issue 9 years ago • 22 comments

Upgraded to GTK+ 3. It won't compile with GTK+ 2 anymore.

I kept the user interface layout pretty much the same for now but made the paperstrip resizable via panes. Quite useful for "zooming in" on the strip.

I also took the liberty of bumping the version to 0.3, seemed like a fitting number. :)

tgmac3

wahlstedt avatar Dec 19 '15 15:12 wahlstedt

I'm new to GTK+ so I've been playing around with it and just found that you can easily switch the theme between the default "light" and "dark" mode. I think the dark theme looks better!

This could be a user configurable option as well... One feature sorely needed is some sort of preferences, so it can remember things like window size between launches.

tgdark

wahlstedt avatar Dec 19 '15 18:12 wahlstedt

I took advantage of GTK+ 3's CSS styling features and moved the colour definitions out to an external .css file that the endusers can use to modify the look of the app.

For now it's only the colours, but other things like fonts and sizes can be controlled via the CSS file as well.

I suggest putting the information data (rate, beat error etc.) into separate GtkLabels (instead of a big GtkDrawingArea) to make them styleable as well as making it easier to migrate to other toolkits in the future.

wahlstedt avatar Dec 21 '15 21:12 wahlstedt

Hi, thanks for your contribution! I'm sorry for the delay in my answer.

The move to GTK3 is welcome to me, there are however a couple issues.

1 - Please keep the same use of tabs and spaces as the original, otherwise it is hard to make diffs and also the code becomes dishomogeneous.

2 - The Windows build is crucial. Currently I can not compile for GTK3 on Windows, but this isn't a big issue. The problem is that the official GTK distribution suggests to use the MSYS2 binaries for windows, and these are at version 3.12, while your code requires at least 3.16. Also on debian stable we have only 3.14.

The ability for the user to style the UI is low priority, because tg is intended for watch enthusiasts, that often are not computer geeks. Anyway, if the GTK labels can be made to look nice, we can use them. This should also make the code shorter, which is good.

vacaboja avatar Dec 23 '15 12:12 vacaboja

On 23 Dec 2015, at 13:38, vacaboja [email protected] wrote: 1 - Please keep the same use of tabs and spaces as the original, otherwise it is hard to make diffs and also the code becomes dishomogeneous.

Sorry about that. I’m using Xcode to edit and I guess the defaults there are different. Will try to update settings to match.

2 - The Windows build is crucial. Currently I can not compile for GTK3 on Windows, but this isn't a big issue. The problem is that the official GTK distribution suggests to use the MSYS2 binaries for windows, and these are at version 3.12, while your code requires at least 3.16. Also on debian stable we have only 3.14.

Wow, I didn’t realise GTK+ wasn’t in sync across platforms. Very odd that the Mac is ahead of others, it’s usually the other way around! lol

Also, I thought I wasn’t using anything that would require a specific GTK+3 version. The only new widget types I added (GtkPaned & GtkGrid) have been there since the launch of v3 in 2011. Do you know what specific features used that causes it to require 3.16? Maybe it’s something trivial that can be replaced.

The ability for the user to style the UI is low priority, because tg is intended for watch enthusiasts, that often are not computer geeks.

It's also useful for people with bad eyesight, they can make the text bigger and increase contrast for example. It’s also handy during development to try out styles without recompiling.

Merry christmas!

/Robert

wahlstedt avatar Dec 23 '15 13:12 wahlstedt

Sorry, these days I have so little time...

gtk_paned_set_wide_handle() requires 3.16, I believe. Except for that it should be compatible with 3.14. I didn't check 3.12, which is the version more easily available for Windows.

Merry Christmas to you too!

vacaboja avatar Dec 25 '15 22:12 vacaboja

On 25 dec 2015, at 23:45, vacaboja [email protected] wrote:

gtk_paned_set_wide_handle() requires 3.16

Aha, that one can be removed. It was added as an attempt to make the divider between the panes look better. It defaults to a thin 1 pixel border, and "set wide" makes it 5 pixels instead.

However, I found that you get better control of the spacing via CSS, so I added the border in the CSS file instead. That probably requires 3.16 as well, but the CSS should be ignored on older versions and not cause any errors.

/Robert

wahlstedt avatar Dec 26 '15 10:12 wahlstedt

The latest commit removes the custom text handling for the info area and moves the text into separate GtkLabels. There's plenty of optimisations available to only update the labels when the data actually change, but for now everything still updates at 10fps.

One idea I had was to sync the refresh rate to the actual rate of the watch since there's no need to update until there's new data available. E.g. a 21600 bph watch would generate updates at 6Hz and a 28800 bph watch would get updated at 8Hz.

I removed the use of gtk_paned_set_wide_handle() so hopefully it won't require v3.16 anymore.

I also changed the indentation setting in xcode from spaces (the default) to tabs. Let me know if that better matches yours!

tglabels

wahlstedt avatar Jan 02 '16 22:01 wahlstedt

Made the colors alternate in the paperstrip, like how the real color Timegraphers does it (Model 1900 etc.)

alternatecolors

wahlstedt avatar Jan 03 '16 13:01 wahlstedt

Began working on a settings window. Nothing is hooked up or saved yet, but it does query PortAudio for what inputs are available so it can show them.

Also added support for mouse wheel zooming of the paperstrip. It's pretty basic at the moment and can be improved by having the dots grow bigger for example.

settings

wahlstedt avatar Jan 08 '16 03:01 wahlstedt

The settings are now saved & loaded from disk. Not all are hooked in yet, but all of the UI settings are working: you can switch the dark theme on/off and the window size will be remembered (including pane divider position).

wahlstedt avatar Jan 09 '16 01:01 wahlstedt

The audio input setting is now working and will use the input device selected.

This leaves only unimplemented things not yet hooked up from the settings. The Rate adjustment should be fairly straightforward, but I'll leave that for you to implement since I don't want to muck around with the actual algorithm calculations for now. :smile:

As for the Precision mode checkbox, my idea is to try and eliminate the need for the light version of the app by adding logic here instead. But I need to check with you about what can be done. For example, it seems that a large part of what the light version does is to use half of the samples, would it be feasible to sample at half the rate instead (i.e. 22050Hz)? Also, would it be beneficial to allow higher than 44.1kHZ sample rates? Many sound cards go up to 192kHz nowadays. Or would the algorithm not have use of the added resolution?

Another sound related optimisation would be to sample in mono instead of stereo. Or are there benefits to getting a stereo signal?

wahlstedt avatar Jan 11 '16 03:01 wahlstedt

Hi, I played a little with your version of tg.

These is the thing that I like, and I will pull: the audio input selection.

I need to think to the other changes a bit more.

The two color trace: that's a good idea, but it needs to be implemented differently. As it is now, it merely alternates the colors, this looks nice but it's not the right thing. Tg has, internally, a concept of what is a tic and what is a toc. The correct implementation is to color according to this information, so I will see what I can do to expose it from algo.c.

The settings window: I am against settings. They make it far too easy to add inessential features. Honestly, I would like this thing to be as black-boxed as possible. The user is not supposed to fiddle with parameters that often he does not fully understand.

The mode of displaying text introduces a regression. Currently, the master version keeps each text display in a fixed position on the screen. However, in the new version, the displays are flush left, so the position of each depends on the total length of text in the preceding ones. And this makes it move as the output changes.

About the error in the clock of the sound card. This quantity is not constant, as it can fluctuate with time and temperature. I've got the impression that current audio cards are good enough, but that is just an impression. A nice addition would be a companion app to let users find it. One should figure out what to use as a reference oscillator...

About mono/stereo. The thing to do is to have tg select automatically.

About the sampling frequency. There is a law of diminishing returns on this. Using 22.05kHz would probably be a mistake. First, the audio card will often still run at 44.1kHz, with the downsampling being done in software. Also, the lt version doesn't perform a proper downsampling. Theoretically, to downsample a signal, one should filter out the unwanted frequencies (above 10kHz in this case) before decimating the samples. By going directly to the decimation step, tg-lt wilfully induces a form of distortion known as aliasing. Aliasing is always very bad, except for this application. The idea is that we don't care if the frequencies in the signal are badly messed up, as long as the timing is preserved. So, a bit counter-intuitively, the lt version is actually using the 44.1kHz sampled signal. On the other hand, my impression is that going further up with sampling rates would be only a source of problems. Probably, in most setups, the higher frequencies get filtered anyway by various combinations of mic, preamp, cheap audio card, os interface.

Actually, having an lt version is a kludge. I will try to make a single one that performs acceptably in any situation.

vacaboja avatar Jan 14 '16 18:01 vacaboja

The two color trace: that's a good idea, but it needs to be implemented differently. As it is now, it merely alternates the colors, this looks nice but it's not the right thing. Tg has, internally, a concept of what is a tic and what is a toc.

I suspected as much, but I haven’t delved into the processing_buffers variables and algo.c since they are still undocumented… Hint, hint. heh

The settings window: I am against settings. They make it far too easy to add inessential features. Honestly, I would like this thing to be as black-boxed as possible.

I would say it’s a mistake not to have user settings. While things like UI settings might arguably be called inessential, in the case of rate adjustment I suspect that is a setting that IS required. See comments later.

I think all but the most trivial app benefits from user configurability. The one-size-fits-all approach doesn’t work well for software. For example, you don’t need an audio input setting, but then you would have to add instructions to make sure the user configures the desired input as the system default before running the app (a task that is much more complicated for the inexperienced). You don’t need to have settings to control CPU usage, but then you would have to make sure users read instructions and select the proper executable to avoid bad performance.

Future features (like printing) most likely will require some sort of settings as well so implementing a settings system from the beginning makes sense.

Making the default settings reasonable would make it so that most users don't have to touch the settings, but having the ability to do so is a great benefit imho. Like the previous discussion about css styling: 99% of the users can use the app as it is but for those 1% with bad eyesight the ability to change some settings can be the difference between being able to use the app or not.

The mode of displaying text introduces a regression. Currently, the master version keeps each text display in a fixed position on the screen. However, in the new version, the displays are flush left, so the position of each depends on the total length of text in the preceding ones. And this makes it move as the output changes.

Right, I simply added the labels to a grid and planned on aligning them better once I had read up on how to do that in GTK. I just did a quick edit and submitted a commit with a fix.

It can be further improved by breaking out the numeric part into separate labels and having new static labels after them with the units text. This will prevent slight aliasing differences when rendering the text.

A big reason for using standard GTK widgets instead of custom rendering is that it makes it much more portable if you want to make a non-GTK version, like iOS. Simply move all GtkLabel objects into UILabel etc. It also reduces load since you can update each label individually instead of having to render them all together.

About the error in the clock of the sound card. This quantity is not constant, as it can fluctuate with time and temperature. I've got the impression that current audio cards are good enough, but that is just an impression. A nice addition would be a companion app to let users find it. One should figure out what to use as a reference oscillator…

While I haven’t done any experiments myself, I'm pretty sure that sound cards don’t perform at the required precision. Error rates are on the order of ±0.01% which is enough to make any watch rate calculation pretty useless.

All software timegraphers have a rate adjustment setting, and there have been lengthy discussions about how to best do the calibration. I’ve followed a long thread at the Watchrepairtalk forum about this topic since the Watch-O-Scope author posts there a lot.

All the hardware timegraphers have calibration options and I would assume they use better oscillators than your average PC sound card. heh

As for the means of calibration, there are various approaches. Hardware timegraphers use a GPS signal, Watch-O-Scope suggests using a quartz watch (would this work in tg?) and the Lepsi iOS/Android app does it via some sort of lengthy in-app process using NTP servers (I have no idea how that could work).

See this loooong page about calibration for the SpecLab app: http://www.qsl.net/dl4yhf/speclab/frqcalib.htm

About mono/stereo. The thing to do is to have tg select automatically

My reason for asking was that it appears as if the stereo samples are merged into a mono waveform right after sampling so it would save RAM and CPU to simply ask for mono input from Portaudio at the start.

I did a quick test with just 1 input channel and it seemed to perform the same.

About the sampling frequency. There is a law of diminishing returns on this.

You’re the pro here, my layman perspective was that the higher the sampling rate, the better the timing resolution of the calculations would be.

Would be interesting to test various sampling rates if you haven’t done so already. E.g. comparing the current method of dropping every second 44.1KHz sample vs using a Portaudio supplied 22050Hz stream. Or the impact of using other rates like 32kHz or 48kHz. Maybe the sweet spot isn’t 44.1? The above linked SpecLab calibration page says that most sound cards perform better at 48kHz than 44.1kHz.

wahlstedt avatar Jan 15 '16 01:01 wahlstedt

I worked more on the info text labels and have now split out the numbers and units into separate labels to make them stay in place better. This also makes them faster to render since we don't have to use Pango text markup to make the unit text smaller.

I also made the numbers bold (via css) as a test.

bolder

wahlstedt avatar Jan 15 '16 02:01 wahlstedt

When searching for more data about sound card oscillator precision I found a nice Android app designed to measure clock drift. It has example data from various (handheld) devices and they vary in drift from single digit to several hundred ppm.

It also features info and plans for PC/GPS calibration,

wahlstedt avatar Jan 17 '16 11:01 wahlstedt

Added a screenshot feature that can save in either PNG (for posting online) or PDF (for printing).

screenshot

wahlstedt avatar Feb 17 '16 00:02 wahlstedt

Tweaked the screenshot code to hide the buttons below the paperstrip when saving. So now the resulting screenshot images contain no UI elements at all.

screenie

wahlstedt avatar Feb 19 '16 23:02 wahlstedt

Hi, it's been a year since I submitted this request and I just noticed that you posted on the WUS forum that you are "working on a save/snapshot/print feature", which this pull request already includes... Does this mean you are not interested in my contributed code?

wahlstedt avatar Feb 09 '17 17:02 wahlstedt

Hi my friend wahlstedt.

No, it does not mean that I am not interested in your code. In fact, I left the pull request open, as you can see. You might also observe that I already used pieces of your code, for instance the current version of tg has a config file as you suggested, and also the structure of the file takes elements of your design. However, your code is not carefully written, and I could not have pulled it in without causing embarrassment to the users.

Take, for instance, the config file cited above. Your code just placed it in the current working directory of the tg process. If the user runs the tg command multiple times from many different directories, he gets multiple configurations switching on and off unpredictably. If the CWD is not writable: error. If the CWD at that moment happens to be a shared folder, maybe with the user's boss? You can not just litter the user's file system with files: there are standards for such things that must be respected cross-platform. Take a look at the current implementation of the configuration file to see what I mean.

About the printing feature specifically, I will certainly use your code. However I can not pull it tout court, because it is not a complete implementation. Did you take a look at how other timegrapher programs handle this feature? Did you try to understand the decision made by other implementers, and only then design your system to be better? A simple screenshot is hardly a complete print facility. It also comes at a high cost, because to pull it I would have to switch to GTK3, since you made your code dependent on that. Please understand that this is a major change, and that it can easily break the build for some user, or break dependencies of installers. In conclusion, as soon as I have the remaining parts to make a complete system in place, which I am currently writing, I will happily pull in the elements that are in your code.

So again, I do not intend to criticize your contribution without reason. In fact I thank you for every line of it, and I will indeed make use of your code, as it already happened for the part handling the configuration file. However I need time to integrate it into tg, and more time to test it, and to ensure that it works solidly on every platform.

vacaboja avatar Feb 10 '17 02:02 vacaboja

Fair enough. It seems like it boils down to you not wanting to upgrade to GTK+ 3? ...which was the purpose this pull request.

The additional commits with features like the config and screenshots were work in progress and not meant to be complete implementations, but rather a starting point for discussion. So those may look "unfinished" since the main goal was migrating the code to GTK+ 3 and then continue working on those other features. But I never heard back from you after your January 2016 comment.

I’m unsure as to why you think GTK+ 3 would be a major change and break things, but that’s your decision. Version 3 had its last long-term stable version release (3.22) back in autumn 2016 and focus has shifted to version 4. As far as I could tell the Windows packages are up to date (with mingw-w64-i686-gtk3-3.22.7-1)

Details at https://blog.gtk.org/2016/09/01/versioning-and-long-term-stability-promise-in-gtk/

wahlstedt avatar Feb 12 '17 00:02 wahlstedt

Would be interesting to test various sampling rates if you haven’t done so already. E.g. comparing the current method of dropping every second 44.1KHz sample vs using a Portaudio supplied 22050Hz stream. Or the impact of using other rates like 32kHz or 48kHz. Maybe the sweet spot isn’t 44.1? The above linked SpecLab calibration page says that most sound cards perform better at 48kHz than 44.1kHz.

It is indeed true that tg doesn't do a low pass filter before decimating the audio. Changing the soundcard sampling rate would do this. It would have also been quite a bit faster, as the code in tg to get the audio into the processing algorithm was not very efficient. But I have sent a PR that makes tg much faster, so it's not as much of a win.

Which speed is better depends on a number of factors. Some sound hardware has a PLL which can be used to generate multiple sampling rates, which would all be derived from the same source clock. Others does not. The USB microphone I'm using only supports 48 kHz. The hardware can't do another frequency. When tg uses 44.1, what happens is the audio is resampled in software. So it's quite silly to resample with a good algorithm from 48 to 44.1, then have tg resample poorly from 44.1 to 22.05.

Your computer motherboard audio hardware almost certainly can do multiple rates. But they are all derived from the same source, their quality will be the same. The same temp coefficient, the same aging, etc. But they might not be the same accuracy. The logic that turns the base clock into the ADC master clock (typically about 512x faster than the actual sampling rate, e.g. 24.576 MHz for 48 kHz) has certain limits to the numerator and denominator it can use for the fractional multiplication of the frequency. So it might be programmed to produce 44.308 kHz instead of 44.100. It would depend on the hardware the source clock. Is it trying to produce 44.1 kHz from a 24.576 MHz XO or 48 kHz from a 22.5792 MHz XO?

I've also written code for an audio source selection dialog and sample rate selection. But tg kind of has a compiled in sample rate in the algorithm, so it doesn't really work yet. And also port audio on Linux doesn't allow you to query allowed sample rate while using the audio hardware, so the choice box with allowed sample rates to choose from doesn't work as well as I'd like.

xyzzy42 avatar Mar 04 '20 08:03 xyzzy42

It also features info and plans for PC/GPS calibration,

Port audio includes a timestamp with each buffer it supplies. On Linux, this is derived from the ALSA hardware timestamp. Unless you have a very fancy audio device, this timestamp is from the Linux system clock. That clock is corrected via the ntp to be phased locked to a ntp server, which is almost certainly using GPS time.

So all you have to do to get accurate time is use the timestamps port audio is already providing.

The computer will need to be ntp synced. Or use a local clock like a GPS receiver to sync. But ntp is really quite good. You can see the measurement of the pll accuracy by looking into ntpd or chrony's detailed states.

System time     : 0.000418330 seconds slow of NTP time
Last offset     : -0.000086358 seconds
RMS offset      : 0.000216011 seconds
Frequency       : 86.200 ppm slow
Residual freq   : -0.001 ppm
Skew            : 0.018 ppm

The computer clock would be off by -7 s/d, but via ntp our error bound is down to 0.0016 s/d. I don't think that's limiting tg's accuracy.

xyzzy42 avatar Mar 04 '20 08:03 xyzzy42