Программа 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;
}