Discussion:
Reading Audio CD Text Data
(too old to reply)
Justin
2004-02-05 00:26:06 UTC
Permalink
Anyone have an example of how to read cd text data? I am trying to use the IOCTL_CDROM_READ_TOC_EX command to return CDROM_TOC_CD_TEXT_DATA, but all I have been able to get is various errors: "The device is not ready" and "Incorrect Function" (each error with the same compiled exe but on different machines). Using the same drive handle and same audio CDs I have successfully read Track ISRCs and basic TOC info using IOCTL_CDROM_READ_Q_CHANNEL and IOCTL_CDROM_READ_TOC.

What I do is I get a handle to my cd-rom, then I lock the cd-rom drive using IOCTL_CDROM_MEDIA_REMOVAL then I read the TOC from the cd using IOCTL_CDROM_READ_TOC then I loop through each of the songs from FirstTrack to LastTrack in the TOC and I get the ISRC using IOCTL_CDROM_READ_Q_CHANNEL and print it out and get the text data using IOCTL_CDROM_READ_TOC_EX and would print it out if it worked through each iteration. Then I unlock the cd drive.

Below is the code I have in C++ that I am trying to use but getting the errors (DeviceIOControl returns FALSE and I get the text of the error with GetLastError()):

hDevice is a a HANDLE to my cd rom drive retrieved with the CreateFile function. I know it is a valid handle because I can successfully open and close the cd drive and read the TOC (first & last track numbers and TRACK_DATA items) and read the track ISRCs.

I am also curious if anyone knows how I can figure out the size I should specify of the output buffer for this command. Currently I am just setting it to 255 bytes, but don't know if that is enough or too much or what.

BOOL getTrackTextData(HANDLE& hDevice, UCHAR trackNum, CDROM_TOC_CD_TEXT_DATA& output)
{
CDROM_READ_TOC_EX inBuf;
inBuf.Format = CDROM_READ_TOC_EX_FORMAT_CDTEXT;
inBuf.Reserved1 = 0;
inBuf.Msf = 1;
inBuf.SessionTrack = trackNum;
inBuf.Reserved2 = 0;
inBuf.Reserved3 = 0;

BOOL bResult;
DWORD bytesRet;

bResult = DeviceIoControl(hDevice, IOCTL_CDROM_READ_TOC_EX, &inBuf, sizeof(inBuf), &output, 255, &bytesRet, (LPOVERLAPPED) NULL);
if (bResult)
{
printf("Success with %i bytes returned.\n", bytesRet);
}
return (bResult);
}

the above function is then called with the following (where i is a loop counter and cdDevice is the cd-rom handle):
....
CDROM_TOC_CD_TEXT_DATA trackCDText;
bReturn = getTrackTextData(cdDevice, i, trackCDText);
....

ps. sorry if this is not the best looking code, I am pretty new to c++

Thank You for any help you can provide.
John Eikanger
2004-02-11 00:46:47 UTC
Permalink
Hi, Justin

I did some research regarding your question. You should not assume a 255
byte sector size. You should specify 2048 bytes when reading in cooked
mode and 2352 bytes in raw mode. For details about the format of the data,
you should contact Phillips for their Red Book spec, more formally known as
Compact Disc-Digital Audio (CD-DA).

Unless you are actually trying to write a driver, this is not the best
place for you to post. I would suggest posting followup questions in
either microsoft.public.win32.programmer.mmedia or
microsoft.public.win32.programmer.kernel, depending on whether your focus
is I/O or multimedia.

Thank you for choosing the MSDN Managed Newsgroups,

John Eikanger
Microsoft Developer Support

This posting is provided “AS IS” with no warranties, and confers no rights.
--------------------
Thread-Topic: Reading Audio CD Text Data
From: =?Utf-8?B?SnVzdGlu?= <***@discussions.microsoft.com>
Subject: Reading Audio CD Text Data
Date: Wed, 4 Feb 2004 16:26:06 -0800
Lines: 40
X-Tomcat-NG: microsoft.public.development.device.drivers

Anyone have an example of how to read cd text data? I am trying to use the
IOCTL_CDROM_READ_TOC_EX command to return CDROM_TOC_CD_TEXT_DATA, but all I
have been able to get is various errors: "The device is not ready" and
"Incorrect Function" (each error with the same compiled exe but on
different machines). Using the same drive handle and same audio CDs I have
successfully read Track ISRCs and basic TOC info using
IOCTL_CDROM_READ_Q_CHANNEL and IOCTL_CDROM_READ_TOC.

What I do is I get a handle to my cd-rom, then I lock the cd-rom drive
using IOCTL_CDROM_MEDIA_REMOVAL then I read the TOC from the cd using
IOCTL_CDROM_READ_TOC then I loop through each of the songs from FirstTrack
to LastTrack in the TOC and I get the ISRC using IOCTL_CDROM_READ_Q_CHANNEL
and print it out and get the text data using IOCTL_CDROM_READ_TOC_EX and
would print it out if it worked through each iteration. Then I unlock the
cd drive.

Below is the code I have in C++ that I am trying to use but getting the
errors (DeviceIOControl returns FALSE and I get the text of the error with
GetLastError()):

hDevice is a a HANDLE to my cd rom drive retrieved with the CreateFile
function. I know it is a valid handle because I can successfully open and
close the cd drive and read the TOC (first & last track numbers and
TRACK_DATA items) and read the track ISRCs.

I am also curious if anyone knows how I can figure out the size I should
specify of the output buffer for this command. Currently I am just setting
it to 255 bytes, but don't know if that is enough or too much or what.

BOOL getTrackTextData(HANDLE& hDevice, UCHAR trackNum,
CDROM_TOC_CD_TEXT_DATA& output)
{
CDROM_READ_TOC_EX inBuf;
inBuf.Format = CDROM_READ_TOC_EX_FORMAT_CDTEXT;
inBuf.Reserved1 = 0;
inBuf.Msf = 1;
inBuf.SessionTrack = trackNum;
inBuf.Reserved2 = 0;
inBuf.Reserved3 = 0;

BOOL bResult;
DWORD bytesRet;

bResult = DeviceIoControl(hDevice, IOCTL_CDROM_READ_TOC_EX, &inBuf,
sizeof(inBuf), &output, 255, &bytesRet, (LPOVERLAPPED) NULL);
if (bResult)
{
printf("Success with %i bytes returned.\n", bytesRet);
}
return (bResult);
}

the above function is then called with the following (where i is a loop
counter and cdDevice is the cd-rom handle):
...
CDROM_TOC_CD_TEXT_DATA trackCDText;
bReturn = getTrackTextData(cdDevice, i, trackCDText);
...

ps. sorry if this is not the best looking code, I am pretty new to c++

Thank You for any help you can provide.

Loading...