Аппаратное обеспечение персонального компьютера© Александр Фролов, Григорий ФроловТом 33, М.: Диалог-МИФИ, 1997, 304 стр. Программа CDPLAYПрограмма CDPLAY предназначена для проигрывания дорожек звуковых компакт-дисков. При запуске этой программы необходимо указать параметр – номер блока, с которого должно выполняться проигрывание. Ниже мы привели пример запуска программы, передав ей адрес 512: CDPLAY, (c) A. Frolov, 1997 Track Red book: 512 Track Sierra: 0 MSCDEX version: 2.95 Found 1 CD Unit, start unit: G CD-ROM letters: G Started. Press any key to stop and eject CD Этот адрес мы взяли из листинга, полученного программой CDINFO, описанной в предыдущем разделе. Он был пересчитан программой CDPLAY в формат Sierra, в результате чего программа запустила проигрывание самой первой звуковой дорожки диска. Если после запуска программы и начала проигрывания нажать любую клавишу, проигрывание будет остановлено, а компакт-диск - извлечен из устройства чтения CD-ROM. Исходный текст программы CDPLAY приведен в листинге 9.2. Листинг 9.2. Файл cdplay\cdplay.с // ===================================================== // Проигрывание звуковых компакт-дисков // // (C) Фролов А.В, 1997 // // E-mail: frolov@glas.apc.org // WWW: http://www.glasnet.ru/~frolov // или // http://www.dials.ccas.ru/frolov // ===================================================== #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <dos.h> #include <memory.h> typedef unsigned char BYTE; typedef unsigned int WORD; typedef unsigned long DWORD; // Необходимо для обеспечения выравнивания // полей структур на границу байта #pragma pack(1) // Заголовок запроса для обращения к драйверу typedef struct _ReqHdr { BYTE bSize; BYTE bSubUnit; BYTE bCmd; WORD wStatus; BYTE bReserved[8]; } ReqHdr; typedef struct _PlayAudio { ReqHdr rh; BYTE bMode; DWORD dwLoc; DWORD dwSectorNum; } PlayAudio; // Запрос IOCTL Output typedef struct _IOCTL_Output { ReqHdr rh; BYTE bMediaDescriptor; DWORD lpTransferAddress; WORD wDataSize; WORD wStartSector; DWORD lpVolID; } IOCTL_Output; // Запрос на извлечение компакт-диска typedef struct _EjectDisk { BYTE bControl; } EjectDisk; #pragma pack() // Прототипы функций void GetCDLetters(BYTE *bLetters); void CallCDDriver(void *rh, int nCDUnit); int PlayAudioTrack(DWORD dwLoc, DWORD dwSectorNum, int nCDUnit); int StopAudio(int nCDUnit); int DeviceOpen(int nCDUnit); int DeviceClose(int nCDUnit); int EjectCD(int nCDUnit); DWORD Red2Sierra(DWORD dwRedLoc); // Регистры для вызова функции int86 union REGS rg; // Количество установленных устройств чтения CD-ROM int nCDUnits; // Номер первого устройства чтения CD-ROM int nCDStartUnit; // Слово состояния после вызова драйвера CD-ROM int iStatus; // Массив номеров установленных устройств CD-ROM BYTE bLetters[26]; // --------------------------------------------------- // main // Точка входа в программу // --------------------------------------------------- int main(int argc, char *argv[]) { int i; DWORD dwStartTrack; printf("CDPLAY, (c) A. Frolov, 1997\n\n"); dwStartTrack = 1; if(argc == 2) { dwStartTrack = atol(argv[1]); printf("Track Red book: %ld\n", dwStartTrack); } else { printf("Usage: CDPLAY <Red book sector address>\n"); return -1; } // Преобразование адреса сектора в формат Sierra dwStartTrack = Red2Sierra(dwStartTrack); printf("Track Sierra: %ld\n", dwStartTrack); // Проверяем, установлена ли программа MSCDEX rg.x.ax = 0x1500; rg.x.bx = 0; int86(0x2f, &rg, &rg); if(rg.x.bx == 0) { printf("MSCDEX is not installed\n"); return -1; } else { // Сохраняем общее количество устройств чтения CD-ROM nCDUnits = rg.x.bx; // Сохраняем номер первого такого устройства nCDStartUnit = rg.x.cx; // Определяем и отображаем вресию MSCDEX rg.x.ax = 0x150c; int86(0x2f, &rg, &rg); printf("MSCDEX version: %d.%d\n", rg.h.bh, rg.h.bl); // Отображаем количество найденных устройств чтения // CD-ROM и номер первого устройства printf("Found %d CD Unit, start unit: %c\n", nCDUnits, nCDStartUnit + 'A'); } // Получаем массив номеров устройств чтения CD-ROM GetCDLetters(bLetters); // Отображаем обозначения всех устройств CD-ROM printf("CD-ROM letters: "); for(i = 0; i < nCDUnits; i++) { printf("%c ", bLetters[i] + 'A'); } printf("\n"); // Открываем устройство iStatus = DeviceOpen(bLetters[0]); if(iStatus & 0x8000) { printf("DeviceOpen status: %04.4X\n", iStatus); return -1; } // Запускаем проигрывание iStatus = PlayAudioTrack(dwStartTrack, 0xffffffff, bLetters[0]); if(iStatus & 0x8000) { printf("PlayAudioTrack status: %04.4X\n", iStatus); return -1; } printf("Started. Press any key to stop and eject CD\n"); // Ожидаем, пока пользователь не нажмет клавишу getch(); // Останавливаем проигрывание iStatus = StopAudio(bLetters[0]); if(iStatus & 0x8000) { printf("StopAudio status: %04.4X\n", iStatus); return -1; } // Извлекаем диск iStatus = EjectCD(bLetters[0]); if(iStatus & 0x8000) { printf("EjectCD status: %04.4X\n", iStatus); return -1; } // Закрываем устройство iStatus = DeviceClose(bLetters[0]); if(iStatus & 0x8000) { printf("DeviceClose status: %04.4X\n", iStatus); return -1; } return 0; } // --------------------------------------------------- // PlayAudioTrack // Запуск проигрывания звукового компакт-диска // --------------------------------------------------- int PlayAudioTrack(DWORD dwLoc, DWORD dwSectorNum, int nCDUnit) { PlayAudio cmd; memset(&cmd, 0, sizeof(PlayAudio)); cmd.rh.bSize = 22; cmd.rh.bSubUnit = 0; cmd.rh.bCmd = 132; cmd.bMode = 0; cmd.dwLoc = dwLoc; cmd.dwSectorNum = dwSectorNum; CallCDDriver(&cmd, nCDUnit); return cmd.rh.wStatus; } // --------------------------------------------------- // StopAudio // Остановка проигрывания звукового компакт-диска // --------------------------------------------------- int StopAudio(int nCDUnit) { ReqHdr cmd; memset(&cmd, 0, sizeof(ReqHdr)); cmd.bSize = 13; cmd.bSubUnit = 0; cmd.bCmd = 133; CallCDDriver(&cmd, nCDUnit); return (cmd.wStatus); } // --------------------------------------------------- // DeviceOpen // Открывание устройства // --------------------------------------------------- int DeviceOpen(int nCDUnit) { ReqHdr cmd; memset(&cmd, 0, sizeof(ReqHdr)); cmd.bSize = 13; cmd.bSubUnit = 0; cmd.bCmd = 13; CallCDDriver(&cmd, nCDUnit); return (cmd.wStatus); } // --------------------------------------------------- // DeviceClose // Закрывание устройства // --------------------------------------------------- int DeviceClose(int nCDUnit) { ReqHdr cmd; memset(&cmd, 0, sizeof(ReqHdr)); cmd.bSize = 13; cmd.bSubUnit = 0; cmd.bCmd = 14; CallCDDriver(&cmd, nCDUnit); return (cmd.wStatus); } // --------------------------------------------------- // EjectCD // Извлечение компакт-диска // --------------------------------------------------- int EjectCD(int nCDUnit) { IOCTL_Output cmd; EjectDisk ed; memset(&cmd, 0, sizeof(IOCTL_Output)); cmd.rh.bSize = 14; cmd.rh.bSubUnit = 0; cmd.rh.bCmd = 12; cmd.bMediaDescriptor = 0; cmd.lpTransferAddress = (DWORD)(void far *)&ed; cmd.wDataSize = 1; cmd.wStartSector = 0; cmd.lpVolID = (DWORD)(void far *)NULL; ed.bControl = 0; CallCDDriver(&cmd, nCDUnit); return cmd.rh.wStatus; } // --------------------------------------------------- // CallCDDriver // Вызов драйвера компакт-диска // --------------------------------------------------- void CallCDDriver(void *rh, int nCDUnit) { static union REGS rg; static struct SREGS srg; segread(&srg); rg.x.ax = 0x1510; rg.x.cx = nCDUnit; rg.x.bx = FP_OFF(rh); int86x(0x2f, &rg, &rg, &srg); } // --------------------------------------------------- // GetCDLetters // Заполнение массива номерами установленных // в системе устройств чтения компакт-диска // --------------------------------------------------- void GetCDLetters(BYTE *bLetters) { static union REGS rg; static struct SREGS srg; segread(&srg); rg.x.ax = 0x150d; rg.x.bx = FP_OFF(bLetters); int86x(0x2f, &rg, &rg, &srg); } // --------------------------------------------------- // Преобразование адреса дорожки из формата Red book // в формат Sierra // --------------------------------------------------- DWORD Red2Sierra(DWORD dwRedLoc) { BYTE bMin, bSec, bFrame; bMin = (BYTE)((dwRedLoc >> 16) & 0xff); bSec = (BYTE)((dwRedLoc >> 8) & 0xff); bFrame = (BYTE)(dwRedLoc & 0xff); return (DWORD)bMin * 75 * 60 + (DWORD)bSec * 75 + (DWORD)bFrame - 150; } |