diff options
Diffstat (limited to 'src/volume-warning.vala')
-rw-r--r-- | src/volume-warning.vala | 408 |
1 files changed, 204 insertions, 204 deletions
diff --git a/src/volume-warning.vala b/src/volume-warning.vala index 659240b..24f90e3 100644 --- a/src/volume-warning.vala +++ b/src/volume-warning.vala @@ -23,208 +23,208 @@ using PulseAudio; public abstract class VolumeWarning : Object { - // true if headphones are in use - public bool headphones_active { get; set; default = false; } - - // true if the warning dialog is being shown - public bool active { get; protected set; default = false; } - - // true if we're playing unapproved loud multimedia over headphones - public bool high_volume { get; protected set; default = false; } - - public enum Key { - VOLUME_UP, - VOLUME_DOWN - } - - public void user_keypress (Key key) { - if ((key == Key.VOLUME_DOWN) && active) { - _notification.close (); - on_user_response (IndicatorSound.WarnNotification.Response.CANCEL); - } - } - - internal VolumeWarning (IndicatorSound.Options options) { - - _options = options; - - init_high_volume (); - init_approved (); - - _notification.user_responded.connect ((n, r) => on_user_response (r)); - } - - ~VolumeWarning () { - clear_timer (ref _approved_timer); - } - - /*** - **** - ***/ - - // true if the user has approved high volumes recently - protected bool approved { get; set; default = false; } - - // true if multimedia is currently playing - protected bool multimedia_active { get; set; default = false; } - - /* Cached value of the multimedia volume reported by pulse. - Setting this only updates the cache -- to change the volume, - use sound_system_set_multimedia_volume. - NB: This PulseAudio.Volume is typed as uint to unconfuse valac. */ - protected uint multimedia_volume { get; set; default = PulseAudio.Volume.INVALID; } - - protected abstract void sound_system_set_multimedia_volume (PulseAudio.Volume volume); - - protected void clear_timer (ref uint timer) { - if (timer != 0) { - Source.remove (timer); - timer = 0; - } - } - - private IndicatorSound.Options _options; - - /** - *** HIGH VOLUME PROPERTY - **/ - - private void init_high_volume () { - const string self_keys[] = { - "multimedia-volume", - "multimedia-active", - "headphones-active", - "high-volume-approved" - }; - foreach (var key in self_keys) - this.notify[key].connect (() => update_high_volume ()); - - const string options_keys[] = { - "loud-volume", - "loud-warning-enabled" - }; - foreach (var key in options_keys) - _options.notify[key].connect (() => update_high_volume ()); - - update_high_volume (); - } - - private void update_high_volume () { - - var newval = _options.loud_warning_enabled - && headphones_active - && multimedia_active - && !approved - && (multimedia_volume != PulseAudio.Volume.INVALID) - // from the sound specs: - // "Whenever you increase volume,..., such that acoustic output would be MORE than 85 dB - && (multimedia_volume > _options.loud_volume); - - if (high_volume != newval) { - debug ("changing high_volume from %d to %d", (int)high_volume, (int)newval); - if (newval && !active) - activate (); - high_volume = newval; - } - } - - /** - *** HIGH VOLUME APPROVED PROPERTY - **/ - - private Settings _settings = new Settings ("org.ayatana.indicator.sound"); - private static const string TTL_KEY = "warning-volume-confirmation-ttl"; - private uint _approved_timer = 0; - private int64 _approved_at = 0; - private int64 _approved_ttl_usec = 0; - - private void approve_high_volume () { - _approved_at = GLib.get_monotonic_time (); - update_approved (); - update_approved_timer (); - } - - private void init_approved () { - _settings.changed[TTL_KEY].connect (() => update_approved_cache ()); - update_approved_cache (); - } - private void update_approved_cache () { - _approved_ttl_usec = _settings.get_int (TTL_KEY); - _approved_ttl_usec *= 1000000; - - update_approved (); - update_approved_timer (); - } - private void update_approved_timer () { - - clear_timer (ref _approved_timer); - - if (_approved_at == 0) - return; - - int64 expires_at = _approved_at + _approved_ttl_usec; - int64 now = GLib.get_monotonic_time (); - if (expires_at > now) { - var seconds_left = 1 + ((expires_at - now) / 1000000); - _approved_timer = Timeout.add_seconds ((uint)seconds_left, () => { - _approved_timer = 0; - update_approved (); - return Source.REMOVE; - }); - } - } - private void update_approved () { - var new_approved = calculate_approved (); - if (approved != new_approved) { - debug ("changing approved from %d to %d", (int)approved, (int)new_approved); - approved = new_approved; - } - } - private bool calculate_approved () { - int64 now = GLib.get_monotonic_time (); - return (_approved_at != 0) - && (_approved_at + _approved_ttl_usec >= now); - } - - // NOTIFICATION - - private IndicatorSound.WarnNotification _notification = new IndicatorSound.WarnNotification (); - private PulseAudio.Volume _ok_volume = PulseAudio.Volume.INVALID; - - protected virtual void preshow () {} - - private void activate () { - preshow (); - _ok_volume = multimedia_volume; - - _notification.show (); - this.active = true; - - // lower the volume to just the warning level - // from the sound specs: - // "Whenever you increase volume,..., such that acoustic output would be MORE than 85 dB - sound_system_set_multimedia_volume (_options.loud_volume); - } - - private void on_user_response (IndicatorSound.WarnNotification.Response response) { - - this.active = false; - - if (response == IndicatorSound.WarnNotification.Response.OK) { - approve_high_volume (); - sound_system_set_multimedia_volume (_ok_volume); - } else { - this.cancel_pressed (this.volume_to_double(_options.loud_volume)); - } - - _ok_volume = PulseAudio.Volume.INVALID; - } - - private static double volume_to_double (PulseAudio.Volume vol) - { - double tmp = (double)(vol - PulseAudio.Volume.MUTED); - return tmp / (double)(PulseAudio.Volume.NORM - PulseAudio.Volume.MUTED); - } - - public signal void cancel_pressed (double cancel_volume); + // true if headphones are in use + public bool headphones_active { get; set; default = false; } + + // true if the warning dialog is being shown + public bool active { get; protected set; default = false; } + + // true if we're playing unapproved loud multimedia over headphones + public bool high_volume { get; protected set; default = false; } + + public enum Key { + VOLUME_UP, + VOLUME_DOWN + } + + public void user_keypress (Key key) { + if ((key == Key.VOLUME_DOWN) && active) { + _notification.close (); + on_user_response (IndicatorSound.WarnNotification.Response.CANCEL); + } + } + + internal VolumeWarning (IndicatorSound.Options options) { + + _options = options; + + init_high_volume (); + init_approved (); + + _notification.user_responded.connect ((n, r) => on_user_response (r)); + } + + ~VolumeWarning () { + clear_timer (ref _approved_timer); + } + + /*** + **** + ***/ + + // true if the user has approved high volumes recently + protected bool approved { get; set; default = false; } + + // true if multimedia is currently playing + protected bool multimedia_active { get; set; default = false; } + + /* Cached value of the multimedia volume reported by pulse. + Setting this only updates the cache -- to change the volume, + use sound_system_set_multimedia_volume. + NB: This PulseAudio.Volume is typed as uint to unconfuse valac. */ + protected uint multimedia_volume { get; set; default = PulseAudio.Volume.INVALID; } + + protected abstract void sound_system_set_multimedia_volume (PulseAudio.Volume volume); + + protected void clear_timer (ref uint timer) { + if (timer != 0) { + Source.remove (timer); + timer = 0; + } + } + + private IndicatorSound.Options _options; + + /** + *** HIGH VOLUME PROPERTY + **/ + + private void init_high_volume () { + const string self_keys[] = { + "multimedia-volume", + "multimedia-active", + "headphones-active", + "high-volume-approved" + }; + foreach (var key in self_keys) + this.notify[key].connect (() => update_high_volume ()); + + const string options_keys[] = { + "loud-volume", + "loud-warning-enabled" + }; + foreach (var key in options_keys) + _options.notify[key].connect (() => update_high_volume ()); + + update_high_volume (); + } + + private void update_high_volume () { + + var newval = _options.loud_warning_enabled + && headphones_active + && multimedia_active + && !approved + && (multimedia_volume != PulseAudio.Volume.INVALID) + // from the sound specs: + // "Whenever you increase volume,..., such that acoustic output would be MORE than 85 dB + && (multimedia_volume > _options.loud_volume); + + if (high_volume != newval) { + debug ("changing high_volume from %d to %d", (int)high_volume, (int)newval); + if (newval && !active) + activate (); + high_volume = newval; + } + } + + /** + *** HIGH VOLUME APPROVED PROPERTY + **/ + + private Settings _settings = new Settings ("org.ayatana.indicator.sound"); + private static const string TTL_KEY = "warning-volume-confirmation-ttl"; + private uint _approved_timer = 0; + private int64 _approved_at = 0; + private int64 _approved_ttl_usec = 0; + + private void approve_high_volume () { + _approved_at = GLib.get_monotonic_time (); + update_approved (); + update_approved_timer (); + } + + private void init_approved () { + _settings.changed[TTL_KEY].connect (() => update_approved_cache ()); + update_approved_cache (); + } + private void update_approved_cache () { + _approved_ttl_usec = _settings.get_int (TTL_KEY); + _approved_ttl_usec *= 1000000; + + update_approved (); + update_approved_timer (); + } + private void update_approved_timer () { + + clear_timer (ref _approved_timer); + + if (_approved_at == 0) + return; + + int64 expires_at = _approved_at + _approved_ttl_usec; + int64 now = GLib.get_monotonic_time (); + if (expires_at > now) { + var seconds_left = 1 + ((expires_at - now) / 1000000); + _approved_timer = Timeout.add_seconds ((uint)seconds_left, () => { + _approved_timer = 0; + update_approved (); + return Source.REMOVE; + }); + } + } + private void update_approved () { + var new_approved = calculate_approved (); + if (approved != new_approved) { + debug ("changing approved from %d to %d", (int)approved, (int)new_approved); + approved = new_approved; + } + } + private bool calculate_approved () { + int64 now = GLib.get_monotonic_time (); + return (_approved_at != 0) + && (_approved_at + _approved_ttl_usec >= now); + } + + // NOTIFICATION + + private IndicatorSound.WarnNotification _notification = new IndicatorSound.WarnNotification (); + private PulseAudio.Volume _ok_volume = PulseAudio.Volume.INVALID; + + protected virtual void preshow () {} + + private void activate () { + preshow (); + _ok_volume = multimedia_volume; + + _notification.show (); + this.active = true; + + // lower the volume to just the warning level + // from the sound specs: + // "Whenever you increase volume,..., such that acoustic output would be MORE than 85 dB + sound_system_set_multimedia_volume (_options.loud_volume); + } + + private void on_user_response (IndicatorSound.WarnNotification.Response response) { + + this.active = false; + + if (response == IndicatorSound.WarnNotification.Response.OK) { + approve_high_volume (); + sound_system_set_multimedia_volume (_ok_volume); + } else { + this.cancel_pressed (this.volume_to_double(_options.loud_volume)); + } + + _ok_volume = PulseAudio.Volume.INVALID; + } + + private static double volume_to_double (PulseAudio.Volume vol) + { + double tmp = (double)(vol - PulseAudio.Volume.MUTED); + return tmp / (double)(PulseAudio.Volume.NORM - PulseAudio.Volume.MUTED); + } + + public signal void cancel_pressed (double cancel_volume); } |