/************************************************************************** * 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; }
// сигнал от таймера: вывести номер трека // и время воспроизведения void __fastcall TForm1::TimerTimer(TObject *Sender) { int trk; // трек int min, sec; // время AnsiString st; if ( MediaPlayer->Mode == mpPlaying ) // режим воспроизведения { // получить номер воспроизводимого трека и trk = MCI_TMSF_TRACK(MediaPlayer->Position); if ( trk != Track ) // произошла смена трека { TrackInfo(); Track = trk; if ( Track > 1 ) SpeedButton1->Enabled = true; // доступна кнопка "пред.трек" if ( Track == MediaPlayer->Tracks) SpeedButton3->Enabled = false; // кнопка "след.трек" недоступна } // вывод информации о воспроизводимом треке min = MCI_TMSF_MINUTE(MediaPlayer->Position); sec = MCI_TMSF_SECOND(MediaPlayer->Position); st.printf("%d:%.2d",min,sec); Label2->Caption = st; return; } // Если дисковод открыт или в нем нет // AudioCD, то Mode == mpOpen. // Ждем диск, т.е. до тех пор пока не будет Mode == mpStopped + кол-во треков > 1 if ( (MediaPlayer->Mode == mpStopped) && (MediaPlayer->Tracks > 1) ) { // диск вставлен Timer->Enabled = false; SpeedButton2->Enabled = true;; SpeedButton2->Tag = 0; SpeedButton3->Enabled = true; MediaPlayer->Notify = true; // получить информацию о времени звучания CD MediaPlayer->TimeFormat = tfMilliseconds; int ms = MediaPlayer->Length; AnsiString st = "Audio CD. Время звучания: "; st = st + IntToStr(MINUTE(ms)); st = st + ":" + IntToStr(SECOND(ms)); Label1->Caption = st; MediaPlayer->TimeFormat = tfTMSF; Label1->Visible = true; Track = 0; return; } // дисковод открыт или в дисководе не Audio CD if (( MediaPlayer->Mode == mpOpen )|| (MediaPlayer->Mode == mpStopped) && (MediaPlayer->Tracks == 1)) { Label1->Caption = "Вставьте Audio CD"; if ( Label1->Visible ) Label1->Visible = false; else Label1->Visible = true; } }
MCIERROR WINAPI fake_mciSendCommandA(MCIDEVICEID IDDevice, UINT uMsg, DWORD_PTR fdwCommand, DWORD_PTR dwParam) { char cmdbuf[1024]; dprintf("mciSendCommandA(IDDevice=%p, uMsg=%p, fdwCommand=%p, dwParam=%p)\r\n", IDDevice, uMsg, fdwCommand, dwParam); if (fdwCommand & MCI_NOTIFY) { dprintf(" MCI_NOTIFY\r\n"); } if (fdwCommand & MCI_WAIT) { dprintf(" MCI_WAIT\r\n"); } if (uMsg == MCI_OPEN) { LPMCI_OPEN_PARMS parms = (LPVOID)dwParam; dprintf(" MCI_OPEN\r\n"); if (fdwCommand & MCI_OPEN_ALIAS) { dprintf(" MCI_OPEN_ALIAS\r\n"); } if (fdwCommand & MCI_OPEN_SHAREABLE) { dprintf(" MCI_OPEN_SHAREABLE\r\n"); } if (fdwCommand & MCI_OPEN_TYPE_ID) { dprintf(" MCI_OPEN_TYPE_ID\r\n"); if (LOWORD(parms->lpstrDeviceType) == MCI_DEVTYPE_CD_AUDIO) { dprintf(" Returning magic device id for MCI_DEVTYPE_CD_AUDIO\r\n"); parms->wDeviceID = MAGIC_DEVICEID; return 0; } } if (fdwCommand & MCI_OPEN_TYPE && !(fdwCommand & MCI_OPEN_TYPE_ID)) { dprintf(" MCI_OPEN_TYPE\r\n"); dprintf(" -> %s\r\n", parms->lpstrDeviceType); if (strcmp(parms->lpstrDeviceType, "cdaudio") == 0) { dprintf(" Returning magic device id for MCI_DEVTYPE_CD_AUDIO\r\n"); parms->wDeviceID = MAGIC_DEVICEID; return 0; } } } if (IDDevice == MAGIC_DEVICEID || IDDevice == 0 || IDDevice == 0xFFFFFFFF) { if (uMsg == MCI_SET) { LPMCI_SET_PARMS parms = (LPVOID)dwParam; dprintf(" MCI_SET\r\n"); if (fdwCommand & MCI_SET_TIME_FORMAT) { dprintf(" MCI_SET_TIME_FORMAT\r\n"); time_format = parms->dwTimeFormat; if (parms->dwTimeFormat == MCI_FORMAT_BYTES) { dprintf(" MCI_FORMAT_BYTES\r\n"); } if (parms->dwTimeFormat == MCI_FORMAT_FRAMES) { dprintf(" MCI_FORMAT_FRAMES\r\n"); } if (parms->dwTimeFormat == MCI_FORMAT_HMS) { dprintf(" MCI_FORMAT_HMS\r\n"); } if (parms->dwTimeFormat == MCI_FORMAT_MILLISECONDS) { dprintf(" MCI_FORMAT_MILLISECONDS\r\n"); } if (parms->dwTimeFormat == MCI_FORMAT_MSF) { dprintf(" MCI_FORMAT_MSF\r\n"); } if (parms->dwTimeFormat == MCI_FORMAT_SAMPLES) { dprintf(" MCI_FORMAT_SAMPLES\r\n"); } if (parms->dwTimeFormat == MCI_FORMAT_TMSF) { dprintf(" MCI_FORMAT_TMSF\r\n"); } } } if (uMsg == MCI_CLOSE) { dprintf(" MCI_CLOSE\r\n"); if (player) { TerminateThread(player, 0); } playing = 0; player = NULL; } if (uMsg == MCI_PLAY) { LPMCI_PLAY_PARMS parms = (LPVOID)dwParam; static struct play_info info = { -1, -1 }; dprintf(" MCI_PLAY\r\n"); if (fdwCommand & MCI_FROM) { dprintf(" dwFrom: %d\r\n", parms->dwFrom); // FIXME: rounding to nearest track if (time_format == MCI_FORMAT_TMSF) { info.first = MCI_TMSF_TRACK(parms->dwFrom); dprintf(" TRACK %d\n", MCI_TMSF_TRACK(parms->dwFrom)); dprintf(" MINUTE %d\n", MCI_TMSF_MINUTE(parms->dwFrom)); dprintf(" SECOND %d\n", MCI_TMSF_SECOND(parms->dwFrom)); dprintf(" FRAME %d\n", MCI_TMSF_FRAME(parms->dwFrom)); } else if (time_format == MCI_FORMAT_MILLISECONDS) { info.first = 0; for (int i = 0; i < MAX_TRACKS; i++) { // FIXME: take closest instead of absolute if (tracks[i].position == parms->dwFrom / 1000) { info.first = i; } } dprintf(" mapped milliseconds to %d\n", info.first); } else { // FIXME: not really info.first = parms->dwFrom; } if (info.first < firstTrack) info.first = firstTrack; if (info.first > lastTrack) info.first = lastTrack; info.last = info.first; } if (fdwCommand & MCI_TO) { dprintf(" dwTo: %d\r\n", parms->dwTo); if (time_format == MCI_FORMAT_TMSF) { info.last = MCI_TMSF_TRACK(parms->dwTo); dprintf(" TRACK %d\n", MCI_TMSF_TRACK(parms->dwTo)); dprintf(" MINUTE %d\n", MCI_TMSF_MINUTE(parms->dwTo)); dprintf(" SECOND %d\n", MCI_TMSF_SECOND(parms->dwTo)); dprintf(" FRAME %d\n", MCI_TMSF_FRAME(parms->dwTo)); } else if (time_format == MCI_FORMAT_MILLISECONDS) { info.last = info.first; for (int i = info.first; i < MAX_TRACKS; i ++) { // FIXME: use better matching if (tracks[i].position + tracks[i].length > parms->dwFrom / 1000) { info.last = i; break; } } dprintf(" mapped milliseconds to %d\n", info.last); } else info.last = parms->dwTo; if (info.last < info.first) info.last = info.first; if (info.last > lastTrack) info.last = lastTrack; } if (info.first && (fdwCommand & MCI_FROM)) { if (player) { TerminateThread(player, 0); } playing = 0; player = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)player_main, (void *)&info, 0, NULL); } } if (uMsg == MCI_STOP) { dprintf(" MCI_STOP\r\n"); playing = 0; } if (uMsg == MCI_STATUS) { LPMCI_STATUS_PARMS parms = (LPVOID)dwParam; dprintf(" MCI_STATUS\r\n"); parms->dwReturn = 0; if (fdwCommand & MCI_TRACK) { dprintf(" MCI_TRACK\r\n"); dprintf(" dwTrack = %d\r\n", parms->dwTrack); } if (fdwCommand & MCI_STATUS_ITEM) { dprintf(" MCI_STATUS_ITEM\r\n"); if (parms->dwItem == MCI_STATUS_CURRENT_TRACK) { dprintf(" MCI_STATUS_CURRENT_TRACK\r\n"); } if (parms->dwItem == MCI_STATUS_LENGTH) { dprintf(" MCI_STATUS_LENGTH\r\n"); int seconds = tracks[parms->dwTrack].length; if (seconds) { if (time_format == MCI_FORMAT_MILLISECONDS) { parms->dwReturn = seconds * 1000; } else { parms->dwReturn = MCI_MAKE_MSF(seconds / 60, seconds % 60, 0); } } } if (parms->dwItem == MCI_CDA_STATUS_TYPE_TRACK) { dprintf(" MCI_CDA_STATUS_TYPE_TRACK\r\n"); } if (parms->dwItem == MCI_STATUS_MEDIA_PRESENT) { dprintf(" MCI_STATUS_MEDIA_PRESENT\r\n"); parms->dwReturn = lastTrack > 0; } if (parms->dwItem == MCI_STATUS_NUMBER_OF_TRACKS) { dprintf(" MCI_STATUS_NUMBER_OF_TRACKS\r\n"); parms->dwReturn = numTracks; } if (parms->dwItem == MCI_STATUS_POSITION) { dprintf(" MCI_STATUS_POSITION\r\n"); if (fdwCommand & MCI_TRACK) { // FIXME: implying milliseconds parms->dwReturn = tracks[parms->dwTrack].position * 1000; } } if (parms->dwItem == MCI_STATUS_MODE) { dprintf(" MCI_STATUS_MODE\r\n"); dprintf(" we are %s\r\n", playing ? "playing" : "NOT playing"); parms->dwReturn = playing ? MCI_MODE_PLAY : MCI_MODE_STOP; } if (parms->dwItem == MCI_STATUS_READY) { dprintf(" MCI_STATUS_READY\r\n"); } if (parms->dwItem == MCI_STATUS_TIME_FORMAT) { dprintf(" MCI_STATUS_TIME_FORMAT\r\n"); } if (parms->dwItem == MCI_STATUS_START) { dprintf(" MCI_STATUS_START\r\n"); } } dprintf(" dwReturn %d\n", parms->dwReturn); } return 0; } /* fallback */ return MCIERR_UNRECOGNIZED_COMMAND; }