public MediaKeyModule(SpotifyInstance instance) { _kh = new KeyboardHook("98"); _kh.KeyDownEvent += args => { switch (args.Key) { case Keys.MediaPlayPause: //Spotify already handles Pause...but it still might be useful in case a rogue app is blocking the keys //instance.TogglePlayState().Wait(); break; case Keys.MediaNextTrack: case Keys.MediaPreviousTrack: // The underlying API uses SendKeys to implement this so we can't exactly use that in our KeyDownEvent! break; case Keys.MediaStop: instance.Pause().Wait(); break; } }; //To ease development, don't bother enable this if started with the debugger attached. Otherwise, it seems like using keyboard // shortcuts to step around code confuse things if (!Debugger.IsAttached) { _kh.Enable(); } }
public SystemMenuUtilities(SpotifyInstance instance) { _proc = new WinEventProc(HookHandler); _mainWindowHandle = instance.MainWindowHandle; User32.GetSystemMenu(_mainWindowHandle, bRevert: true); _systemMenuHandle = User32.GetSystemMenu(_mainWindowHandle, bRevert: false); int processId; var threadId = User32.GetWindowThreadProcessId(_mainWindowHandle, out processId); var handle = SetWinEventHook(User32.WindowsEventHookType.EVENT_OBJECT_INVOKED, User32.WindowsEventHookType.EVENT_OBJECT_INVOKED, IntPtr.Zero, _proc, processId, threadId, User32.WindowsEventHookFlags.WINEVENT_OUTOFCONTEXT); _windowHook = new User32.SafeEventHookHandle(handle); AddMenuItem("Hello!", () => MessageBox.Show("HI!"), precedeWithSeparator: true); }
public LockDetector(SpotifyInstance instance) { _instance = instance; SystemEvents.SessionSwitch += SystemEvents_SessionSwitch; }
public void InstanceClosed(SpotifyInstance oldInstance) { _ni.Icon = _notRunning; _instance = null; _ni.Text = "Spotify not running"; }
public void SpotifyAvailable(SpotifyInstance instance) { _instance = instance; }
private void Tick() { //If we already have an instance, don't bother doing anything if (_currentInstance != null) { return; } //Look for a new instance var instance = SpotifyInstance.TryFind(out _currentInstance); //If we didn't find one, just bail and wait for the next tick of our timer if (instance == null) { return; } //No point in looking for more instances since we found it _timer.Enabled = false; //Setup the event for when Spotify exits var proc = instance.Process; proc.EnableRaisingEvents = true; proc.Exited += (sender, args) => { //Notify all the modules foreach (var service in _runningModules.ToList()) { //Long running instances just get told of the closed instance but stick around var longRunning = service as ILongRunningModule; if (longRunning != null) { longRunning.InstanceClosed(instance); } else { //Transient ones are cleaned up and thrown away service.Dispose(); _runningModules.Remove(service); } } //Then finally cleanup the API object and restart our timer _currentInstance.Dispose(); _currentInstance = null; _timer.Enabled = true; }; //Forward Play State Changed events to the relevant modules _currentInstance.OnPlayStateChange += (sender, args) => { foreach (var service in _runningModules.OfType <IPlayStateChanged>()) { service.OnPlayStateChanged(args); } }; //Forward Track Changed events to the relevant modules _currentInstance.OnTrackChange += (sender, args) => { foreach (var service in _runningModules.OfType <ITrackChanged>()) { service.OnTrackChanged(args.NewTrack); } }; //Notify the long running modules that a new instance has been found foreach (var service in _runningModules.Cast <ILongRunningModule>()) { service.SpotifyAvailable(instance); } //Create new instances of the transient modules foreach (var type in _transientModuleTypes) { _runningModules.Add((ISimpleModule)Activator.CreateInstance(type, instance)); } //Grab the current/initial status and pass that along to the modules var status = _currentInstance.GetStatus(); foreach (var service in _runningModules.OfType <IPlayStateChanged>()) { service.OnPlayStateChanged(new PlayStateEventArgs { Playing = status?.Playing ?? false }); } foreach (var service in _runningModules.OfType <ITrackChanged>()) { service.OnTrackChanged(status?.Track); } }