淦!
首先代码是不完整的, 我还是没能成功设置音量, 除此之外, 别的倒是挺顺利的, 当前实现的功能如下:
播放 暂停 还原 停止 获取进度 获取长度 设置进度 获取播放状态
内容:
- 本项目的仓库在: SlimeNull/AudioTest, 在这里下载哦, 别忘了还原 nuget 包, 因为用了 NAudio 库.
> 音乐播放 Demo:
- 先放图吧:
首先左上角是打开文件的, 然后 PlayType 是播放方式, 我现在让它支持 3 种, 一种是SoundPlayer, 然后是 MCI, 然后是 NAudio 库. 实现了播放, 暂停, 停止, 移除, 进度调整到开头, 进度调整(就那个track bar), 同步播放(如果点了这个, UI线程会阻塞的哦), 获取音乐长度, 获取播放状态, 获取播放位置, 重复播放. 不同的功能对不同的播放种类支持性不同, 所以, 如果你按下了按钮, 没反应, 也没报错, 那就是它不支持这个功能(也就是代码里没有写)'
下载代码, 请看前面的链接.↑跳转↑
> MCI 播放器封装:
- 上边的窗体程序就体现了封装类所实现的所有功能喔, 所以试试吧, 你也可以直接粘贴下面的代码, 但是cs文件的名称, 如果可以的话, 我希望你命名为 “Null.MciPlayer” (没错就是我的名字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
using System; using System.IO; using System.Runtime.InteropServices; namespace Null.MciPlayer { public class MciPlayer : IDisposable { [DllImport("kernel32.dll", EntryPoint = "GetShortPathNameW", CharSet = CharSet.Unicode)] extern static short GetShortPath(string longPath, string buffer, int bufferSize); [DllImport("winmm.dll", EntryPoint = "mciSendString", CharSet = CharSet.Unicode)] extern static int MciSendString(string command, string buffer, int bufferSize, IntPtr callback); bool TryGetShortPath(string longPath, out string shortPath) { shortPath = null; short reqLen = GetShortPath(longPath, null, 0); // 指定 null与0, 则返回需要的长度 if (reqLen == 0) return false; shortPath = new string('\0', reqLen); // 声明缓冲 short rstLen = GetShortPath(longPath, shortPath, reqLen); // 转换 if (rstLen == 0 || rstLen == reqLen) return false; shortPath = shortPath.TrimEnd('\0'); return true; } private string longpath; private string shortName; private string aliasName; public MciPlayer() { } public MciPlayer(string path) { if (!File.Exists(path)) throw new FileNotFoundException("File not exist.", path); longpath = path; } void MciSendStringWithCheck(string command, string buffer, int bufferSize, IntPtr callback) { int err = MciSendString(command, buffer, bufferSize, callback); if (err != 0) throw new MciException(err); } string StatusInfo(string info) { string buffer = new string('\0', 32); MciSendStringWithCheck($"status {aliasName} {info}", buffer, 32, IntPtr.Zero); return buffer.TrimEnd('\0'); } public string DevicePath { get => longpath; } public string DeviceShortPath { get => shortName; } public string AliasName { get => aliasName; } public bool SetDevicePath(string longpath) { if (aliasName != null) return false; this.longpath = longpath; return true; } public void Open() { if (!TryGetShortPath(longpath, out shortName)) throw new Exception("Get short path faield when initializing."); aliasName = $"nmci{DateTime.Now.Ticks}"; MciSendStringWithCheck($"open {shortName} alias {aliasName}", null, 0, IntPtr.Zero); } public void Close() { MciSendStringWithCheck($"close {aliasName}", null, 0, IntPtr.Zero); aliasName = null; } public void Play() { MciSendStringWithCheck($"play {aliasName}", null, 0, IntPtr.Zero); } public void Resume() { MciSendStringWithCheck($"resume {aliasName}", null, 0, IntPtr.Zero); } public void Pause() { MciSendStringWithCheck($"pause {aliasName}", null, 0, IntPtr.Zero); } public void Stop() { MciSendStringWithCheck($"stop {aliasName}", null, 0, IntPtr.Zero); } public int GetPosition() { return int.Parse(StatusInfo("position")); } public int GetLength() { return int.Parse(StatusInfo("length")); } public PlaybackState GetState() { switch (StatusInfo("mode").ToLower()) { case "playing": return PlaybackState.Playing; case "paused": return PlaybackState.Paused; case "stopped": return PlaybackState.Stopped; default: return PlaybackState.Invalid; } } public void PlayWait() { MciSendStringWithCheck($"play {aliasName} wait", null, 0, IntPtr.Zero); } public void PlayRepeat() { MciSendStringWithCheck($"play {aliasName} repeat", null, 0, IntPtr.Zero); } public void Seek(int position) { MciSendStringWithCheck($"seek {aliasName} to {position}", null, 0, IntPtr.Zero); } public void SeekToStart() { MciSendStringWithCheck($"seek {aliasName} to start", null, 0, IntPtr.Zero); } public void SetSeekMode(bool fExact) { MciSendStringWithCheck($"set {aliasName} seek exactly {(fExact ? "on" : "off")}", null, 0, IntPtr.Zero); } public void Dispose() { if (aliasName != null) Close(); } } public enum PlaybackState { Stopped, Playing, Paused, Invalid = -1, } public class MciException : Exception { private MciError err; public int ErrorId { get => (int)err; } public string ErrorName { get => err.ToString(); } public override string Message { get => ErrorName; } public MciException() { } public MciException(int errorId) { if (Enum.IsDefined(typeof(MciError), errorId)) err = (MciError)errorId; else throw new ArgumentOutOfRangeException("不是正确的错误ID"); } public MciException(string errorName) { if (!Enum.TryParse<MciError>(errorName, out err)) throw new ArgumentOutOfRangeException("不是正确的错误ID"); } enum MciError { MCIERR_NO_ERROR = 0, MCIERR_INVALID_DEVICE_ID = 257, MCIERR_UNRECOGNIZED_KEYWORD = 259, MCIERR_UNRECOGNIZED_COMMAND = 261, MCIERR_HARDWARE = 262, MCIERR_INVALID_DEVICE_NAME = 263, MCIERR_OUT_OF_MEMORY = 264, MCIERR_DEVICE_OPEN = 265, MCIERR_CANNOT_LOAD_DRIVER = 266, MCIERR_MISSING_COMMAND_STRING = 267, MCIERR_PARAM_OVERFLOW = 268, MCIERR_MISSING_STRING_ARGUMENT = 269, MCIERR_BAD_INTEGER = 270, MCIERR_PARSER_INTERNAL = 271, MCIERR_DRIVER_INTERNAL = 272, MCIERR_MISSING_PARAMETER = 273, MCIERR_UNSUPPORTED_FUNCTION = 274, MCIERR_FILE_NOT_FOUND = 275, MCIERR_DEVICE_NOT_READY = 276, MCIERR_INTERNAL = 277, MCIERR_DRIVER = 278, MCIERR_CANNOT_USE_ALL = 279, MCIERR_MULTIPLE = 280, MCIERR_EXTENSION_NOT_FOUND = 281, MCIERR_OUTOFRANGE = 282, MCIERR_FLAGS_NOT_COMPATIBLE = 284, MCIERR_FILE_NOT_SAVED = 286, MCIERR_DEVICE_TYPE_REQUIRED = 287, MCIERR_DEVICE_LOCKED = 288, MCIERR_DUPLICATE_ALIAS = 289, MCIERR_BAD_CONSTANT = 290, MCIERR_MUST_USE_SHAREABLE = 291, MCIERR_MISSING_DEVICE_NAME = 292, MCIERR_BAD_TIME_FORMAT = 293, MCIERR_NO_CLOSING_QUOTE = 294, MCIERR_DUPLICATE_FLAGS = 295, MCIERR_INVALID_FILE = 296, MCIERR_NULL_PARAMETER_BLOCK = 297, MCIERR_UNNAMED_RESOURCE = 298, MCIERR_NEW_REQUIRES_ALIAS = 299, MCIERR_NOTIFY_ON_AUTO_OPEN = 300, MCIERR_NO_ELEMENT_ALLOWED = 301, MCIERR_NONAPPLICABLE_FUNCTION = 302, MCIERR_ILLEGAL_FOR_AUTO_OPEN = 303, MCIERR_FILENAME_REQUIRED = 304, MCIERR_EXTRA_CHARACTERS = 305, MCIERR_DEVICE_NOT_INSTALLED = 306, MCIERR_GET_CD = 307, MCIERR_SET_CD = 308, MCIERR_SET_DRIVE = 309, MCIERR_DEVICE_LENGTH = 310, MCIERR_DEVICE_ORD_LENGTH = 311, MCIERR_NO_INTEGER = 312, MCIERR_WAVE_OUTPUTSINUSE = 320, MCIERR_WAVE_SETOUTPUTINUSE = 321, MCIERR_WAVE_INPUTSINUSE = 322, MCIERR_WAVE_SETINPUTINUSE = 323, MCIERR_WAVE_OUTPUTUNSPECIFIED = 324, MCIERR_WAVE_INPUTUNSPECIFIED = 325, MCIERR_WAVE_OUTPUTSUNSUITABLE = 326, MCIERR_WAVE_SETOUTPUTUNSUITABLE = 327, MCIERR_WAVE_INPUTSUNSUITABLE = 328, MCIERR_WAVE_SETINPUTUNSUITABLE = 329, MCIERR_SEQ_DIV_INCOMPATIBLE = 336, MCIERR_SEQ_PORT_INUSE = 337, MCIERR_SEQ_PORT_NONEXISTENT = 338, MCIERR_SEQ_PORT_MAPNODEVICE = 339, MCIERR_SEQ_PORT_MISCERROR = 340, MCIERR_SEQ_TIMER = 341, MCIERR_SEQ_PORTUNSPECIFIED = 342, MCIERR_SEQ_NOMIDIPRESENT = 343, MCIERR_NO_WINDOW = 346, MCIERR_CREATEWINDOW = 347, MCIERR_FILE_READ = 348, MCIERR_FILE_WRITE = 349, MCIERR_NO_IDENTITY = 350, } } }
如果有什么建议或者这个类有可改进的地方, 欢迎留言哦~ n(*≧▽≦*)n