00001
00002 #ifdef WIN32
00003 #pragma warning (disable:4786)
00004 #endif
00005
00006 #include <windows.h>
00007 #include "API/Sound/cd_audio.h"
00008 #include <stdio.h>
00009 #include "cdaudio_win32.h"
00010
00011 void CL_CDDrive_Win32::init_cdaudio()
00012 {
00013 int i;
00014 char drive[4];
00015
00016 for (i='A'; i<='Z'; i++)
00017 {
00018 sprintf(drive, "%c:\\", i);
00019 if (GetDriveType(drive) == DRIVE_CDROM )
00020 {
00021 char name[256];
00022 GetVolumeInformation(drive, name, 256, NULL, NULL, NULL, NULL, 0);
00023
00024 CL_CDAudio::cd_drives.push_back(new CL_CDDrive_Win32(drive, name));
00025 }
00026 }
00027 }
00028
00029
00030
00031
00032
00033 CL_CDDrive_Win32::CL_CDDrive_Win32(std::string path, std::string name)
00034 {
00035 this->path = path;
00036 this->name = name;
00037 id = 0;
00038 }
00039
00040 CL_CDDrive_Win32::~CL_CDDrive_Win32()
00041 {
00042 }
00043
00044 bool CL_CDDrive_Win32::send_command(unsigned int msg, unsigned int flags, void *arg)
00045 {
00046 MCIERROR mci_error;
00047 mci_error = mciSendCommand(id, msg, flags, (DWORD) arg);
00048
00049 return mci_error == 0;
00050 }
00051
00052 bool CL_CDDrive_Win32::init()
00053 {
00054 MCI_OPEN_PARMS mci_open;
00055 memset(&mci_open, 0, sizeof(MCI_OPEN_PARMS));
00056 MCI_SET_PARMS mci_set;
00057 memset(&mci_set, 0, sizeof(MCI_SET_PARMS));
00058 DWORD flags;
00059
00060 mci_open.lpstrDeviceType = (LPCSTR) MCI_DEVTYPE_CD_AUDIO;
00061 mci_open.lpstrElementName = path.c_str();
00062
00063 flags = MCI_OPEN_TYPE |
00064 MCI_OPEN_SHAREABLE |
00065 MCI_OPEN_TYPE_ID |
00066 MCI_OPEN_ELEMENT;
00067
00068 if (!send_command(MCI_OPEN, flags, &mci_open))
00069 {
00070 flags &= ~MCI_OPEN_SHAREABLE;
00071 if (!send_command(MCI_OPEN, flags, &mci_open))
00072 {
00073 return false;
00074 }
00075 }
00076 id = mci_open.wDeviceID;
00077
00078
00079 mci_set.dwTimeFormat = MCI_FORMAT_MSF;
00080 send_command(MCI_SET, MCI_SET_TIME_FORMAT, &mci_set);
00081
00082 return read_toc();
00083 }
00084
00085 bool CL_CDDrive_Win32::read_toc()
00086 {
00087 MCI_STATUS_PARMS mci_status;
00088 int i;
00089 DWORD flags;
00090 bool retval = false;
00091
00092 mci_status.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
00093 flags = MCI_STATUS_ITEM | MCI_WAIT;
00094
00095 if (send_command(MCI_STATUS, flags, &mci_status))
00096 {
00097 num_tracks = mci_status.dwReturn;
00098 tracks.reserve(num_tracks+1);
00099
00100 flags = MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT;
00101 for (i=0; i<num_tracks;i++)
00102 {
00103 STrack track;
00104 track.id = i+1;
00105
00106 mci_status.dwTrack = id;
00107 mci_status.dwItem = MCI_CDA_STATUS_TYPE_TRACK;
00108 if (!send_command(MCI_STATUS, flags, &mci_status))
00109 {
00110 break;
00111 }
00112
00113 if (mci_status.dwReturn == MCI_CDA_TRACK_AUDIO )
00114 {
00115 track.is_audio = true;
00116 } else
00117 {
00118 track.is_audio = false;
00119 }
00120
00121 mci_status.dwItem = MCI_STATUS_POSITION;
00122 if (!send_command(MCI_STATUS, flags, &mci_status))
00123 {
00124 break;
00125 }
00126
00127 track.start_frame = MSF_TO_FRAMES(
00128 MCI_MSF_MINUTE(mci_status.dwReturn),
00129 MCI_MSF_SECOND(mci_status.dwReturn),
00130 MCI_MSF_FRAME(mci_status.dwReturn));
00131 track.length_frames = 0;
00132
00133 if (i > 0)
00134 {
00135 tracks[i-1].length_frames = track.start_frame - tracks[i-1].start_frame;
00136 }
00137 tracks.push_back(track);
00138 }
00139
00140 if (i == num_tracks)
00141 {
00142 flags &= ~MCI_TRACK;
00143 mci_status.dwItem = MCI_STATUS_LENGTH;
00144 if (send_command(MCI_STATUS, flags, &mci_status))
00145 {
00146 int offset = MSF_TO_FRAMES(
00147 MCI_MSF_MINUTE(mci_status.dwReturn),
00148 MCI_MSF_SECOND(mci_status.dwReturn),
00149 MCI_MSF_FRAME(mci_status.dwReturn));
00150
00151 STrack track;
00152 track.is_audio = false;
00153 track.start_frame = offset;
00154 track.length_frames = 0;
00155 tracks.push_back(track);
00156
00157 tracks[i-1].length_frames = offset - tracks[i-1].start_frame;
00158 retval = true;
00159 }
00160 }
00161 }
00162
00163 return retval;
00164 }
00165
00166 void CL_CDDrive_Win32::update_status()
00167 {
00168 MCI_STATUS_PARMS mci_status;
00169 DWORD flags;
00170
00171 flags = MCI_STATUS_ITEM | MCI_WAIT;
00172 mci_status.dwItem = MCI_STATUS_MODE;
00173
00174 bool update_position = false;
00175
00176 cd_playing = false;
00177 cur_track = -1;
00178 cur_frame = -1;
00179
00180 if (!send_command(MCI_STATUS, flags, &mci_status))
00181 {
00182 throw "Failed to get CD status";
00183 }
00184 else
00185 {
00186
00187 switch (mci_status.dwReturn)
00188 {
00189 case MCI_MODE_PLAY:
00190 cd_playing = true;
00191 update_position = true;
00192 break;
00193 case MCI_MODE_PAUSE:
00194 update_position = true;
00195 break;
00196 }
00197 }
00198
00199 if (update_position)
00200 {
00201 mci_status.dwItem = MCI_STATUS_POSITION;
00202 if (send_command(MCI_STATUS, flags, &mci_status))
00203 {
00204 cur_frame = MSF_TO_FRAMES(
00205 MCI_MSF_MINUTE(mci_status.dwReturn),
00206 MCI_MSF_SECOND(mci_status.dwReturn),
00207 MCI_MSF_FRAME(mci_status.dwReturn));
00208
00209 cur_track = 0;
00210 int t = 1;
00211 for (std::vector<STrack>::iterator it = tracks.begin();it!=tracks.end();it++)
00212 {
00213 if ((*it).start_frame < cur_frame && ((*it).start_frame+(*it).length_frames) > cur_frame)
00214 {
00215 cur_track = t;
00216 break;
00217 }
00218 }
00219 }
00220 }
00221 }
00222
00223 std::string CL_CDDrive_Win32::get_drive_path()
00224 {
00225 return path;
00226 }
00227
00228 std::string CL_CDDrive_Win32::get_cd_name()
00229 {
00230 return name;
00231 }
00232
00233 int CL_CDDrive_Win32::get_num_tracks()
00234 {
00235 return num_tracks;
00236 }
00237
00238 bool CL_CDDrive_Win32::is_playing()
00239 {
00240 update_status();
00241 return cd_playing;
00242 }
00243
00244 int CL_CDDrive_Win32::get_cur_track()
00245 {
00246 update_status();
00247 return cur_track;
00248 }
00249
00250 int CL_CDDrive_Win32::get_cur_frame()
00251 {
00252 update_status();
00253 return cur_frame;
00254 }
00255
00256 bool CL_CDDrive_Win32::play_tracks(int track, int end_track)
00257 {
00258 if (track < 1 || track > num_tracks) return false;
00259 if (end_track != 0 && end_track < track) return false;
00260 if (end_track == 0) end_track = num_tracks;
00261 if (end_track >= tracks.size()) end_track = tracks.size()-1;
00262
00263 return play_frames(
00264 tracks[track-1].start_frame,
00265 tracks[end_track-1].start_frame+tracks[end_track-1].length_frames);
00266 }
00267
00268 bool CL_CDDrive_Win32::play_frames(int frame, int end_frame)
00269 {
00270 MCI_PLAY_PARMS mci_play;
00271 int m, s, f;
00272 DWORD flags;
00273
00274 flags = MCI_FROM | MCI_TO | MCI_NOTIFY;
00275 mci_play.dwCallback = 0;
00276 FRAMES_TO_MSF(frame, &m, &s, &f);
00277 mci_play.dwFrom = MCI_MAKE_MSF(m, s, f);
00278 FRAMES_TO_MSF(end_frame, &m, &s, &f);
00279 mci_play.dwTo = MCI_MAKE_MSF(m, s, f);
00280
00281 return send_command(MCI_PLAY, flags, &mci_play);
00282
00283 }
00284
00285 bool CL_CDDrive_Win32::play_track(int track)
00286 {
00287 if (track < 1 || track > num_tracks) return false;
00288 return play_frames(
00289 tracks[track-1].start_frame,
00290 tracks[track-1].start_frame+tracks[track-1].length_frames);
00291 }
00292
00293 void CL_CDDrive_Win32::stop()
00294 {
00295 send_command(MCI_STOP, MCI_WAIT, NULL);
00296 }
00297
00298 void CL_CDDrive_Win32::pause()
00299 {
00300 send_command(MCI_PAUSE, MCI_WAIT, NULL);
00301 }
00302
00303 void CL_CDDrive_Win32::resume()
00304 {
00305 send_command(MCI_RESUME, MCI_WAIT, NULL);
00306 }
00307