logo
несколько программ / bsp33

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

}