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