Ejemplo n.º 1
0
        public ImageProvider(
            [NotNull] IMicrophoneControllerEx microphoneController,
            [NotNull] IConfigProvider <MicSwitchOverlayConfig> configProvider,
            [NotNull][Dependency(WellKnownSchedulers.UI)] IScheduler uiScheduler)
        {
            Observable.Merge(
                microphoneController.WhenAnyValue(x => x.Mute).ToUnit(),
                this.WhenAnyValue(x => x.StreamingMicrophoneImage).ToUnit(),
                this.WhenAnyValue(x => x.MutedMicrophoneImage).ToUnit())
            .ObserveOn(uiScheduler)
            .Select(x => microphoneController.Mute ?? false ? mutedMicrophoneImage : streamingMicrophoneImage)
            .SubscribeSafe(x => MicrophoneImage = x, Log.HandleUiException)
            .AddTo(Anchors);

            this.WhenAnyValue(x => x.MicrophoneImage)
            .Select(x => x as BitmapSource)
            .SelectSafeOrDefault(x => x == null ? default : Icon.FromHandle(x.ToBitmap().GetHicon()))
            .DisposePrevious()
            .SubscribeSafe(x => MicrophoneImageAsIcon = x, Log.HandleUiException)
            .AddTo(Anchors);

            configProvider.ListenTo(x => x.MicrophoneIcon)
            .ObserveOn(uiScheduler)
            .SelectSafeOrDefault(x => x.ToBitmapImage())
            .SubscribeSafe(x => StreamingMicrophoneImage = x ?? defaultMicrophoneImage, Log.HandleUiException)
            .AddTo(Anchors);

            configProvider.ListenTo(x => x.MutedMicrophoneIcon)
            .ObserveOn(uiScheduler)
            .SelectSafeOrDefault(x => x.ToBitmapImage())
            .SubscribeSafe(x => MutedMicrophoneImage = x ?? defaultMutedMicrophoneImage, Log.HandleUiException)
            .AddTo(Anchors);
        }
Ejemplo n.º 2
0
        public ImageProvider(
            [NotNull] IMicrophoneControllerEx microphoneController,
            [NotNull] IConfigProvider <MicSwitchConfig> configProvider,
            [NotNull][Dependency(WellKnownSchedulers.UI)] IScheduler uiScheduler)
        {
            this.microphoneController = microphoneController;

            configProvider.ListenTo(x => x.MicrophoneLineId)
            .ObserveOn(uiScheduler)
            .Subscribe(lineId => microphoneController.LineId = lineId)
            .AddTo(Anchors);

            Observable.Merge(
                microphoneController.WhenAnyValue(x => x.Mute).ToUnit(),
                this.WhenAnyValue(x => x.MicrophoneImage).ToUnit(),
                this.WhenAnyValue(x => x.MutedMicrophoneImage).ToUnit()
                )
            .ObserveOn(uiScheduler)
            .Subscribe(() => RaisePropertyChanged(nameof(ActiveMicrophoneImage)))
            .AddTo(Anchors);

            configProvider.ListenTo(x => x.MicrophoneIcon)
            .ObserveOn(uiScheduler)
            .SelectSafeOrDefault(x => x.ToBitmapImage())
            .Subscribe(x => MicrophoneImage = x ?? defaultMicrophoneImage)
            .AddTo(Anchors);

            configProvider.ListenTo(x => x.MutedMicrophoneIcon)
            .ObserveOn(uiScheduler)
            .SelectSafeOrDefault(x => x.ToBitmapImage())
            .Subscribe(x => MutedMicrophoneImage = x ?? defaultMutedMicrophoneImage)
            .AddTo(Anchors);
        }
Ejemplo n.º 3
0
        public MainWindowViewModel(
            [NotNull] IAppArguments appArguments,
            [NotNull] IFactory <IStartupManager, StartupManagerArgs> startupManagerFactory,
            [NotNull] IMicrophoneControllerEx microphoneController,
            [NotNull] IMicSwitchOverlayViewModel overlay,
            [NotNull] IAudioNotificationsManager audioNotificationsManager,
            [NotNull] IFactory <IAudioNotificationSelectorViewModel> audioSelectorFactory,
            [NotNull] IApplicationUpdaterViewModel appUpdater,
            [NotNull][Dependency(WellKnownWindows.MainWindow)] IWindowTracker mainWindowTracker,
            [NotNull] IConfigProvider <MicSwitchConfig> configProvider,
            [NotNull] IComplexHotkeyTracker hotkeyTracker,
            [NotNull] IMicrophoneProvider microphoneProvider,
            [NotNull] IImageProvider imageProvider,
            [NotNull] IViewController viewController,
            [NotNull][Dependency(WellKnownSchedulers.UI)] IScheduler uiScheduler)
        {
            var startupManagerArgs = new StartupManagerArgs
            {
                UniqueAppName   = $"{appArguments.AppName}{(appArguments.IsDebugMode ? "-debug" : string.Empty)}",
                ExecutablePath  = appUpdater.GetLatestExecutable().FullName,
                CommandLineArgs = appArguments.StartupArgs,
                AutostartFlag   = appArguments.AutostartFlag
            };

            this.startupManager = startupManagerFactory.Create(startupManagerArgs);

            this.appArguments         = appArguments;
            this.microphoneController = microphoneController;

            ApplicationUpdater     = appUpdater;
            this.mainWindowTracker = mainWindowTracker;
            this.configProvider    = configProvider;
            this.imageProvider     = imageProvider;
            this.RaiseWhenSourceValue(x => x.IsActive, mainWindowTracker, x => x.IsActive).AddTo(Anchors);

            AudioSelectorWhenMuted   = audioSelectorFactory.Create();
            AudioSelectorWhenUnmuted = audioSelectorFactory.Create();

            Observable.Merge(
                AudioSelectorWhenMuted.ObservableForProperty(x => x.SelectedValue, skipInitial: true),
                AudioSelectorWhenUnmuted.ObservableForProperty(x => x.SelectedValue, skipInitial: true))
            .Subscribe(() => this.RaisePropertyChanged(nameof(AudioNotification)), Log.HandleException)
            .AddTo(Anchors);

            configProvider.ListenTo(x => x.Notification)
            .ObserveOn(uiScheduler)
            .Subscribe(cfg =>
            {
                Log.Debug($"Applying new notification configuration: {cfg.DumpToTextRaw()} (current: {AudioNotification.DumpToTextRaw()})");
                AudioNotification = cfg;
            }, Log.HandleException)
            .AddTo(Anchors);

            configProvider.ListenTo(x => x.IsPushToTalkMode)
            .ObserveOn(uiScheduler)
            .Subscribe(x =>
            {
                IsPushToTalkMode = x;
                if (isPushToTalkMode)
                {
                    MuteMicrophoneCommand.Execute(true);
                }
            }, Log.HandleException)
            .AddTo(Anchors);

            configProvider.ListenTo(x => x.SuppressHotkey)
            .ObserveOn(uiScheduler)
            .Subscribe(x => SuppressHotkey = x, Log.HandleException)
            .AddTo(Anchors);

            Observable.Merge(configProvider.ListenTo(x => x.MicrophoneHotkey), configProvider.ListenTo(x => x.MicrophoneHotkeyAlt))
            .Select(x => new
            {
                Hotkey    = (HotkeyGesture) new HotkeyConverter().ConvertFrom(configProvider.ActualConfig.MicrophoneHotkey ?? string.Empty),
                HotkeyAlt = (HotkeyGesture) new HotkeyConverter().ConvertFrom(configProvider.ActualConfig.MicrophoneHotkeyAlt ?? string.Empty),
            })
            .ObserveOn(uiScheduler)
            .Subscribe(cfg =>
            {
                Log.Debug($"Setting new hotkeys configuration: {cfg.DumpToTextRaw()} (current: {hotkey}, alt: {hotkeyAlt})");
                Hotkey    = cfg.Hotkey;
                HotkeyAlt = cfg.HotkeyAlt;
            }, Log.HandleException)
            .AddTo(Anchors);

            Overlay = overlay;

            this.RaiseWhenSourceValue(x => x.RunAtLogin, startupManager, x => x.IsRegistered, uiScheduler).AddTo(Anchors);
            this.RaiseWhenSourceValue(x => x.MicrophoneVolume, microphoneController, x => x.VolumePercent, uiScheduler).AddTo(Anchors);
            this.RaiseWhenSourceValue(x => x.MicrophoneMuted, microphoneController, x => x.Mute, uiScheduler).AddTo(Anchors);
            ImageProvider = imageProvider;

            microphoneProvider.Microphones
            .ToObservableChangeSet()
            .ObserveOn(uiScheduler)
            .Bind(out var microphones)
            .Subscribe()
            .AddTo(Anchors);
            Microphones = microphones;

            this.ObservableForProperty(x => x.MicrophoneMuted, skipInitial: true)
            .DistinctUntilChanged()
            .Where(x => !MicrophoneLine.IsEmpty)
            .Skip(1)     // skip initial setup
            .Subscribe(x =>
            {
                var cfg = configProvider.ActualConfig.Notification;
                var notificationToPlay = x.Value ? cfg.On : cfg.Off;
                Log.Debug($"Playing notification {notificationToPlay} (cfg: {cfg.DumpToTextRaw()})");
                audioNotificationsManager.PlayNotification(notificationToPlay);
            }, Log.HandleUiException)
            .AddTo(Anchors);

            this.WhenAnyValue(x => x.MicrophoneLine)
            .DistinctUntilChanged()
            .Subscribe(x => microphoneController.LineId = x, Log.HandleUiException)
            .AddTo(Anchors);

            Observable.Merge(
                configProvider.ListenTo(x => x.MicrophoneLineId).ToUnit(),
                Microphones.ToObservableChangeSet().ToUnit())
            .Select(_ => configProvider.ActualConfig.MicrophoneLineId)
            .ObserveOn(uiScheduler)
            .Subscribe(configLineId =>
            {
                Log.Debug($"Microphone line configuration changed, lineId: {configLineId}, known lines: {Microphones.DumpToTextRaw()}");

                var micLine = Microphones.FirstOrDefault(line => line.Equals(configLineId));
                if (micLine.IsEmpty)
                {
                    Log.Debug($"Selecting first one of available microphone lines, known lines: {Microphones.DumpToTextRaw()}");
                    micLine = Microphones.FirstOrDefault();
                }
                MicrophoneLine = micLine;
                MuteMicrophoneCommand.ResetError();
            }, Log.HandleUiException)
            .AddTo(Anchors);

            hotkeyTracker
            .WhenAnyValue(x => x.IsActive)
            .ObserveOn(uiScheduler)
            .Subscribe(async isActive =>
            {
                if (isPushToTalkMode)
                {
                    await MuteMicrophoneCommandExecuted(!isActive);
                }
                else
                {
                    await MuteMicrophoneCommandExecuted(!MicrophoneMuted);
                }
            }, Log.HandleUiException)
            .AddTo(Anchors);

            ToggleOverlayLockCommand = CommandWrapper.Create(
                () =>
            {
                if (overlay.IsLocked && overlay.UnlockWindowCommand.CanExecute(null))
                {
                    overlay.UnlockWindowCommand.Execute(null);
                }
                else if (!overlay.IsLocked && overlay.LockWindowCommand.CanExecute(null))
                {
                    overlay.LockWindowCommand.Execute(null);
                }
            });

            ExitAppCommand = CommandWrapper.Create(
                () =>
            {
                Log.Debug("Closing application");
                configProvider.Save(configProvider.ActualConfig);
                Application.Current.Shutdown();
            });

            this.WhenAnyValue(x => x.WindowState)
            .Subscribe(x => ShowInTaskbar = x != WindowState.Minimized, Log.HandleUiException)
            .AddTo(Anchors);

            ShowAppCommand = CommandWrapper.Create(
                () =>
            {
                if (Visibility != Visibility.Visible)
                {
                    viewController.Show();
                }
                else
                {
                    viewController.Hide();
                }
            });

            OpenAppDataDirectoryCommand = CommandWrapper.Create(OpenAppDataDirectory);

            ResetOverlayPositionCommand = CommandWrapper.Create(ResetOverlayPositionCommandExecuted);

            RunAtLoginToggleCommand          = CommandWrapper.Create <bool>(RunAtLoginCommandExecuted);
            MuteMicrophoneCommand            = CommandWrapper.Create <bool>(MuteMicrophoneCommandExecuted);
            SelectMicrophoneIconCommand      = CommandWrapper.Create(SelectMicrophoneIconCommandExecuted);
            SelectMutedMicrophoneIconCommand = CommandWrapper.Create(SelectMutedMicrophoneIconCommandExecuted);
            ResetMicrophoneIconsCommand      = CommandWrapper.Create(ResetMicrophoneIconsCommandExecuted);

            var executingAssemblyName = Assembly.GetExecutingAssembly().GetName();

            Title = $"{(appArguments.IsDebugMode ? "[D]" : "")} {executingAssemblyName.Name} v{executingAssemblyName.Version}";

            WindowState = WindowState.Minimized;
            viewController
            .WhenLoaded
            .Take(1)
            .Select(() => configProvider.ListenTo(y => y.StartMinimized))
            .Switch()
            .Take(1)
            .ObserveOn(uiScheduler)
            .Subscribe(
                x =>
            {
                if (x)
                {
                    Log.Debug($"StartMinimized option is active - minimizing window, current state: {WindowState}");
                    StartMinimized = true;
                    viewController.Hide();
                }
                else
                {
                    Log.Debug($"StartMinimized option is not active - showing window as Normal, current state: {WindowState}");
                    StartMinimized = false;
                    viewController.Show();
                }
            }, Log.HandleUiException)
            .AddTo(Anchors);

            // config processing
            Observable.Merge(
                this.ObservableForProperty(x => x.MicrophoneLine, skipInitial: true).ToUnit(),
                this.ObservableForProperty(x => x.IsPushToTalkMode, skipInitial: true).ToUnit(),
                this.ObservableForProperty(x => x.AudioNotification, skipInitial: true).ToUnit(),
                this.ObservableForProperty(x => x.HotkeyAlt, skipInitial: true).ToUnit(),
                this.ObservableForProperty(x => x.Hotkey, skipInitial: true).ToUnit(),
                this.ObservableForProperty(x => x.SuppressHotkey, skipInitial: true).ToUnit(),
                this.ObservableForProperty(x => x.StartMinimized, skipInitial: true).ToUnit())
            .Throttle(ConfigThrottlingTimeout)
            .ObserveOn(uiScheduler)
            .Subscribe(() =>
            {
                var config = configProvider.ActualConfig.CloneJson();
                config.IsPushToTalkMode    = IsPushToTalkMode;
                config.MicrophoneHotkey    = (Hotkey ?? new HotkeyGesture()).ToString();
                config.MicrophoneHotkeyAlt = (HotkeyAlt ?? new HotkeyGesture()).ToString();
                config.MicrophoneLineId    = MicrophoneLine;
                config.Notification        = AudioNotification;
                config.SuppressHotkey      = SuppressHotkey;
                config.StartMinimized      = StartMinimized;
                configProvider.Save(config);
            }, Log.HandleUiException)
            .AddTo(Anchors);
        }
Ejemplo n.º 4
0
        public MicrophoneControllerViewModel(
            IMicrophoneControllerEx microphoneController,
            IMicrophoneProvider microphoneProvider,
            IComplexHotkeyTracker hotkeyTracker,
            IFactory <IHotkeyTracker> hotkeyTrackerFactory,
            IFactory <IHotkeyEditorViewModel> hotkeyEditorFactory,
            IConfigProvider <MicSwitchConfig> configProvider,
            IConfigProvider <MicSwitchHotkeyConfig> hotkeyConfigProvider,
            [Dependency(WellKnownSchedulers.UI)] IScheduler uiScheduler)
        {
            microphoneProvider.Microphones
            .ToObservableChangeSet()
            .ObserveOn(uiScheduler)
            .Bind(out var microphones)
            .SubscribeToErrors(Log.HandleUiException)
            .AddTo(Anchors);
            Microphones = microphones;

            this.microphoneController = microphoneController;
            this.hotkeyTrackerFactory = hotkeyTrackerFactory;
            this.hotkeyEditorFactory  = hotkeyEditorFactory;
            this.hotkeyConfigProvider = hotkeyConfigProvider;
            this.uiScheduler          = uiScheduler;
            MuteMicrophoneCommand     = CommandWrapper.Create <object>(MuteMicrophoneCommandExecuted);
            Hotkey           = PrepareHotkey("Mute/Un-mute microphone", x => x.Hotkey, (config, hotkeyConfig) => config.Hotkey = hotkeyConfig);
            HotkeyToggle     = PrepareHotkey("Toggle microphone state", x => x.HotkeyForToggle, (config, hotkeyConfig) => config.HotkeyForToggle = hotkeyConfig);
            HotkeyMute       = PrepareHotkey("Mute microphone", x => x.HotkeyForMute, (config, hotkeyConfig) => config.HotkeyForMute = hotkeyConfig);
            HotkeyUnmute     = PrepareHotkey("Un-mute microphone", x => x.HotkeyForUnmute, (config, hotkeyConfig) => config.HotkeyForUnmute = hotkeyConfig);
            HotkeyPushToMute = PrepareHotkey("Push-To-Mute", x => x.HotkeyForPushToMute, (config, hotkeyConfig) => config.HotkeyForPushToMute = hotkeyConfig);
            HotkeyPushToTalk = PrepareHotkey("Push-To-Talk", x => x.HotkeyForPushToTalk, (config, hotkeyConfig) => config.HotkeyForPushToTalk = hotkeyConfig);

            PrepareTracker(HotkeyMode.Click, HotkeyToggle)
            .ObservableForProperty(x => x.IsActive, skipInitial: true)
            .SubscribeSafe(x =>
            {
                Log.Debug($"[{x.Sender}] Toggling microphone state: {microphoneController}");
                microphoneController.Mute = !microphoneController.Mute;
            }, Log.HandleUiException)
            .AddTo(Anchors);

            PrepareTracker(HotkeyMode.Hold, HotkeyMute)
            .ObservableForProperty(x => x.IsActive, skipInitial: true)
            .Where(x => x.Value)
            .SubscribeSafe(x =>
            {
                Log.Debug($"[{x.Sender}] Muting microphone: {microphoneController}");
                microphoneController.Mute = true;
            }, Log.HandleUiException)
            .AddTo(Anchors);

            PrepareTracker(HotkeyMode.Hold, HotkeyUnmute)
            .ObservableForProperty(x => x.IsActive, skipInitial: true)
            .Where(x => x.Value)
            .SubscribeSafe(x =>
            {
                Log.Debug($"[{x.Sender}] Un-muting microphone: {microphoneController}");
                microphoneController.Mute = false;
            }, Log.HandleUiException)
            .AddTo(Anchors);

            PrepareTracker(HotkeyMode.Hold, HotkeyPushToTalk)
            .ObservableForProperty(x => x.IsActive, skipInitial: true)
            .SubscribeSafe(x =>
            {
                Log.Debug($"[{x.Sender}] Processing push-to-talk hotkey for microphone: {microphoneController}");
                microphoneController.Mute = !x.Value;
            }, Log.HandleUiException)
            .AddTo(Anchors);

            PrepareTracker(HotkeyMode.Hold, HotkeyPushToMute)
            .ObservableForProperty(x => x.IsActive, skipInitial: true)
            .SubscribeSafe(x =>
            {
                Log.Debug($"[{x.Sender}] Processing push-to-mute hotkey for microphone: {microphoneController}");
                microphoneController.Mute = x.Value;
            }, Log.HandleUiException)
            .AddTo(Anchors);

            this.RaiseWhenSourceValue(x => x.MicrophoneVolume, microphoneController, x => x.VolumePercent, uiScheduler).AddTo(Anchors);
            this.RaiseWhenSourceValue(x => x.MicrophoneMuted, microphoneController, x => x.Mute, uiScheduler).AddTo(Anchors);

            this.WhenAnyValue(x => x.MicrophoneLine)
            .DistinctUntilChanged()
            .SubscribeSafe(x => microphoneController.LineId = x, Log.HandleUiException)
            .AddTo(Anchors);

            hotkeyConfigProvider.ListenTo(x => x.MuteMode)
            .ObserveOn(uiScheduler)
            .Subscribe(x =>
            {
                Log.Debug($"Mute mode loaded from config: {x}");
                MuteMode = x;
            })
            .AddTo(Anchors);

            hotkeyConfigProvider.ListenTo(x => x.EnableAdvancedHotkeys)
            .ObserveOn(uiScheduler)
            .Subscribe(x => EnableAdditionalHotkeys = x)
            .AddTo(Anchors);

            hotkeyConfigProvider.ListenTo(x => x.InitialMicrophoneState)
            .ObserveOn(uiScheduler)
            .Subscribe(x => InitialMicrophoneState = x)
            .AddTo(Anchors);

            configProvider.ListenTo(x => x.VolumeControlEnabled)
            .ObserveOn(uiScheduler)
            .SubscribeSafe(x => MicrophoneVolumeControlEnabled = x, Log.HandleException)
            .AddTo(Anchors);

            Observable.Merge(
                configProvider.ListenTo(x => x.MicrophoneLineId).ToUnit(),
                Microphones.ToObservableChangeSet().ToUnit())
            .Select(_ => configProvider.ActualConfig.MicrophoneLineId)
            .ObserveOn(uiScheduler)
            .SubscribeSafe(configLineId =>
            {
                Log.Debug($"Microphone line configuration changed, lineId: {configLineId}, known lines: {Microphones.DumpToTextRaw()}");

                var micLine = Microphones.FirstOrDefault(line => line.Equals(configLineId));
                if (micLine.IsEmpty)
                {
                    Log.Debug($"Selecting first one of available microphone lines, known lines: {Microphones.DumpToTextRaw()}");
                    micLine = Microphones.FirstOrDefault();
                }
                MicrophoneLine = micLine;
                MuteMicrophoneCommand.ResetError();
            }, Log.HandleUiException)
            .AddTo(Anchors);

            this.WhenAnyValue(x => x.MuteMode, x => x.InitialMicrophoneState)
            .ObserveOn(uiScheduler)
            .SubscribeSafe(_ =>
            {
                Log.Debug($"Processing muteMode: {muteMode}, {microphoneController}.Mute: {microphoneController.Mute}");
                switch (muteMode)
                {
                case MuteMode.PushToTalk:
                    Log.Debug($"{muteMode} mute mode is enabled, un-muting microphone");
                    microphoneController.Mute = true;
                    break;

                case MuteMode.PushToMute:
                    microphoneController.Mute = false;
                    Log.Debug($"{muteMode} mute mode is enabled, muting microphone");
                    break;

                case MuteMode.ToggleMute when initialMicrophoneState == MicrophoneState.Mute:
                    Log.Debug($"{muteMode} enabled, muting microphone");
                    microphoneController.Mute = true;
                    break;

                case MuteMode.ToggleMute when initialMicrophoneState == MicrophoneState.Unmute:
                    Log.Debug($"{muteMode} enabled, un-muting microphone");
                    microphoneController.Mute = false;
                    break;

                default:
                    Log.Debug($"{muteMode} enabled, action is not needed");
                    break;
                }
            }, Log.HandleUiException)
            .AddTo(Anchors);

            hotkeyTracker
            .WhenAnyValue(x => x.IsActive)
            .Skip(1)
            .ObserveOn(uiScheduler)
            .SubscribeSafe(async isActive =>
            {
                Log.Debug($"Handling hotkey press (isActive: {isActive}), mute mode: {muteMode}");
                switch (muteMode)
                {
                case MuteMode.PushToTalk:
                    microphoneController.Mute = !isActive;
                    break;

                case MuteMode.PushToMute:
                    microphoneController.Mute = isActive;
                    break;

                case MuteMode.ToggleMute:
                    microphoneController.Mute = !microphoneController.Mute;
                    break;

                default:
                    throw new ArgumentOutOfRangeException(nameof(muteMode), muteMode, @"Unsupported mute mode");
                }
            }, Log.HandleUiException)
            .AddTo(Anchors);

            Observable.Merge(
                this.ObservableForProperty(x => x.MuteMode, skipInitial: true).ToUnit(),
                this.ObservableForProperty(x => x.EnableAdditionalHotkeys, skipInitial: true).ToUnit(),
                this.ObservableForProperty(x => x.InitialMicrophoneState, skipInitial: true).ToUnit(),
                Hotkey.ObservableForProperty(x => x.Properties, skipInitial: true).ToUnit())
            .Throttle(ConfigThrottlingTimeout)
            .ObserveOn(uiScheduler)
            .SubscribeSafe(() =>
            {
                var hotkeyConfig      = hotkeyConfigProvider.ActualConfig.CloneJson();
                hotkeyConfig.Hotkey   = Hotkey.Properties;
                hotkeyConfig.MuteMode = muteMode;
                hotkeyConfig.EnableAdvancedHotkeys  = enableAdvancedHotkeys;
                hotkeyConfig.InitialMicrophoneState = initialMicrophoneState;
                hotkeyConfigProvider.Save(hotkeyConfig);
            }, Log.HandleUiException)
            .AddTo(Anchors);

            Observable.Merge(
                this.ObservableForProperty(x => x.MicrophoneLine, skipInitial: true).ToUnit(),
                this.ObservableForProperty(x => x.MicrophoneVolumeControlEnabled, skipInitial: true).ToUnit())
            .Throttle(ConfigThrottlingTimeout)
            .ObserveOn(uiScheduler)
            .SubscribeSafe(() =>
            {
                var config = configProvider.ActualConfig.CloneJson();
                config.MicrophoneLineId     = microphoneLine;
                config.VolumeControlEnabled = microphoneVolumeControlEnabled;
                configProvider.Save(config);
            }, Log.HandleUiException)
            .AddTo(Anchors);
        }
Ejemplo n.º 5
0
        public MicSwitchOverlayViewModel(
            IOverlayWindowController overlayWindowController,
            IMicrophoneControllerEx microphoneController,
            IConfigProvider<MicSwitchOverlayConfig> configProvider,
            IImageProvider imageProvider,
            [Dependency(WellKnownSchedulers.UI)] IScheduler uiScheduler)
        {
            this.overlayWindowController = overlayWindowController;
            this.microphoneController = microphoneController;
            this.configProvider = configProvider;
            this.imageProvider = imageProvider;
            OverlayMode = OverlayMode.Transparent;
            MinSize = new Size(40, 40);
            MaxSize = new Size(300, 300);
            DefaultSize = new Size(120, 120);
            SizeToContent = SizeToContent.Manual;
            TargetAspectRatio = MinSize.Width / MinSize.Height;
            IsUnlockable = true;
            Title = "MicSwitch";
            IsEnabled = true;

            this.WhenAnyValue(x => x.IsLocked)
                .SubscribeSafe(isLocked => OverlayMode = isLocked ? OverlayMode.Transparent : OverlayMode.Layered, Log.HandleUiException)
                .AddTo(Anchors);

            this.RaiseWhenSourceValue(x => x.IsEnabled, overlayWindowController, x => x.IsEnabled).AddTo(Anchors);
            this.RaiseWhenSourceValue(x => x.Mute, microphoneController, x => x.Mute, uiScheduler).AddTo(Anchors);
            this.RaiseWhenSourceValue(x => x.MicrophoneImage, imageProvider, x => x.MicrophoneImage, uiScheduler).AddTo(Anchors);
            
            ToggleLockStateCommand = CommandWrapper.Create(
                () =>
                {
                    if (IsLocked && UnlockWindowCommand.CanExecute(null))
                    {
                        UnlockWindowCommand.Execute(null);
                    }
                    else if (!IsLocked && LockWindowCommand.CanExecute(null))
                    {
                        LockWindowCommand.Execute(null);
                    }
                    else
                    {
                        throw new ApplicationException($"Something went wrong - invalid Overlay Lock state: {new {IsLocked, IsUnlockable, CanUnlock = UnlockWindowCommand.CanExecute(null), CanLock = LockWindowCommand.CanExecute(null)  }}");
                    }
                });

            this.WhenAnyValue(x => x.IsEnabled)
                .Where(x => !IsEnabled && !IsLocked)
                .ObserveOn(uiScheduler)
                .SubscribeSafe(() => LockWindowCommand.Execute(null), Log.HandleUiException)
                .AddTo(Anchors);

            this.WhenAnyValue(x => x.OverlayWindow)
                .Where(x => x != null)
                .SubscribeSafe(x => x.LogWndProc("MicOverlay").AddTo(Anchors), Log.HandleUiException)
                .AddTo(Anchors);

            this.WhenAnyValue(x => x.OverlayVisibilityMode, x => x.Mute)
                .Select(_ =>
                {
                    return OverlayVisibilityMode switch
                    {
                        OverlayVisibilityMode.Always => true,
                        OverlayVisibilityMode.Never => false,
                        OverlayVisibilityMode.WhenMuted => Mute,
                        OverlayVisibilityMode.WhenUnmuted => !Mute,
                        _ => throw new ArgumentOutOfRangeException(nameof(overlayVisibilityMode), overlayVisibilityMode, "Unknown visibility mode")
                    };
                })
                .DistinctUntilChanged()
                .ObserveOn(uiScheduler)
                .SubscribeSafe(x => IsEnabled = x, Log.HandleUiException)
                .AddTo(Anchors);
            
            WhenLoaded
                .Take(1)
                .SubscribeSafe(_ =>
                {
                    configProvider
                        .WhenChanged
                        .ObserveOn(uiScheduler)
                        .SubscribeSafe(LoadConfig, Log.HandleUiException)
                        .AddTo(Anchors);
                    
                    Observable.Merge(
                            this.ObservableForProperty(x => x.NativeBounds, skipInitial: true).ToUnit(),
                            this.ObservableForProperty(x => x.Opacity, skipInitial: true).ToUnit(),
                            this.ObservableForProperty(x => x.OverlayVisibilityMode, skipInitial: true).ToUnit(),
                            this.ObservableForProperty(x => x.IsEnabled, skipInitial: true).ToUnit(),
                            this.ObservableForProperty(x => x.IsLocked, skipInitial: true).ToUnit())
                        .SkipUntil(WhenLoaded)
                        .Throttle(ConfigThrottlingTimeout)
                        .ObserveOn(uiScheduler)
                        .SubscribeSafe(SaveConfig, Log.HandleUiException)
                        .AddTo(Anchors);
                }, Log.HandleUiException)
                .AddTo(Anchors);
        }
Ejemplo n.º 6
0
        public MicSwitchOverlayViewModel(
            [NotNull] IOverlayWindowController overlayWindowController,
            [NotNull] IMicrophoneControllerEx microphoneController,
            [NotNull] IConfigProvider<MicSwitchConfig> configProvider,
            [NotNull] IImageProvider imageProvider,
            [NotNull] [Dependency(WellKnownSchedulers.UI)] IScheduler uiScheduler)
        {
            this.overlayWindowController = overlayWindowController;
            this.microphoneController = microphoneController;
            this.configProvider = configProvider;
            this.imageProvider = imageProvider;
            OverlayMode = OverlayMode.Transparent;
            MinSize = new Size(120, 120);
            MaxSize = new Size(300, 300);
            SizeToContent = SizeToContent.Manual;
            TargetAspectRatio = MinSize.Width / MinSize.Height;
            IsUnlockable = true;
            Title = "MicSwitch";
            WhenLoaded
                .Take(1)
                .Select(x => configProvider.WhenChanged)
                .Switch()
                .ObserveOn(uiScheduler)
                .Subscribe(ApplyConfig)
                .AddTo(Anchors);

            this.WhenAnyValue(x => x.IsLocked)
                .Subscribe(isLocked => OverlayMode = isLocked ? OverlayMode.Transparent : OverlayMode.Layered)
                .AddTo(Anchors);

            configProvider.ListenTo(x => x.MicrophoneLineId)
                .ObserveOn(uiScheduler)
                .Subscribe(lineId => { microphoneController.LineId = lineId; })
                .AddTo(Anchors);

            this.RaiseWhenSourceValue(x => x.IsEnabled, overlayWindowController, x => x.IsEnabled).AddTo(Anchors);
            this.RaiseWhenSourceValue(x => x.Mute, microphoneController, x => x.Mute, uiScheduler).AddTo(Anchors);
            this.RaiseWhenSourceValue(x => x.MicrophoneImage, imageProvider, x => x.ActiveMicrophoneImage, uiScheduler).AddTo(Anchors);
            
            ToggleLockStateCommand = CommandWrapper.Create(
                () =>
                {
                    if (IsLocked && UnlockWindowCommand.CanExecute(null))
                    {
                        UnlockWindowCommand.Execute(null);
                    }
                    else if (!IsLocked && LockWindowCommand.CanExecute(null))
                    {
                        LockWindowCommand.Execute(null);
                    }
                    else
                    {
                        throw new ApplicationException($"Something went wrong - invalid Overlay Lock state: {new {IsLocked, IsUnlockable, CanUnlock = UnlockWindowCommand.CanExecute(null), CanLock = LockWindowCommand.CanExecute(null)  }}");
                    }
                });
            
            Observable.Merge(
                    this.ObservableForProperty(x => x.Left, skipInitial: true).ToUnit(),
                    this.ObservableForProperty(x => x.Top, skipInitial: true).ToUnit(),
                    this.ObservableForProperty(x => x.Width, skipInitial: true).ToUnit(),
                    this.ObservableForProperty(x => x.Height, skipInitial: true).ToUnit(),
                    this.ObservableForProperty(x => x.IsEnabled, skipInitial: true).ToUnit(),
                    this.ObservableForProperty(x => x.IsLocked, skipInitial: true).ToUnit())
                .SkipUntil(WhenLoaded)
                .Throttle(ConfigThrottlingTimeout)
                .ObserveOn(uiScheduler)
                .Subscribe(SaveConfig, Log.HandleUiException)
                .AddTo(Anchors);

            this.WhenAnyValue(x => x.IsEnabled)
                .Where(x => !IsEnabled && !IsLocked)
                .ObserveOn(uiScheduler)
                .Subscribe(() => LockWindowCommand.Execute(null), Log.HandleUiException)
                .AddTo(Anchors);
        }