1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
3 * Main file for CD-ROM support
5 * Copyright 1994 Martin Ayotte
6 * Copyright 1999 Eric Pouech
7 * Copyright 2000 Andreas Mohr
15 #include <sys/ioctl.h>
18 #include "debugtools.h"
20 #include "wine/winestring.h"
22 DEFAULT_DEBUG_CHANNEL(cdrom
);
24 #define MAX_CDAUDIO_TRACKS 256
26 /**************************************************************************
27 * CDROM_Open [internal]
30 * or -1 (figure it out)
32 int CDROM_Open(WINE_CDAUDIO
* wcda
, int drive
)
40 for (i
=0; i
< MAX_DOS_DRIVES
; i
++)
41 if (DRIVE_GetType(i
) == TYPE_CDROM
)
53 WARN("No CD-ROM #%d found !\n", drive
);
56 if ((dev
= DRIVE_GetDevice(drive
)) == NULL
)
58 WARN("No device entry for CD-ROM #%d (drive %c:) found !\n",
63 wcda
->unixdev
= open(dev
, O_RDONLY
| O_NONBLOCK
, 0);
64 if (wcda
->unixdev
== -1) {
65 WARN("can't open '%s'!. %s\n", dev
, strerror(errno
));
68 wcda
->cdaMode
= WINE_CDA_OPEN
; /* to force reading tracks info */
71 wcda
->dwFirstFrame
= 0;
72 wcda
->dwLastFrame
= 0;
73 wcda
->lpdwTrackLen
= NULL
;
74 wcda
->lpdwTrackPos
= NULL
;
75 wcda
->lpbTrackFlags
= NULL
;
79 /**************************************************************************
80 * CDROM_GetMediaType [internal]
82 int CDROM_GetMediaType(WINE_CDAUDIO
* wcda
)
85 return ioctl(wcda
->unixdev
, CDROM_DISC_STATUS
);
91 /**************************************************************************
92 * CDROM_Close [internal]
94 int CDROM_Close(WINE_CDAUDIO
* wcda
)
96 #if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)
97 if (wcda
->lpdwTrackLen
!= NULL
) free(wcda
->lpdwTrackLen
);
98 if (wcda
->lpdwTrackPos
!= NULL
) free(wcda
->lpdwTrackPos
);
99 if (wcda
->lpbTrackFlags
!= NULL
) free(wcda
->lpbTrackFlags
);
100 close(wcda
->unixdev
);
107 /**************************************************************************
108 * CDROM_Get_UPC [internal]
110 * upc has to be 14 bytes long
112 int CDROM_Get_UPC(WINE_CDAUDIO
* wcda
, LPSTR upc
)
115 struct cdrom_mcn mcn
;
116 int status
= ioctl(wcda
->unixdev
, CDROM_GET_MCN
, &mcn
);
119 ERR("ioctl() failed with code %d\n",status
);
122 strcpy(upc
, mcn
.medium_catalog_number
);
129 /**************************************************************************
130 * CDROM_Audio_GetNumberOfTracks [internal]
132 UINT16
CDROM_Audio_GetNumberOfTracks(WINE_CDAUDIO
* wcda
)
134 #if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)
136 struct cdrom_tochdr hdr
;
138 struct ioc_toc_header hdr
;
141 if (wcda
->nTracks
== 0) {
143 if (ioctl(wcda
->unixdev
, CDROMREADTOCHDR
, &hdr
))
145 if (ioctl(wcda
->unixdev
, CDIOREADTOCHEADER
, &hdr
))
148 WARN("(%p) -- Error occurred (%d)!\n", wcda
, errno
);
152 wcda
->nFirstTrack
= hdr
.cdth_trk0
;
153 wcda
->nLastTrack
= hdr
.cdth_trk1
;
155 wcda
->nFirstTrack
= hdr
.starting_track
;
156 wcda
->nLastTrack
= hdr
.ending_track
;
158 wcda
->nTracks
= wcda
->nLastTrack
- wcda
->nFirstTrack
+ 1;
160 return wcda
->nTracks
;
166 /**************************************************************************
167 * CDROM_Audio_GetTracksInfo [internal]
169 BOOL
CDROM_Audio_GetTracksInfo(WINE_CDAUDIO
* wcda
)
171 #if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)
173 int start
, last_start
= 0;
174 int total_length
= 0;
176 struct cdrom_tocentry entry
;
178 struct ioc_read_toc_entry entry
;
179 struct cd_toc_entry toc_buffer
;
182 if (wcda
->nTracks
== 0) {
183 if (CDROM_Audio_GetNumberOfTracks(wcda
) == (WORD
)-1) return FALSE
;
185 TRACE("nTracks=%u\n", wcda
->nTracks
);
187 if (wcda
->lpdwTrackLen
!= NULL
)
188 free(wcda
->lpdwTrackLen
);
189 wcda
->lpdwTrackLen
= (LPDWORD
)malloc((wcda
->nTracks
+ 1) * sizeof(DWORD
));
190 if (wcda
->lpdwTrackPos
!= NULL
)
191 free(wcda
->lpdwTrackPos
);
192 wcda
->lpdwTrackPos
= (LPDWORD
)malloc((wcda
->nTracks
+ 1) * sizeof(DWORD
));
193 if (wcda
->lpbTrackFlags
!= NULL
)
194 free(wcda
->lpbTrackFlags
);
195 wcda
->lpbTrackFlags
= (LPBYTE
)malloc((wcda
->nTracks
+ 1) * sizeof(BYTE
));
196 if (wcda
->lpdwTrackLen
== NULL
|| wcda
->lpdwTrackPos
== NULL
||
197 wcda
->lpbTrackFlags
== NULL
) {
198 WARN("error allocating track table !\n");
201 memset(wcda
->lpdwTrackLen
, 0, (wcda
->nTracks
+ 1) * sizeof(DWORD
));
202 memset(wcda
->lpdwTrackPos
, 0, (wcda
->nTracks
+ 1) * sizeof(DWORD
));
203 memset(wcda
->lpbTrackFlags
, 0, (wcda
->nTracks
+ 1) * sizeof(BYTE
));
204 for (i
= 0; i
<= wcda
->nTracks
; i
++) {
205 if (i
== wcda
->nTracks
)
207 entry
.cdte_track
= CDROM_LEADOUT
;
210 entry
.starting_track
= LEADOUT
; /* FIXME */
214 entry
.cdte_track
= i
+ 1;
216 entry
.starting_track
= i
+ 1;
219 entry
.cdte_format
= CDROM_MSF
;
221 bzero((char *)&toc_buffer
, sizeof(toc_buffer
));
222 entry
.address_format
= CD_MSF_FORMAT
;
223 entry
.data_len
= sizeof(toc_buffer
);
224 entry
.data
= &toc_buffer
;
227 if (ioctl(wcda
->unixdev
, CDROMREADTOCENTRY
, &entry
))
229 if (ioctl(wcda
->unixdev
, CDIOREADTOCENTRYS
, &entry
))
232 WARN("error read entry (%s)\n", strerror(errno
));
233 /* update status according to new status */
234 CDROM_Audio_GetCDStatus(wcda
);
239 start
= CDFRAMES_PERSEC
* (SECONDS_PERMIN
*
240 entry
.cdte_addr
.msf
.minute
+ entry
.cdte_addr
.msf
.second
) +
241 entry
.cdte_addr
.msf
.frame
;
243 start
= CDFRAMES_PERSEC
* (SECONDS_PERMIN
*
244 toc_buffer
.addr
.msf
.minute
+ toc_buffer
.addr
.msf
.second
) +
245 toc_buffer
.addr
.msf
.frame
;
249 wcda
->dwFirstFrame
= start
;
250 TRACE("dwFirstOffset=%u\n", start
);
252 length
= start
- last_start
;
254 start
= last_start
- length
;
255 total_length
+= length
;
256 wcda
->lpdwTrackLen
[i
- 1] = length
;
257 wcda
->lpdwTrackPos
[i
- 1] = start
;
258 TRACE("track #%u start=%u len=%u\n", i
, start
, length
);
261 wcda
->lpbTrackFlags
[i
] =
262 (entry
.cdte_adr
<< 4) | (entry
.cdte_ctrl
& 0x0f);
264 wcda
->lpbTrackFlags
[i
] =
265 (toc_buffer
.addr_type
<< 4) | (toc_buffer
.control
& 0x0f);
267 TRACE("track #%u flags=%02x\n", i
+ 1, wcda
->lpbTrackFlags
[i
]);
269 wcda
->dwLastFrame
= last_start
;
270 TRACE("total_len=%u\n", total_length
);
277 /**************************************************************************
278 * CDROM_Audio_GetCDStatus [internal]
280 BOOL
CDROM_Audio_GetCDStatus(WINE_CDAUDIO
* wcda
)
282 #if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)
283 int oldmode
= wcda
->cdaMode
;
285 wcda
->sc
.cdsc_format
= CDROM_MSF
;
287 struct ioc_read_subchannel read_sc
;
289 read_sc
.address_format
= CD_MSF_FORMAT
;
290 read_sc
.data_format
= CD_CURRENT_POSITION
;
292 read_sc
.data_len
= sizeof(wcda
->sc
);
293 read_sc
.data
= (struct cd_sub_channel_info
*)&wcda
->sc
;
296 if (ioctl(wcda
->unixdev
, CDROMSUBCHNL
, &wcda
->sc
))
298 if (ioctl(wcda
->unixdev
, CDIOCREADSUBCHANNEL
, &read_sc
))
301 TRACE("opened or no_media (%s)!\n", strerror(errno
));
302 wcda
->cdaMode
= WINE_CDA_OPEN
; /* was NOT_READY */
307 wcda
->sc
.cdsc_audiostatus
309 wcda
->sc
.header
.audio_status
313 case CDROM_AUDIO_INVALID
:
315 case CD_AS_AUDIO_INVALID
:
317 WARN("device doesn't support status.\n");
318 wcda
->cdaMode
= WINE_CDA_DONTKNOW
;
321 case CDROM_AUDIO_NO_STATUS
:
323 case CD_AS_NO_STATUS
:
325 wcda
->cdaMode
= WINE_CDA_STOP
;
326 TRACE("WINE_CDA_STOP !\n");
329 case CDROM_AUDIO_PLAY
:
331 case CD_AS_PLAY_IN_PROGRESS
:
333 wcda
->cdaMode
= WINE_CDA_PLAY
;
336 case CDROM_AUDIO_PAUSED
:
338 case CD_AS_PLAY_PAUSED
:
340 wcda
->cdaMode
= WINE_CDA_PAUSE
;
341 TRACE("WINE_CDA_PAUSE !\n");
345 TRACE("status=%02X !\n",
346 wcda
->sc
.cdsc_audiostatus
);
348 TRACE("status=%02X !\n",
349 wcda
->sc
.header
.audio_status
);
353 wcda
->nCurTrack
= wcda
->sc
.cdsc_trk
;
355 CDFRAMES_PERMIN
* wcda
->sc
.cdsc_absaddr
.msf
.minute
+
356 CDFRAMES_PERSEC
* wcda
->sc
.cdsc_absaddr
.msf
.second
+
357 wcda
->sc
.cdsc_absaddr
.msf
.frame
;
359 wcda
->nCurTrack
= wcda
->sc
.what
.position
.track_number
;
361 CDFRAMES_PERMIN
* wcda
->sc
.what
.position
.absaddr
.msf
.minute
+
362 CDFRAMES_PERSEC
* wcda
->sc
.what
.position
.absaddr
.msf
.second
+
363 wcda
->sc
.what
.position
.absaddr
.msf
.frame
;
366 TRACE("%02u-%02u:%02u:%02u\n",
368 wcda
->sc
.cdsc_absaddr
.msf
.minute
,
369 wcda
->sc
.cdsc_absaddr
.msf
.second
,
370 wcda
->sc
.cdsc_absaddr
.msf
.frame
);
372 TRACE("%02u-%02u:%02u:%02u\n",
373 wcda
->sc
.what
.position
.track_number
,
374 wcda
->sc
.what
.position
.absaddr
.msf
.minute
,
375 wcda
->sc
.what
.position
.absaddr
.msf
.second
,
376 wcda
->sc
.what
.position
.absaddr
.msf
.frame
);
379 if (oldmode
!= wcda
->cdaMode
&& oldmode
== WINE_CDA_OPEN
) {
380 if (!CDROM_Audio_GetTracksInfo(wcda
)) {
381 WARN("error updating TracksInfo !\n");
391 /**************************************************************************
392 * CDROM_Audio_Play [internal]
394 int CDROM_Audio_Play(WINE_CDAUDIO
* wcda
, DWORD start
, DWORD end
)
396 #if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)
398 struct cdrom_msf msf
;
400 struct ioc_play_msf msf
;
404 msf
.cdmsf_min0
= start
/ CDFRAMES_PERMIN
;
405 msf
.cdmsf_sec0
= (start
% CDFRAMES_PERMIN
) / CDFRAMES_PERSEC
;
406 msf
.cdmsf_frame0
= start
% CDFRAMES_PERSEC
;
407 msf
.cdmsf_min1
= end
/ CDFRAMES_PERMIN
;
408 msf
.cdmsf_sec1
= (end
% CDFRAMES_PERMIN
) / CDFRAMES_PERSEC
;
409 msf
.cdmsf_frame1
= end
% CDFRAMES_PERSEC
;
411 msf
.start_m
= start
/ CDFRAMES_PERMIN
;
412 msf
.start_s
= (start
% CDFRAMES_PERMIN
) / CDFRAMES_PERSEC
;
413 msf
.start_f
= start
% CDFRAMES_PERSEC
;
414 msf
.end_m
= end
/ CDFRAMES_PERMIN
;
415 msf
.end_s
= (end
% CDFRAMES_PERMIN
) / CDFRAMES_PERSEC
;
416 msf
.end_f
= end
% CDFRAMES_PERSEC
;
419 if (ioctl(wcda
->unixdev
, CDROMSTART
))
421 if (ioctl(wcda
->unixdev
, CDIOCSTART
, NULL
))
424 WARN("motor doesn't start !\n");
428 if (ioctl(wcda
->unixdev
, CDROMPLAYMSF
, &msf
))
430 if (ioctl(wcda
->unixdev
, CDIOCPLAYMSF
, &msf
))
433 WARN("device doesn't play !\n");
437 TRACE("msf = %d:%d:%d %d:%d:%d\n",
438 msf
.cdmsf_min0
, msf
.cdmsf_sec0
, msf
.cdmsf_frame0
,
439 msf
.cdmsf_min1
, msf
.cdmsf_sec1
, msf
.cdmsf_frame1
);
441 TRACE("msf = %d:%d:%d %d:%d:%d\n",
442 msf
.start_m
, msf
.start_s
, msf
.start_f
,
443 msf
.end_m
, msf
.end_s
, msf
.end_f
);
451 /**************************************************************************
452 * CDROM_Audio_Stop [internal]
454 int CDROM_Audio_Stop(WINE_CDAUDIO
* wcda
)
456 #if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)
459 ret
= ioctl(wcda
->unixdev
, CDROMSTOP
);
461 ret
= ioctl(wcda
->unixdev
, CDIOCSTOP
, NULL
);
469 /**************************************************************************
470 * CDROM_Audio_Pause [internal]
472 int CDROM_Audio_Pause(WINE_CDAUDIO
* wcda
, int pauseOn
)
474 #if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)
477 ret
= ioctl(wcda
->unixdev
, pauseOn
? CDROMPAUSE
: CDROMRESUME
);
479 ret
= ioctl(wcda
->unixdev
, pauseOn
? CDIOCPAUSE
: CDIOCRESUME
, NULL
);
487 /**************************************************************************
488 * CDROM_Audio_Seek [internal]
490 int CDROM_Audio_Seek(WINE_CDAUDIO
* wcda
, DWORD at
)
492 #if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)
495 struct cdrom_msf0 msf
;
496 msf
.minute
= at
/ CDFRAMES_PERMIN
;
497 msf
.second
= (at
% CDFRAMES_PERMIN
) / CDFRAMES_PERSEC
;
498 msf
.frame
= at
% CDFRAMES_PERSEC
;
500 ret
= ioctl(wcda
->unixdev
, CDROMSEEK
, &msf
);
502 /* FIXME: the current end for play is lost
503 * use end of CD ROM instead
505 FIXME("Could a BSD expert implement the seek function ?\n");
506 CDROM_Audio_Play(wcda
, at
, wcda
->lpdwTrackPos
[wcda
->nTracks
] + wcda
->lpdwTrackLen
[wcda
->nTracks
]);
515 /**************************************************************************
516 * CDROM_SetDoor [internal]
518 int CDROM_SetDoor(WINE_CDAUDIO
* wcda
, int open
)
520 #if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)
524 ret
= ioctl(wcda
->unixdev
, CDROMEJECT
);
526 ret
= ioctl(wcda
->unixdev
, CDROMEJECT
, 1);
529 ret
= (ioctl(wcda
->unixdev
, CDIOCALLOW
, NULL
)) ||
530 (ioctl(wcda
->unixdev
, open
? CDIOCEJECT
: CDIOCCLOSE
, NULL
)) ||
531 (ioctl(wcda
->unixdev
, CDIOCPREVENT
, NULL
));
540 /**************************************************************************
541 * CDROM_Reset [internal]
543 int CDROM_Reset(WINE_CDAUDIO
* wcda
)
545 #if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__)
548 ret
= ioctl(wcda
->unixdev
, CDROMRESET
);
550 ret
= ioctl(wcda
->unixdev
, CDIOCRESET
, NULL
);
558 WORD
CDROM_Data_FindBestVoldesc(int fd
)
560 BYTE cur_vd_type
, max_vd_type
= 0;
561 unsigned int offs
, best_offs
= 0;
563 for (offs
=0x8000; offs
<= 0x9800; offs
+= 0x800)
565 lseek(fd
, offs
, SEEK_SET
);
566 read(fd
, &cur_vd_type
, 1);
567 if (cur_vd_type
== 0xff) /* voldesc set terminator */
569 if (cur_vd_type
> max_vd_type
)
571 max_vd_type
= cur_vd_type
;
578 /**************************************************************************
579 * CDROM_Audio_GetSerial [internal]
581 DWORD
CDROM_Audio_GetSerial(WINE_CDAUDIO
* wcda
)
583 unsigned long serial
= 0;
586 WORD wMinutes
, wSeconds
, wFrames
;
588 DWORD dwStart
, dwEnd
;
591 * wMagic collects the wFrames from track 1
592 * dwStart, dwEnd collect the beginning and end of the disc respectively, in
594 * There it is collected for correcting the serial when there are less than
600 for (i
= 0; i
< wcda
->nTracks
; i
++) {
601 dwFrame
= wcda
->lpdwTrackPos
[i
];
602 wMinutes
= dwFrame
/ CDFRAMES_PERMIN
;
603 wSeconds
= (dwFrame
- CDFRAMES_PERMIN
* wMinutes
) / CDFRAMES_PERSEC
;
604 wFrames
= dwFrame
- CDFRAMES_PERMIN
* wMinutes
- CDFRAMES_PERSEC
* wSeconds
;
605 msf
= CDROM_MAKE_MSF(wMinutes
, wSeconds
, wFrames
);
607 serial
+= (CDROM_MSF_MINUTE(msf
) << 16) +
608 (CDROM_MSF_SECOND(msf
) << 8) +
609 (CDROM_MSF_FRAME(msf
));
616 dwEnd
= dwFrame
+ wcda
->lpdwTrackLen
[i
];
620 if (wcda
->nTracks
< 3)
622 serial
+= wMagic
+ (dwEnd
- dwStart
);
627 /**************************************************************************
628 * CDROM_Data_GetSerial [internal]
630 DWORD
CDROM_Data_GetSerial(WINE_CDAUDIO
* wcda
)
632 WORD offs
= CDROM_Data_FindBestVoldesc(wcda
->unixdev
);
637 BYTE b0
= 0, b1
= 1, b2
= 2, b3
= 3;
646 lseek(wcda
->unixdev
,offs
,SEEK_SET
);
647 read(wcda
->unixdev
,buf
,2048);
649 * OK, another braindead one... argh. Just believe it.
650 * Me$$ysoft chose to reverse the serial number in NT4/W2K.
651 * It's true and nobody will ever be able to change it.
653 ovi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
655 if ((ovi
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
656 && (ovi
.dwMajorVersion
>= 4))
658 b0
= 3; b1
= 2; b2
= 1; b3
= 0;
660 for(i
=0; i
<2048; i
+=4)
662 /* DON'T optimize this into DWORD !! (breaks overflow) */
663 serial
.p
[b0
] += buf
[i
+b0
];
664 serial
.p
[b1
] += buf
[i
+b1
];
665 serial
.p
[b2
] += buf
[i
+b2
];
666 serial
.p
[b3
] += buf
[i
+b3
];
672 /**************************************************************************
673 * CDROM_GetSerial [internal]
675 DWORD
CDROM_GetSerial(int drive
)
680 /* EXPIRES 01.01.2002 */
681 WARN("CD-ROM serial number calculation might fail.\n");
682 WARN("Please test with as many exotic CDs as possible !\n");
684 if (!(CDROM_Open(&wcda
, drive
)))
686 int media
= CDROM_GetMediaType(&wcda
);
689 if (media
== CDS_AUDIO
)
691 if (!(CDROM_Audio_GetCDStatus(&wcda
))) {
692 ERR("couldn't get CD status !\n");
696 serial
= CDROM_Audio_GetSerial(&wcda
);
699 if ((media
> CDS_AUDIO
)
700 || (media
== -1) /* ioctl() error: ISO9660 image file given ? */
702 /* hopefully a data CD */
703 serial
= CDROM_Data_GetSerial(&wcda
);
705 WARN("Strange CD type (%d) or empty ?\n", media
);
707 p
= (media
== CDS_AUDIO
) ? "Audio " :
708 (media
> CDS_AUDIO
) ? "Data " : "";
710 TRACE("%sCD serial number is %04x-%04x.\n",
711 p
, HIWORD(serial
), LOWORD(serial
));
713 if (media
>= CDS_AUDIO
)
714 ERR("couldn't get %sCD serial !\n", p
);
720 static const char empty_label
[] = " ";
722 /**************************************************************************
723 * CDROM_Data_GetLabel [internal]
725 DWORD
CDROM_Data_GetLabel(WINE_CDAUDIO
* wcda
, char *label
)
727 #define LABEL_LEN 32+1
728 WORD offs
= CDROM_Data_FindBestVoldesc(wcda
->unixdev
);
729 WCHAR label_read
[LABEL_LEN
]; /* Unicode possible, too */
730 DWORD unicode_id
= 0;
734 if ((lseek(wcda
->unixdev
, offs
+0x58, SEEK_SET
) == offs
+0x58)
735 && (read(wcda
->unixdev
, &unicode_id
, 3) == 3))
737 int ver
= (unicode_id
& 0xff0000) >> 16;
739 if ((lseek(wcda
->unixdev
, offs
+0x28, SEEK_SET
) != offs
+0x28)
740 || (read(wcda
->unixdev
, &label_read
, LABEL_LEN
) != LABEL_LEN
))
743 if ((LOWORD(unicode_id
) == 0x2f25) /* Unicode ID */
744 && ((ver
== 0x40) || (ver
== 0x43) || (ver
== 0x45)))
745 { /* yippee, unicode */
748 for (i
=0; i
<LABEL_LEN
;i
++)
749 { /* Motorola -> Intel Unicode conversion :-\ */
751 label_read
[i
] = (ch
<< 8) | (ch
>> 8);
753 lstrcpynWtoA(label
, label_read
, 11);
757 strncpy(label
, (LPSTR
)label_read
, 11);
764 ERR("error reading label !\n");
765 strcpy(label
, empty_label
);
769 /**************************************************************************
770 * CDROM_GetLabel [internal]
772 DWORD
CDROM_GetLabel(int drive
, char *label
)
777 if (!(CDROM_Open(&wcda
, drive
)))
779 int media
= CDROM_GetMediaType(&wcda
);
782 if (media
== CDS_AUDIO
)
784 strcpy(label
, "Audio CD ");
787 if (media
== CDS_NO_INFO
)
789 strcpy(label
, empty_label
);
792 if ((media
> CDS_AUDIO
)
793 || (media
== -1) /* ioctl() error: ISO9660 image file given ? */
795 /* hopefully a data CD */
796 CDROM_Data_GetLabel(&wcda
, label
);
799 WARN("Strange CD type (%d) or empty ?\n", media
);
800 strcpy(label
, empty_label
);
804 p
= (media
== CDS_AUDIO
) ? "Audio " :
805 (media
> CDS_AUDIO
) ? "Data " : "";
806 TRACE("%sCD label is '%s'.\n",