From 48e92f2e9c3ffb99c24c4d729d9cc2327e458930 Mon Sep 17 00:00:00 2001 From: samzong Date: Tue, 1 Oct 2024 18:54:55 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E2=9C=A8=20feat:=20Add=20SleepManager=20to?= =?UTF-8?q?=20prevent=20system=20sleep=20during=20music=20playback?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit feat: add SleepManager to prevent system sleep during music playback Introduce a SleepManager class to manage system sleep prevention, ensuring that the application can keep playing music without interruptions. Integrate it into the AppDelegate to toggle sleep prevention via the menu. Update menu items to reflect the current state of sleep prevention. Add necessary permissions to the Info.plist for sleep management. ``` --- AppDelegate.swift | 33 ++++++++++++++----- MacMusicPlayer.xcodeproj/project.pbxproj | 4 +++ MacMusicPlayer/Info.plist | 2 ++ Managers/SleepManager.swift | 42 ++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 8 deletions(-) create mode 100644 Managers/SleepManager.swift diff --git a/AppDelegate.swift b/AppDelegate.swift index af61d7c..ea8d622 100644 --- a/AppDelegate.swift +++ b/AppDelegate.swift @@ -14,10 +14,12 @@ class AppDelegate: NSObject, NSApplicationDelegate { var statusItem: NSStatusItem? var popover: NSPopover? var playerManager: PlayerManager! + var sleepManager: SleepManager! var menu: NSMenu! func applicationDidFinishLaunching(_ notification: Notification) { playerManager = PlayerManager() + sleepManager = SleepManager() statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) @@ -51,24 +53,28 @@ class AppDelegate: NSObject, NSApplicationDelegate { menu.addItem(NSMenuItem.separator()) // Play/Pause - let playPauseItem = NSMenuItem(title: "Play", action: #selector(togglePlayPause), keyEquivalent: "") + let playPauseItem = NSMenuItem(title: "播放", action: #selector(togglePlayPause), keyEquivalent: "") menu.addItem(playPauseItem) // Previous - menu.addItem(NSMenuItem(title: "Previous", action: #selector(playPrevious), keyEquivalent: "")) + menu.addItem(NSMenuItem(title: "上一首", action: #selector(playPrevious), keyEquivalent: "")) // Next - menu.addItem(NSMenuItem(title: "Next", action: #selector(playNext), keyEquivalent: "")) - + menu.addItem(NSMenuItem(title: "下一首", action: #selector(playNext), keyEquivalent: "")) menu.addItem(NSMenuItem.separator()) // Reconfigure folder - menu.addItem(NSMenuItem(title: "Sources", action: #selector(reconfigureFolder), keyEquivalent: "s")) + menu.addItem(NSMenuItem(title: "设置音乐源", action: #selector(reconfigureFolder), keyEquivalent: "s")) + + // 防止休眠开关 + let preventSleepItem = NSMenuItem(title: "防止 Mac 休眠", action: #selector(togglePreventSleep), keyEquivalent: "") + preventSleepItem.state = sleepManager.preventSleep ? .on : .off + menu.addItem(preventSleepItem) menu.addItem(NSMenuItem.separator()) // Quit - menu.addItem(NSMenuItem(title: "Exit", action: #selector(quit), keyEquivalent: "")) + menu.addItem(NSMenuItem(title: "退出", action: #selector(quit), keyEquivalent: "")) // Set up observers for player state changes NotificationCenter.default.addObserver(self, selector: #selector(updateMenuItems), name: NSNotification.Name("TrackChanged"), object: nil) @@ -108,11 +114,11 @@ class AppDelegate: NSObject, NSApplicationDelegate { @objc func updateMenuItems() { if let trackInfoItem = menu.item(at: 0), let trackLabel = trackInfoItem.view?.subviews.first as? NSTextField { - trackLabel.stringValue = playerManager.currentTrack?.title ?? "No track selected" + trackLabel.stringValue = playerManager.currentTrack?.title ?? "未选择音乐源" } if let playPauseItem = menu.item(at: 2) { - playPauseItem.title = playerManager.isPlaying ? "Pause" : "Play" + playPauseItem.title = playerManager.isPlaying ? "暂停" : "播放" } } @@ -139,4 +145,15 @@ class AppDelegate: NSObject, NSApplicationDelegate { @objc func quit() { NSApplication.shared.terminate(self) } + @objc func togglePreventSleep() { + sleepManager.preventSleep.toggle() + if let preventSleepItem = menu.item(withTitle: "防止 Mac 休眠") { + preventSleepItem.state = sleepManager.preventSleep ? .on : .off + } + } + + // 添加这个方法来确保应用保持活跃状态 + func applicationWillTerminate(_ aNotification: Notification) { + sleepManager.preventSleep = false + } } diff --git a/MacMusicPlayer.xcodeproj/project.pbxproj b/MacMusicPlayer.xcodeproj/project.pbxproj index 44176d6..0ed460c 100644 --- a/MacMusicPlayer.xcodeproj/project.pbxproj +++ b/MacMusicPlayer.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 991C44522C9A9E1600F2BB76 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 991C44512C9A9E1600F2BB76 /* ContentView.swift */; }; 991C44542C9A9E2A00F2BB76 /* ControlOverlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 991C44532C9A9E2A00F2BB76 /* ControlOverlay.swift */; }; 991C445D2C9AB7FA00F2BB76 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 991C445C2C9AB7FA00F2BB76 /* AppDelegate.swift */; }; + 99C304BA2CABDEAB00D7B495 /* SleepManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 99C304B92CABDEAB00D7B495 /* SleepManager.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -23,6 +24,7 @@ 991C44512C9A9E1600F2BB76 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 991C44532C9A9E2A00F2BB76 /* ControlOverlay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ControlOverlay.swift; sourceTree = ""; }; 991C445C2C9AB7FA00F2BB76 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 99C304B92CABDEAB00D7B495 /* SleepManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SleepManager.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ @@ -83,6 +85,7 @@ isa = PBXGroup; children = ( 991C444D2C9A9DEE00F2BB76 /* PlayerManager.swift */, + 99C304B92CABDEAB00D7B495 /* SleepManager.swift */, ); path = Managers; sourceTree = ""; @@ -191,6 +194,7 @@ 991C44522C9A9E1600F2BB76 /* ContentView.swift in Sources */, 991C44542C9A9E2A00F2BB76 /* ControlOverlay.swift in Sources */, 991C443B2C9A9C6E00F2BB76 /* MacMusicPlayerApp.swift in Sources */, + 99C304BA2CABDEAB00D7B495 /* SleepManager.swift in Sources */, 991C444E2C9A9DEE00F2BB76 /* PlayerManager.swift in Sources */, 991C44502C9A9E0400F2BB76 /* Track.swift in Sources */, ); diff --git a/MacMusicPlayer/Info.plist b/MacMusicPlayer/Info.plist index db9c907..185ada3 100644 --- a/MacMusicPlayer/Info.plist +++ b/MacMusicPlayer/Info.plist @@ -23,5 +23,7 @@ audio + NSPowerManagementUsageDescription + MacMusicPlayer 需要权限来防止系统休眠,以确保音乐播放不被中断。 diff --git a/Managers/SleepManager.swift b/Managers/SleepManager.swift new file mode 100644 index 0000000..7e28862 --- /dev/null +++ b/Managers/SleepManager.swift @@ -0,0 +1,42 @@ +// +// SleepManager.swift +// MacMusicPlayer +// +// Created by X on 10/1/24. +// + +import Foundation +import IOKit.pwr_mgt + +class SleepManager: ObservableObject { + @Published var preventSleep = false { + didSet { + updateSleepAssertion() + } + } + + private var assertionID: IOPMAssertionID = 0 + + func updateSleepAssertion() { + if preventSleep { + createAssertion() + } else { + releaseAssertion() + } + } + + private func createAssertion() { + let reason = "MacMusicPlayer is preventing display sleep" + IOPMAssertionCreateWithName(kIOPMAssertionTypePreventUserIdleDisplaySleep as CFString, + IOPMAssertionLevel(kIOPMAssertionLevelOn), + reason as CFString, + &assertionID) + } + + private func releaseAssertion() { + if assertionID != 0 { + IOPMAssertionRelease(assertionID) + assertionID = 0 + } + } +} From cac4390aea36f626ef982f0e4500e2c24754ae0e Mon Sep 17 00:00:00 2001 From: samzong Date: Tue, 1 Oct 2024 18:57:00 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E2=9C=A8=20feat:=20Add=20support=20for=20p?= =?UTF-8?q?reventing=20Mac=20sleep=20in=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update README.md to include a new feature that prevents Mac from sleeping with a single click. This enhances user experience by allowing uninterrupted music playback. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index fcdc226..42197c1 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ MacMusicPlayer 是一个简洁、轻量级的 macOS 音乐播放器,设计为 - 📂 随时重新配置音乐文件夹 - 🎨 简洁的用户界面,最小化干扰 +- 😴 支持防止 Mac 休眠(一键开启) + ## 安装 1. 下载最新的 MacMusicPlayer.dmg 文件。