void Refresh() { bool success = false; // if we have no queue, but still have levels, gradually bring them down if (player == null) { float maxLvl = -1f; DateTime thisFire = DateTime.Now; // calculate how much time passed since the last draw var timePassed = (thisFire - peakFalloffLastFire).TotalSeconds; foreach (var thisMeter in sublevelMeters) { float newPeak, newLevel; newLevel = (float)(thisMeter.Level - timePassed * kLevelFalloffPerSec); if (newLevel < 0) { newLevel = 0; } thisMeter.Level = newLevel; if (showPeaks) { newPeak = (float)(thisMeter.PeakLevel - timePassed * kPeakFalloffPerSec); if (newPeak < 0) { newPeak = 0; } thisMeter.PeakLevel = newPeak; if (newPeak > maxLvl) { maxLvl = newPeak; } } else if (newLevel > maxLvl) { maxLvl = newLevel; } thisMeter.SetNeedsDisplay(); } // stop the timer when the last level has hit 0 if (maxLvl <= 0) { updateTimer.Invalidate(); updateTimer = null; } peakFalloffLastFire = thisFire; success = true; } else { player.UpdateMeters(); for (int i = 0; i < channelNumbers.Length; i++) { int channelIdx = channelNumbers [i]; LevelMeter channelView = sublevelMeters [channelIdx]; if (channelIdx >= channelNumbers.Length) { goto bail; } if (channelIdx > 127) { goto bail; } channelView.Level = meterTable.ValueAt(player.AveragePower((uint)i)); if (showPeaks) { channelView.PeakLevel = meterTable.ValueAt(player.PeakPower((uint)i)); } else { channelView.PeakLevel = 0; } channelView.SetNeedsDisplay(); success = true; } } bail: if (!success) { foreach (var thisMeter in sublevelMeters) { thisMeter.Level = 0; thisMeter.SetNeedsDisplay(); } Console.WriteLine("ERROR: metering failed\n"); } }