static DWORD MSF_Add(DWORD d1, DWORD d2) { WORD c, m, s, f; f = MCI_MSF_FRAME(d1) + MCI_MSF_FRAME(d2); c = f / CDFRAMES_PERSEC; f = f % CDFRAMES_PERSEC; s = MCI_MSF_SECOND(d1) + MCI_MSF_SECOND(d2) + c; c = s / 60; s = s % 60; m = MCI_MSF_MINUTE(d1) + MCI_MSF_MINUTE(d2) + c; /* may be > 60 */ return MCI_MAKE_MSF(m,s,f); }
bool CDROM_Interface_Ioctl::mci_CDPosition(int *position) { *position = 0; DWORD flags = MCI_STATUS_ITEM | MCI_WAIT; MCI_STATUS_PARMS mci_status; mci_status.dwItem = MCI_STATUS_MODE; if (mci_CDioctl(MCI_STATUS, flags, &mci_status)) return true; switch (mci_status.dwReturn) { case MCI_MODE_NOT_READY: case MCI_MODE_OPEN: case MCI_MODE_STOP: return true; // not ready/undefined status case MCI_MODE_PLAY: case MCI_MODE_PAUSE: mci_status.dwItem = MCI_STATUS_POSITION; if (!mci_CDioctl(MCI_STATUS, flags, &mci_status)) { *position = MSF_TO_FRAMES( MCI_MSF_MINUTE(mci_status.dwReturn), MCI_MSF_SECOND(mci_status.dwReturn), MCI_MSF_FRAME(mci_status.dwReturn)); } return false; // no error, position read default: break; } return false; }
int PlatPlayCDDA(int track) { DWORD dwReturn; MCI_SET_PARMS mciSetParms = {0,0,0}; MCI_PLAY_PARMS mciPlayParms = {0,0,0}; MCI_STATUS_PARMS mciStatusParms = {0,0,0,0}; /* check the cdDeviceId */ if(cdDeviceID==NO_DEVICE) return SOUND_PLATFORMERROR; /* set the time format */ mciSetParms.dwTimeFormat = MCI_FORMAT_MSF; dwReturn = mciSendCommand((UINT)cdDeviceID,MCI_SET,MCI_SET_TIME_FORMAT,(DWORD)(LPVOID) &mciSetParms); if(dwReturn) { // NewOnScreenMessage("CD ERROR - TIME FORMAT"); /* error */ return SOUND_PLATFORMERROR; } /* find the length of the track... */ mciStatusParms.dwItem = MCI_STATUS_LENGTH; mciStatusParms.dwTrack = track; dwReturn = mciSendCommand((UINT)cdDeviceID,MCI_STATUS,MCI_STATUS_ITEM|MCI_TRACK,(DWORD)(LPVOID)&mciStatusParms); if(dwReturn) { /* error */ // NewOnScreenMessage("CD ERROR - GET LENGTH"); return SOUND_PLATFORMERROR; } /* set the time format */ mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF; dwReturn = mciSendCommand((UINT)cdDeviceID,MCI_SET,MCI_SET_TIME_FORMAT,(DWORD)(LPVOID) &mciSetParms); if(dwReturn) { /* error */ // NewOnScreenMessage("CD ERROR - TIME FORMAT"); return SOUND_PLATFORMERROR; } /* play the track: set up for notification when track finishes, or an error occurs */ mciPlayParms.dwFrom=MCI_MAKE_TMSF(track,0,0,0); mciPlayParms.dwTo=MCI_MAKE_TMSF(track, MCI_MSF_MINUTE(mciStatusParms.dwReturn), MCI_MSF_SECOND(mciStatusParms.dwReturn), MCI_MSF_FRAME(mciStatusParms.dwReturn)); mciPlayParms.dwCallback=(DWORD)hWndMain; dwReturn = mciSendCommand((UINT)cdDeviceID,MCI_PLAY,MCI_FROM|MCI_TO|MCI_NOTIFY,(DWORD)(LPVOID)&mciPlayParms); if(dwReturn) { /* error */ // NewOnScreenMessage("CD ERROR - PLAY"); return SOUND_PLATFORMERROR; } return 0; }
/************************************************************************** * MCICDA_CalcFrame [internal] */ static DWORD MCICDA_CalcFrame(WINE_MCICDAUDIO* wmcda, DWORD dwTime) { DWORD dwFrame = 0; UINT wTrack; CDROM_TOC toc; DWORD br; BYTE* addr; TRACE("(%p, %08X, %u);\n", wmcda, wmcda->dwTimeFormat, dwTime); switch (wmcda->dwTimeFormat) { case MCI_FORMAT_MILLISECONDS: dwFrame = ((dwTime - 1) * CDFRAMES_PERSEC + 500) / 1000; TRACE("MILLISECONDS %u\n", dwFrame); break; case MCI_FORMAT_MSF: TRACE("MSF %02u:%02u:%02u\n", MCI_MSF_MINUTE(dwTime), MCI_MSF_SECOND(dwTime), MCI_MSF_FRAME(dwTime)); dwFrame += CDFRAMES_PERMIN * MCI_MSF_MINUTE(dwTime); dwFrame += CDFRAMES_PERSEC * MCI_MSF_SECOND(dwTime); dwFrame += MCI_MSF_FRAME(dwTime); break; case MCI_FORMAT_TMSF: default: /* unknown format ! force TMSF ! ... */ wTrack = MCI_TMSF_TRACK(dwTime); if (!DeviceIoControl(wmcda->handle, IOCTL_CDROM_READ_TOC, NULL, 0, &toc, sizeof(toc), &br, NULL)) return 0; if (wTrack < toc.FirstTrack || wTrack > toc.LastTrack) return 0; TRACE("MSF %02u-%02u:%02u:%02u\n", MCI_TMSF_TRACK(dwTime), MCI_TMSF_MINUTE(dwTime), MCI_TMSF_SECOND(dwTime), MCI_TMSF_FRAME(dwTime)); addr = toc.TrackData[wTrack - toc.FirstTrack].Address; TRACE("TMSF trackpos[%u]=%d:%d:%d\n", wTrack, addr[1], addr[2], addr[3]); dwFrame = CDFRAMES_PERMIN * (addr[1] + MCI_TMSF_MINUTE(dwTime)) + CDFRAMES_PERSEC * (addr[2] + MCI_TMSF_SECOND(dwTime)) + addr[3] + MCI_TMSF_FRAME(dwTime); break; } return dwFrame; }
long cdrom_notification_routine ( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { if ( cdrom_track_repeat ) { MCI_PLAY_PARMS play_parameters; MCI_STATUS_PARMS status_parameters; DWORD value; status_parameters.dwItem = MCI_STATUS_LENGTH; status_parameters.dwTrack = cdrom_track_playing; value = mciSendCommand ( cdrom_device_id, MCI_STATUS, ( MCI_TRACK | MCI_STATUS_ITEM ), ( DWORD ) ( LPVOID ) &status_parameters ); if ( !value ) { int minutes, seconds, frames; minutes = MCI_MSF_MINUTE ( status_parameters.dwReturn ), seconds = MCI_MSF_SECOND ( status_parameters.dwReturn ), frames = MCI_MSF_FRAME ( status_parameters.dwReturn ), play_parameters.dwFrom = 0; play_parameters.dwTo = 0; play_parameters.dwFrom = MCI_MAKE_TMSF ( cdrom_track_playing, 0, 0, 0 ); play_parameters.dwTo = MCI_MAKE_TMSF ( cdrom_track_playing, minutes, seconds, frames ); play_parameters.dwCallback = ( DWORD ) application_window; mciSendCommand ( cdrom_device_id, MCI_PLAY, ( MCI_FROM | MCI_TO | MCI_NOTIFY ), ( DWORD ) ( LPVOID ) &play_parameters ); } } else { cdrom_audio_track_playing = FALSE; } return ( TRUE ); }
static void test_play(HWND hwnd) { MCIDEVICEID wDeviceID; MCI_PARMS_UNION parm; MCIERROR err, ok_hw; DWORD numtracks, track, duration; DWORD factor = winetest_interactive ? 3 : 1; char buf[1024]; memset(buf, 0, sizeof(buf)); parm.gen.dwCallback = (DWORD_PTR)hwnd; /* once to rule them all */ err = mciSendString("open cdaudio alias c notify shareable", buf, sizeof(buf), hwnd); ok(!err || err == MCIERR_CANNOT_LOAD_DRIVER || err == MCIERR_MUST_USE_SHAREABLE, "mci open cdaudio notify returned %s\n", dbg_mcierr(err)); test_notification(hwnd, "open alias notify", err ? 0 : MCI_NOTIFY_SUCCESSFUL); /* Native returns MUST_USE_SHAREABLE when there's trouble with the hardware * (e.g. unreadable disk) or when Media Player already has the device open, * yet adding that flag does not help get past this error. */ if(err) { skip("Cannot open any cdaudio device, %s.\n", dbg_mcierr(err)); return; } wDeviceID = atoi(buf); ok(!strcmp(buf,"1"), "mci open deviceId: %s, expected 1\n", buf); err = mciSendString("capability c has video notify", buf, sizeof(buf), hwnd); ok(!err, "capability video: %s\n", dbg_mcierr(err)); if(!err) ok(!strcmp(buf, "false"), "capability video is %s\n", buf); test_notification(hwnd, "capability notify", MCI_NOTIFY_SUCCESSFUL); err = mciSendString("capability c can play", buf, sizeof(buf), hwnd); ok(!err, "capability video: %s\n", dbg_mcierr(err)); if(!err) ok(!strcmp(buf, "true"), "capability play is %s\n", buf); err = mciSendString("capability c", buf, sizeof(buf), NULL); ok(err == MCIERR_MISSING_PARAMETER, "capability nokeyword: %s\n", dbg_mcierr(err)); parm.caps.dwItem = 0x4001; parm.caps.dwReturn = 0xFEEDABAD; err = mciSendCommand(wDeviceID, MCI_GETDEVCAPS, MCI_GETDEVCAPS_ITEM, (DWORD_PTR)&parm); ok(err == MCIERR_UNSUPPORTED_FUNCTION, "GETDEVCAPS %x: %s\n", parm.caps.dwItem, dbg_mcierr(err)); parm.caps.dwItem = MCI_GETDEVCAPS_DEVICE_TYPE; err = mciSendCommand(wDeviceID, MCI_GETDEVCAPS, MCI_GETDEVCAPS_ITEM, (DWORD_PTR)&parm); ok(!err, "GETDEVCAPS device type: %s\n", dbg_mcierr(err)); if(!err) ok( parm.caps.dwReturn == MCI_DEVTYPE_CD_AUDIO, "getdevcaps device type: %u\n", parm.caps.dwReturn); err = mciSendCommand(wDeviceID, MCI_RECORD, 0, (DWORD_PTR)&parm); ok(err == MCIERR_UNSUPPORTED_FUNCTION, "MCI_RECORD: %s\n", dbg_mcierr(err)); /* Wine's MCI_MapMsgAtoW crashes on MCI_SAVE without parm->lpfilename */ parm.save.lpfilename = "foo"; err = mciSendCommand(wDeviceID, MCI_SAVE, 0, (DWORD_PTR)&parm); ok(err == MCIERR_UNSUPPORTED_FUNCTION, "MCI_SAVE: %s\n", dbg_mcierr(err)); /* commands from the core set are UNSUPPORTED, others UNRECOGNIZED */ err = mciSendCommand(wDeviceID, MCI_STEP, 0, (DWORD_PTR)&parm); ok(err == MCIERR_UNRECOGNIZED_COMMAND, "MCI_STEP: %s\n", dbg_mcierr(err)); parm.status.dwItem = MCI_STATUS_TIME_FORMAT; parm.status.dwReturn = 0xFEEDABAD; err = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD_PTR)&parm); ok(!err, "STATUS time format: %s\n", dbg_mcierr(err)); if(!err) ok(parm.status.dwReturn == MCI_FORMAT_MSF, "status time default format: %ld\n", parm.status.dwReturn); /* "CD-Audio" */ err = mciSendString("info c product wait notify", buf, sizeof(buf), hwnd); ok(!err, "info product: %s\n", dbg_mcierr(err)); test_notification(hwnd, "info notify", err ? 0 : MCI_NOTIFY_SUCCESSFUL); parm.status.dwItem = MCI_STATUS_MEDIA_PRESENT; parm.status.dwReturn = 0xFEEDABAD; err = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD_PTR)&parm); ok(err || parm.status.dwReturn == TRUE || parm.status.dwReturn == FALSE, "STATUS media present: %s\n", dbg_mcierr(err)); if (parm.status.dwReturn != TRUE) { skip("No CD-ROM in drive.\n"); return; } parm.status.dwItem = MCI_STATUS_MODE; err = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD_PTR)&parm); ok(!err, "STATUS mode: %s\n", dbg_mcierr(err)); switch(parm.status.dwReturn) { case MCI_MODE_NOT_READY: skip("CD-ROM mode not ready (DVD in drive?)\n"); return; case MCI_MODE_OPEN: /* should not happen with MEDIA_PRESENT */ skip("CD-ROM drive is open\n"); /* set door closed may not work. */ return; default: /* play/record/seek/pause */ ok(parm.status.dwReturn==MCI_MODE_STOP, "STATUS mode is %lx\n", parm.status.dwReturn); /* fall through */ case MCI_MODE_STOP: /* normal */ break; } /* Initial mode is "stopped" with a CD in drive */ err = mciSendString("status c mode", buf, sizeof(buf), hwnd); ok(!err, "status mode: %s\n", dbg_mcierr(err)); if(!err) ok(!strcmp(buf, "stopped"), "status mode is initially %s\n", buf); err = mciSendString("status c ready", buf, sizeof(buf), hwnd); ok(!err, "status ready: %s\n", dbg_mcierr(err)); if(!err) ok(!strcmp(buf, "true"), "status ready with media is %s\n", buf); err = mciSendString("info c product identity", buf, sizeof(buf), hwnd); ok(!err, "info 2flags: %s\n", dbg_mcierr(err)); /* not MCIERR_FLAGS_NOT_COMPATIBLE */ /* Precedence rule p>u>i verified experimentally, not tested here. */ err = mciSendString("info c identity", buf, sizeof(buf), hwnd); ok(!err || err == MCIERR_HARDWARE, "info identity: %s\n", dbg_mcierr(err)); /* a blank disk causes MCIERR_HARDWARE and other commands to fail likewise. */ ok_hw = err; err = mciSendString("info c upc", buf, sizeof(buf), hwnd); ok(err == ok_hw || err == MCIERR_NO_IDENTITY, "info upc: %s\n", dbg_mcierr(err)); parm.status.dwItem = MCI_STATUS_NUMBER_OF_TRACKS; parm.status.dwReturn = 0; err = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD_PTR)&parm); ok(err == ok_hw, "STATUS number of tracks: %s\n", dbg_mcierr(err)); numtracks = parm.status.dwReturn; /* cf. MAXIMUM_NUMBER_TRACKS */ ok(0 < numtracks && numtracks <= 99, "number of tracks=%ld\n", parm.status.dwReturn); err = mciSendString("status c length", buf, sizeof(buf), hwnd); ok(err == ok_hw, "status length: %s\n", dbg_mcierr(err)); if(!err) trace("CD length %s\n", buf); if(err) { /* MCIERR_HARDWARE when given a blank disk */ skip("status length %s (blank disk?)\n", dbg_mcierr(ok_hw)); return; } /* Linux leaves the drive at some random position, * native initialises to the start position below. */ err = mciSendString("status c position", buf, sizeof(buf), hwnd); ok(!err, "status position: %s\n", dbg_mcierr(err)); if(!err) todo_wine ok(!strcmp(buf, "00:02:00") || !strcmp(buf, "00:02:33") || !strcmp(buf, "00:03:00"), "status position initially %s\n", buf); /* 2 seconds is the initial position even with data tracks. */ err = mciSendString("status c position start notify", buf, sizeof(buf), hwnd); ok(err == ok_hw, "status position start: %s\n", dbg_mcierr(err)); if(!err) ok(!strcmp(buf, "00:02:00") || !strcmp(buf, "00:02:33") || !strcmp(buf, "00:03:00"), "status position start %s\n", buf); test_notification(hwnd, "status notify", err ? 0 : MCI_NOTIFY_SUCCESSFUL); err = mciSendString("status c position start track 1 notify", buf, sizeof(buf), hwnd); ok(err == MCIERR_FLAGS_NOT_COMPATIBLE, "status position start: %s\n", dbg_mcierr(err)); test_notification(hwnd, "status 2flags", err ? 0 : MCI_NOTIFY_SUCCESSFUL); err = mciSendString("play c from 00:02:00 to 00:01:00 notify", buf, sizeof(buf), hwnd); todo_wine ok(err == MCIERR_OUTOFRANGE, "play 2s to 1s: %s\n", dbg_mcierr(err)); test_notification(hwnd, "play 2s to 1s", err ? 0 : MCI_NOTIFY_SUCCESSFUL); err = mciSendString("resume c", buf, sizeof(buf), hwnd); ok(err == MCIERR_HARDWARE || /* Win9x */ err == MCIERR_UNSUPPORTED_FUNCTION, "resume without play: %s\n", dbg_mcierr(err)); /* not NONAPPLICABLE_FUNCTION */ /* vmware with a .iso (data-only) yields no error on NT/w2k */ err = mciSendString("seek c wait", buf, sizeof(buf), hwnd); ok(err == MCIERR_MISSING_PARAMETER, "seek noflag: %s\n", dbg_mcierr(err)); err = mciSendString("seek c to start to end", buf, sizeof(buf), hwnd); ok(err == MCIERR_FLAGS_NOT_COMPATIBLE || broken(!err), "seek to start+end: %s\n", dbg_mcierr(err)); /* Win9x only errors out with Seek to start to <position> */ /* set Wine to a defined position before play */ err = mciSendString("seek c to start notify", buf, sizeof(buf), hwnd); ok(!err, "seek to start: %s\n", dbg_mcierr(err)); test_notification(hwnd, "seek to start", err ? 0 : MCI_NOTIFY_SUCCESSFUL); /* Win9X Status position / current track then sometimes report the end position / track! */ err = mciSendString("status c mode", buf, sizeof(buf), hwnd); ok(!err, "status mode: %s\n", dbg_mcierr(err)); if(!err) ok(!strcmp(buf, "stopped"), "status mode after seek is %s\n", buf); /* MCICDA ignores MCI_SET_VIDEO * One xp machine ignored SET_AUDIO, one w2k and one w7 machine honoured it * and simultaneously toggled the mute button in the mixer control panel. * Or does it only depend on the HW, not the OS? */ err = mciSendString("set c video audio all on", buf, sizeof(buf), hwnd); ok(!err, "set video/audio: %s\n", dbg_mcierr(err)); err = mciSendString("set c time format ms", buf, sizeof(buf), hwnd); ok(!err, "set time format ms: %s\n", dbg_mcierr(err)); memset(buf, 0, sizeof(buf)); err = mciSendString("status c position start", buf, sizeof(buf), hwnd); ok(!err, "status position start (ms): %s\n", dbg_mcierr(err)); duration = atoi(buf); if(!err) ok(duration > 2000, "status position initially %sms\n", buf); /* 00:02:00 corresponds to 2001 ms, 02:33 -> 2441 etc. */ err = mciSendString("status c position start track 1", buf, sizeof(buf), hwnd); ok(err == MCIERR_FLAGS_NOT_COMPATIBLE, "status position start+track: %s\n", dbg_mcierr(err)); err = mciSendString("status c notify wait", buf, sizeof(buf), hwnd); ok(err == MCIERR_MISSING_PARAMETER, "status noflag: %s\n", dbg_mcierr(err)); err = mciSendString("status c length track 1", buf, sizeof(buf), hwnd); ok(!err, "status length (ms): %s\n", dbg_mcierr(err)); if(!err) { trace("track #1 length %sms\n", buf); duration = atoi(buf); } else duration = 2001; /* for the position test below */ if (0) { /* causes some native systems to return Seek and Play with MCIERR_HARDWARE */ /* depending on capability can eject only? */ err = mciSendString("set c door closed notify", buf, sizeof(buf), hwnd); ok(!err, "set door closed: %s\n", dbg_mcierr(err)); test_notification(hwnd, "door closed", err ? 0 : MCI_NOTIFY_SUCCESSFUL); } /* Changing the disk while the MCI device is open causes the Status * command to report stale data. Native obviously caches the TOC. */ /* status type track is localised, strcmp("audio|other") may fail. */ parm.status.dwItem = MCI_CDA_STATUS_TYPE_TRACK; parm.status.dwTrack = 1; parm.status.dwReturn = 0xFEEDABAD; err = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM|MCI_TRACK, (DWORD_PTR)&parm); ok(!err, "STATUS type track 1: %s\n", dbg_mcierr(err)); ok(parm.status.dwReturn==MCI_CDA_TRACK_OTHER || parm.status.dwReturn==MCI_CDA_TRACK_AUDIO, "unknown track type %lx\n", parm.status.dwReturn); if (parm.status.dwReturn == MCI_CDA_TRACK_OTHER) { /* Find an audio track */ parm.status.dwItem = MCI_CDA_STATUS_TYPE_TRACK; parm.status.dwTrack = numtracks; parm.status.dwReturn = 0xFEEDABAD; err = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM|MCI_TRACK, (DWORD_PTR)&parm); ok(!err, "STATUS type track %u: %s\n", numtracks, dbg_mcierr(err)); ok(parm.status.dwReturn == MCI_CDA_TRACK_OTHER || parm.status.dwReturn == MCI_CDA_TRACK_AUDIO, "unknown track type %lx\n", parm.status.dwReturn); track = (!err && parm.status.dwReturn == MCI_CDA_TRACK_AUDIO) ? numtracks : 0; /* Seek to start (above) skips over data tracks * In case of a data only CD, it seeks to the end of disk, however * another Status position a few seconds later yields MCIERR_HARDWARE. */ parm.status.dwItem = MCI_STATUS_POSITION; parm.status.dwReturn = 2000; err = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD_PTR)&parm); ok(!err || broken(err == MCIERR_HARDWARE), "STATUS position: %s\n", dbg_mcierr(err)); if(!err && track) ok(parm.status.dwReturn > duration, "Seek did not skip data tracks, position %lums\n", parm.status.dwReturn); /* dwReturn > start + length(#1) may fail because of small position report fluctuation. * On some native systems, status position fluctuates around the target position; * Successive calls return varying positions! */ err = mciSendString("set c time format msf", buf, sizeof(buf), hwnd); ok(!err, "set time format msf: %s\n", dbg_mcierr(err)); parm.status.dwItem = MCI_STATUS_LENGTH; parm.status.dwTrack = 1; parm.status.dwReturn = 0xFEEDABAD; err = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM|MCI_TRACK, (DWORD_PTR)&parm); ok(!err, "STATUS length track %u: %s\n", parm.status.dwTrack, dbg_mcierr(err)); duration = parm.status.dwReturn; trace("track #1 length: %02um:%02us:%02uframes\n", MCI_MSF_MINUTE(duration), MCI_MSF_SECOND(duration), MCI_MSF_FRAME(duration)); ok(duration>>24==0, "CD length high bits %08X\n", duration); /* TODO only with mixed CDs? */ /* play track 1 to length silently works with data tracks */ parm.play.dwFrom = MCI_MAKE_MSF(0,2,0); parm.play.dwTo = duration; /* omitting 2 seconds from end */ err = mciSendCommand(wDeviceID, MCI_PLAY, MCI_FROM|MCI_TO, (DWORD_PTR)&parm); ok(!err, "PLAY data to %08X: %s\n", duration, dbg_mcierr(err)); Sleep(1500*factor); /* Time to spin up, hopefully less than track length */ err = mciSendString("status c mode", buf, sizeof(buf), hwnd); ok(!err, "status mode: %s\n", dbg_mcierr(err)); if(!err) ok(!strcmp(buf, "stopped"), "status mode on data is %s\n", buf); } else if (parm.status.dwReturn == MCI_CDA_TRACK_AUDIO) {
/* Get CD-ROM status */ static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position) { CDstatus status; MCI_STATUS_PARMS mci_status; DWORD flags; flags = MCI_STATUS_ITEM | MCI_WAIT; mci_status.dwItem = MCI_STATUS_MODE; if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags, &mci_status) < 0 ) { status = CD_ERROR; } else { switch (mci_status.dwReturn) { case MCI_MODE_NOT_READY: case MCI_MODE_OPEN: status = CD_TRAYEMPTY; break; case MCI_MODE_STOP: #ifdef BROKEN_MCI_PAUSE if ( SDL_paused[cdrom->id] ) { status = CD_PAUSED; } else { status = CD_STOPPED; } #else status = CD_STOPPED; #endif /* BROKEN_MCI_PAUSE */ break; case MCI_MODE_PLAY: #ifdef BROKEN_MCI_PAUSE if ( SDL_paused[cdrom->id] ) { status = CD_PAUSED; } else { status = CD_PLAYING; } #else status = CD_PLAYING; #endif /* BROKEN_MCI_PAUSE */ break; case MCI_MODE_PAUSE: status = CD_PAUSED; break; default: status = CD_ERROR; break; } } if ( position ) { if ( status == CD_PLAYING || (status == CD_PAUSED) ) { mci_status.dwItem = MCI_STATUS_POSITION; if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags, &mci_status) == 0 ) { *position = MSF_TO_FRAMES( MCI_MSF_MINUTE(mci_status.dwReturn), MCI_MSF_SECOND(mci_status.dwReturn), MCI_MSF_FRAME(mci_status.dwReturn)); } else { *position = 0; } } else { *position = 0; } } return(status); }
static int SDL_SYS_CDGetTOC(SDL_CD *cdrom) { MCI_STATUS_PARMS mci_status; int i, okay; DWORD flags; okay = 0; mci_status.dwItem = MCI_STATUS_NUMBER_OF_TRACKS; flags = MCI_STATUS_ITEM | MCI_WAIT; if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags, &mci_status) == 0 ) { cdrom->numtracks = mci_status.dwReturn; if ( cdrom->numtracks > SDL_MAX_TRACKS ) { cdrom->numtracks = SDL_MAX_TRACKS; } /* Read all the track TOC entries */ flags = MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT; for ( i=0; i<cdrom->numtracks; ++i ) { cdrom->track[i].id = i+1; mci_status.dwTrack = cdrom->track[i].id; #ifdef MCI_CDA_STATUS_TYPE_TRACK mci_status.dwItem = MCI_CDA_STATUS_TYPE_TRACK; if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags, &mci_status) < 0 ) { break; } if ( mci_status.dwReturn == MCI_CDA_TRACK_AUDIO ) { cdrom->track[i].type = SDL_AUDIO_TRACK; } else { cdrom->track[i].type = SDL_DATA_TRACK; } #else cdrom->track[i].type = SDL_AUDIO_TRACK; #endif mci_status.dwItem = MCI_STATUS_POSITION; if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags, &mci_status) < 0 ) { break; } cdrom->track[i].offset = MSF_TO_FRAMES( MCI_MSF_MINUTE(mci_status.dwReturn), MCI_MSF_SECOND(mci_status.dwReturn), MCI_MSF_FRAME(mci_status.dwReturn)); cdrom->track[i].length = 0; if ( i > 0 ) { cdrom->track[i-1].length = cdrom->track[i].offset- cdrom->track[i-1].offset; } } if ( i == cdrom->numtracks ) { mci_status.dwTrack = cdrom->track[i - 1].id; mci_status.dwItem = MCI_STATUS_LENGTH; if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags, &mci_status) == 0 ) { cdrom->track[i - 1].length = MSF_TO_FRAMES( MCI_MSF_MINUTE(mci_status.dwReturn), MCI_MSF_SECOND(mci_status.dwReturn), MCI_MSF_FRAME(mci_status.dwReturn)); /* compute lead-out offset */ cdrom->track[i].offset = cdrom->track[i - 1].offset + cdrom->track[i - 1].length; cdrom->track[i].length = 0; okay = 1; } } } return(okay ? 0 : -1); }
int internal_play_cd_audio_track ( void *data ) { int track; track = *( ( int * ) data ); if ( cdrom_device_captured ) { MCI_PLAY_PARMS play_parameters; MCI_STATUS_PARMS status_parameters; DWORD value; status_parameters.dwItem = MCI_STATUS_LENGTH; status_parameters.dwTrack = track; value = mciSendCommand ( cdrom_device_id, MCI_STATUS, ( MCI_TRACK | MCI_STATUS_ITEM ), ( DWORD ) ( LPVOID ) &status_parameters ); if ( value ) { debug_log ( "Unable to get track length" ); } else { int minutes, seconds, frames; minutes = MCI_MSF_MINUTE ( status_parameters.dwReturn ), seconds = MCI_MSF_SECOND ( status_parameters.dwReturn ), frames = MCI_MSF_FRAME ( status_parameters.dwReturn ), play_parameters.dwFrom = 0; play_parameters.dwTo = 0; play_parameters.dwFrom = MCI_MAKE_TMSF ( track, 0, 0, 0 ); play_parameters.dwTo = MCI_MAKE_TMSF ( track, minutes, seconds, frames ); play_parameters.dwCallback = ( DWORD ) application_window; value = mciSendCommand ( cdrom_device_id, MCI_PLAY, ( MCI_FROM | MCI_TO | MCI_NOTIFY ), ( DWORD ) ( LPVOID ) &play_parameters ); if ( value ) { // // Ditch the cd player! // debug_log ( "Unable to play cd" ); release_cd_audio_device (); } else { cdrom_audio_track_playing = TRUE; } } } return ( TRUE ); }