// created on 17/05/2002 at 19:18 using System; using System.Runtime.InteropServices; using System.Text; namespace CD { struct TOC { public uint min; public uint sec; public uint frames; public TOC(uint AFrames) { frames = AFrames % 75; AFrames = AFrames / 75; sec = AFrames % 60; AFrames = AFrames / 60; min = AFrames; } public TOC(string TOCString) { min = uint.Parse(TOCString.Substring(0, 2)); sec = uint.Parse(TOCString.Substring(3, 2)); frames = uint.Parse(TOCString.Substring(6, 2)); } public override string ToString() { return min.ToString() + ":" + sec.ToString() + ":" + frames.ToString(); } } class CDInfo { // imports from winmm.dll [ DllImport( "winmm.dll", EntryPoint="mciSendStringA", CharSet=CharSet.Ansi )] protected static extern int mciSendString(string lpstrCommand, StringBuilder lpstrReturnString, int uReturnLength, IntPtr hwndCallback); [ DllImport( "winmm.dll", EntryPoint="mciGetErrorStringA", CharSet=CharSet.Ansi )] protected static extern int mciGetErrorString(int dwError, StringBuilder lpstrBuffer, int uLength); private string Alias; // constructor public CDInfo(char Drive) { Alias = Guid.NewGuid().ToString(); SendString("open " + Drive + ":\\ type cdaudio shareable wait alias " + Alias); } public CDInfo() { Alias = Guid.NewGuid().ToString(); SendString("open cdaudio shareable wait alias " + Alias); } ~CDInfo() { Close(); } public void Close() { SendAliasedString("close"); } protected string SendAliasedString(string Cmd, string Params) { return SendString(Cmd + " " + Alias + " " + Params); } protected string SendAliasedString(string Cmd) { return SendString(Cmd + " " + Alias); } protected string SendString(string Cmd) { int ret; StringBuilder buffer = new StringBuilder(255); ret = mciSendString(Cmd, buffer, buffer.Capacity, IntPtr.Zero); if (ret != 0) throw new Exception(GetMciError(ret)); return buffer.ToString(); } protected string GetMciError(int errorCode) { StringBuilder buffer = new StringBuilder(255); if (mciGetErrorString(errorCode, buffer, buffer.Capacity) == 0) return ""; return buffer.ToString(); } public uint DiscID() { TOC[] TOCList = new TOC[100]; // for each track, get position (starting location) for (uint Loop = 1; Loop <= TotalTrackCount(); Loop++) { TOCList[Loop-1] = TrackPosition(Loop); } uint n = 0; uint i = 0; while (i < TotalTrackCount()) { uint cddb_sum = 0; uint j = (TOCList[i].min * 60) + TOCList[i].sec; while (j>0) { cddb_sum = cddb_sum + (j % 10); j = j / 10; } n = n + cddb_sum; i++; } return ((n % 0xff) << 24 | TotalCDLength() << 8 | TotalTrackCount()); } public string DiscIDHex() { return string.Format("{0:X8}", DiscID()); } public uint TOCToFrames(TOC ATOC) { return (ATOC.min*60*75) + (ATOC.sec*75) + ATOC.frames; } public uint TotalCDLength() { // get last track length TOC LLastTrack = TrackLength(TotalTrackCount()); // +1 to fix Windows MCI bug, according to cddb howto LLastTrack.frames++; // compute lead-out track position (in frame format) uint dwPos = TOCToFrames(TrackPosition(TotalTrackCount())) + TOCToFrames(LLastTrack); // save lead-out track position (in MSF format) TOC LeadOutTrack = new TOC(dwPos); return ((LeadOutTrack.min * 60) + LeadOutTrack.sec) - ((TrackPosition(1).min * 60) + TrackPosition(1).sec); } public TOC TrackLength(uint Track) { string LTrackLength = SendAliasedString("status", " length track " + Track); TOC LToc = new TOC(LTrackLength); return LToc; } public uint TotalTrackCount() { return(uint.Parse(SendAliasedString("status", "number of tracks"))); } public TOC TrackPosition(uint Track) { string trackpos = SendAliasedString("status", "position track " + Track.ToString()); TOC LToc = new TOC(trackpos); return LToc; } public void Play() { SendAliasedString("play"); } public void Pause() { SendAliasedString("pause"); } public void Stop() { SendAliasedString("stop"); SendAliasedString("seek", "to start"); } public void GotoTrack(uint Track) { bool LPlaying = Playing(); SendAliasedString("seek", "to " + TrackPosition(Track).ToString()); if (LPlaying) { Play(); } } public void Next() { uint LTrackToGoTo; if (CurrentTrack() == TotalTrackCount()) LTrackToGoTo = 1; else LTrackToGoTo = CurrentTrack()+1; GotoTrack(LTrackToGoTo); } public void Previous() { uint LTrackToGoTo; if (CurrentTrack() == 1) LTrackToGoTo = TotalTrackCount(); else LTrackToGoTo = CurrentTrack()-1; GotoTrack(LTrackToGoTo); } public uint CurrentTrack() { return uint.Parse(SendAliasedString("status", "current track")); } public bool Playing() { return (SendAliasedString("status", "mode") == "playing"); } public void Eject() { SendAliasedString("set", "door open"); } } }