Release 940714
[wine/multimedia.git] / misc / mcicda.c
blob3b49cdeeb10dc1261dafd68590bf90fba19bef0d
1 /*
2 * Sample MCI CDAUDIO Wine Driver for Linux
4 * Copyright 1994 Martin Ayotte
5 */
6 #ifndef WINELIB
7 static char Copyright[] = "Copyright Martin Ayotte, 1994";
9 /*
10 #define DEBUG_CDAUDIO
13 #include "stdio.h"
14 #include "win.h"
15 #include "user.h"
16 #include "driver.h"
17 #include "mmsystem.h"
19 #include <fcntl.h>
20 #include <sys/ioctl.h>
21 #include <linux/soundcard.h>
22 #include <linux/cdrom.h>
24 #define SOUND_DEV "/dev/dsp"
25 #define CDAUDIO_DEV "/dev/sbpcd"
27 #ifdef SOUND_VERSION
28 #define IOCTL(a,b,c) ioctl(a,b,&c)
29 #else
30 #define IOCTL(a,b,c) (c = ioctl(a,b,c) )
31 #endif
33 #define MAX_CDAUDIODRV 2
34 #define MAX_CDAUDIO_TRACKS 256
36 #define CDFRAMES_PERSEC 75
37 #define CDFRAMES_PERMIN 4500
38 #define SECONDS_PERMIN 60
40 typedef struct {
41 int nUseCount; /* Incremented for each shared open */
42 BOOL fShareable; /* TRUE if first open was shareable */
43 WORD wNotifyDeviceID; /* MCI device ID with a pending notification */
44 HANDLE hCallback; /* Callback handle for pending notification */
45 MCI_OPEN_PARMS openParms;
46 DWORD dwTimeFormat;
47 int unixdev;
48 struct cdrom_subchnl sc;
49 int mode;
50 UINT nCurTrack;
51 DWORD dwCurFrame;
52 UINT nTracks;
53 DWORD dwTotalLen;
54 LPDWORD lpdwTrackLen;
55 LPDWORD lpdwTrackPos;
56 DWORD dwFirstOffset;
57 } LINUX_CDAUDIO;
59 static LINUX_CDAUDIO CDADev[MAX_CDAUDIODRV];
61 UINT CDAUDIO_GetNumberOfTracks(UINT wDevID);
62 BOOL CDAUDIO_GetTracksInfo(UINT wDevID);
63 BOOL CDAUDIO_GetCDStatus(UINT wDevID);
64 DWORD CDAUDIO_CalcTime(UINT wDevID, DWORD dwFormatType, DWORD dwFrame);
67 /*-----------------------------------------------------------------------*/
70 /**************************************************************************
71 * CDAUDIO_mciOpen [internal]
73 DWORD CDAUDIO_mciOpen(DWORD dwFlags, LPMCI_OPEN_PARMS lpParms)
75 UINT wDevID;
76 int cdrom;
77 #ifdef DEBUG_CDAUDIO
78 printf("CDAUDIO_mciOpen(%08X, %08X);\n", dwFlags, lpParms);
79 #endif
80 if (lpParms == NULL) return MCIERR_INTERNAL;
81 wDevID = lpParms->wDeviceID;
82 if (CDADev[wDevID].nUseCount > 0) {
83 /* The driver already open on this channel */
84 /* If the driver was% op, ened shareable before and this open specifies */
85 /* shareable then increment the use count */
86 if (CDADev[wDevID].fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
87 ++CDADev[wDevID].nUseCount;
88 else
89 return MCIERR_MUST_USE_SHAREABLE;
91 else {
92 CDADev[wDevID].nUseCount = 1;
93 CDADev[wDevID].fShareable = dwFlags & MCI_OPEN_SHAREABLE;
95 if (dwFlags & MCI_OPEN_ELEMENT) {
96 printf("CDAUDIO_mciOpen // MCI_OPEN_ELEMENT !\n");
97 /* return MCIERR_NO_ELEMENT_ALLOWED; */
99 memcpy(&CDADev[wDevID].openParms, lpParms, sizeof(MCI_OPEN_PARMS));
100 CDADev[wDevID].wNotifyDeviceID = lpParms->wDeviceID;
101 CDADev[wDevID].unixdev = open (CDAUDIO_DEV, O_RDONLY, 0);
102 if (CDADev[wDevID].unixdev == -1) {
103 printf("CDAUDIO_mciOpen // can't open '%s' !\n", CDAUDIO_DEV);
104 return MCIERR_HARDWARE;
106 CDADev[wDevID].mode = 0;
107 CDADev[wDevID].dwTimeFormat = MCI_FORMAT_TMSF;
108 CDADev[wDevID].nCurTrack = 0;
109 CDADev[wDevID].nTracks = 0;
110 CDADev[wDevID].dwTotalLen = 0;
111 CDADev[wDevID].dwFirstOffset = 0;
112 CDADev[wDevID].lpdwTrackLen = NULL;
113 CDADev[wDevID].lpdwTrackPos = NULL;
114 if (!CDAUDIO_GetTracksInfo(wDevID)) {
115 printf("CDAUDIO_mciOpen // error reading TracksInfo !\n");
116 /* return MCIERR_INTERNAL; */
118 if (dwFlags & MCI_NOTIFY) {
119 printf("CDAUDIO_mciOpen // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback);
120 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
121 CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
123 return 0;
126 /**************************************************************************
127 * CDAUDIO_mciClose [internal]
129 DWORD CDAUDIO_mciClose(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
131 #ifdef DEBUG_CDAUDIO
132 printf("CDAUDIO_mciClose(%u, %08X, %08X);\n", wDevID, dwParam, lpParms);
133 #endif
134 if (CDADev[wDevID].lpdwTrackLen != NULL) free(CDADev[wDevID].lpdwTrackLen);
135 if (CDADev[wDevID].lpdwTrackPos != NULL) free(CDADev[wDevID].lpdwTrackPos);
136 close(CDADev[wDevID].unixdev);
139 /**************************************************************************
140 * CDAUDIO_mciGetDevCaps [internal]
142 DWORD CDAUDIO_mciGetDevCaps(UINT wDevID, DWORD dwFlags,
143 LPMCI_GETDEVCAPS_PARMS lpParms)
145 #ifdef DEBUG_CDAUDIO
146 printf("CDAUDIO_mciGetDevCaps(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
147 #endif
148 if (lpParms == NULL) return MCIERR_INTERNAL;
149 if (dwFlags & MCI_GETDEVCAPS_ITEM) {
150 printf("CDAUDIO_mciGetDevCaps // MCI_GETDEVCAPS_ITEM dwItem=%08X);\n",
151 lpParms->dwItem);
152 switch(lpParms->dwItem) {
153 case MCI_GETDEVCAPS_CAN_RECORD:
154 lpParms->dwReturn = FALSE;
155 break;
156 case MCI_GETDEVCAPS_HAS_AUDIO:
157 lpParms->dwReturn = TRUE;
158 break;
159 case MCI_GETDEVCAPS_HAS_VIDEO:
160 lpParms->dwReturn = FALSE;
161 break;
162 case MCI_GETDEVCAPS_DEVICE_TYPE:
163 lpParms->dwReturn = MCI_DEVTYPE_CD_AUDIO;
164 break;
165 case MCI_GETDEVCAPS_USES_FILES:
166 lpParms->dwReturn = FALSE;
167 break;
168 case MCI_GETDEVCAPS_COMPOUND_DEVICE:
169 lpParms->dwReturn = FALSE;
170 break;
171 case MCI_GETDEVCAPS_CAN_EJECT:
172 lpParms->dwReturn = TRUE;
173 break;
174 case MCI_GETDEVCAPS_CAN_PLAY:
175 lpParms->dwReturn = TRUE;
176 break;
177 case MCI_GETDEVCAPS_CAN_SAVE:
178 lpParms->dwReturn = FALSE;
179 break;
180 default:
181 return MCIERR_UNRECOGNIZED_COMMAND;
184 printf("CDAUDIO_mciGetDevCaps // lpParms->dwReturn=%08X);\n", lpParms->dwReturn);
185 return 0;
188 /**************************************************************************
189 * CDAUDIO_mciInfo [internal]
191 DWORD CDAUDIO_mciInfo(UINT wDevID, DWORD dwFlags, LPMCI_INFO_PARMS lpParms)
193 #ifdef DEBUG_CDAUDIO
194 printf("CDAUDIO_mciInfo(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
195 #endif
196 if (lpParms == NULL) return MCIERR_INTERNAL;
197 lpParms->lpstrReturn = NULL;
198 switch(dwFlags) {
199 case MCI_INFO_PRODUCT:
200 lpParms->lpstrReturn = "Linux CDROM 0.5";
201 break;
202 default:
203 return MCIERR_UNRECOGNIZED_COMMAND;
205 if (lpParms->lpstrReturn != NULL)
206 lpParms->dwRetSize = strlen(lpParms->lpstrReturn);
207 else
208 lpParms->dwRetSize = 0;
209 return 0;
212 /**************************************************************************
213 * CDAUDIO_mciStatus [internal]
215 DWORD CDAUDIO_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
217 #ifdef DEBUG_CDAUDIO
218 printf("CDAUDIO_mciStatus(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
219 #endif
220 if (lpParms == NULL) return MCIERR_INTERNAL;
221 if (CDADev[wDevID].unixdev == 0) return MMSYSERR_NOTENABLED;
222 if (dwFlags & MCI_NOTIFY) {
223 #ifdef DEBUG_CDAUDIO
224 printf("CDAUDIO_mciStatus // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback);
225 #endif
226 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
227 CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
229 if (dwFlags & MCI_STATUS_ITEM) {
230 switch(lpParms->dwItem) {
231 case MCI_STATUS_CURRENT_TRACK:
232 if (!CDAUDIO_GetCDStatus(wDevID)) return MCIERR_INTERNAL;
233 lpParms->dwReturn = CDADev[wDevID].nCurTrack;
234 #ifdef DEBUG_CDAUDIO
235 printf("CDAUDIO_mciStatus // CURRENT_TRACK=%u!\n", lpParms->dwReturn);
236 #endif
237 return 0;
238 case MCI_STATUS_LENGTH:
239 if (CDADev[wDevID].nTracks == 0) {
240 if (!CDAUDIO_GetTracksInfo(wDevID)) {
241 printf("CDAUDIO_mciStatus // error reading TracksInfo !\n");
242 return MCIERR_INTERNAL;
245 if (dwFlags & MCI_TRACK) {
246 printf("CDAUDIO_mciStatus // MCI_TRACK #%u LENGTH=??? !\n",
247 lpParms->dwTrack);
248 if (lpParms->dwTrack > CDADev[wDevID].nTracks)
249 return MCIERR_OUTOFRANGE;
250 lpParms->dwReturn = CDADev[wDevID].lpdwTrackLen[lpParms->dwTrack];
252 else
253 lpParms->dwReturn = CDADev[wDevID].dwTotalLen;
254 lpParms->dwReturn = CDAUDIO_CalcTime(wDevID,
255 CDADev[wDevID].dwTimeFormat, lpParms->dwReturn);
256 printf("CDAUDIO_mciStatus // LENGTH=%u !\n", lpParms->dwReturn);
257 return 0;
258 case MCI_STATUS_MODE:
259 if (!CDAUDIO_GetCDStatus(wDevID)) return MCIERR_INTERNAL;
260 lpParms->dwReturn = CDADev[wDevID].mode;
261 #ifdef DEBUG_CDAUDIO
262 printf("CDAUDIO_mciStatus // MCI_STATUS_MODE=%08X !\n",
263 lpParms->dwReturn);
264 #endif
265 return 0;
266 case MCI_STATUS_MEDIA_PRESENT:
267 lpParms->dwReturn = (CDADev[wDevID].nTracks > 0) ? TRUE : FALSE;
268 if (lpParms->dwReturn == FALSE)
269 printf("CDAUDIO_mciStatus // MEDIA_NOT_PRESENT !\n");
270 else
271 printf("CDAUDIO_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
272 return 0;
273 case MCI_STATUS_NUMBER_OF_TRACKS:
274 lpParms->dwReturn = CDAUDIO_GetNumberOfTracks(wDevID);
275 printf("CDAUDIO_mciStatus // MCI_STATUS_NUMBER_OF_TRACKS = %u !\n",
276 lpParms->dwReturn);
277 if (lpParms->dwReturn == (WORD)-1) return MCIERR_INTERNAL;
278 return 0;
279 case MCI_STATUS_POSITION:
280 if (!CDAUDIO_GetCDStatus(wDevID)) return MCIERR_INTERNAL;
281 lpParms->dwReturn = CDADev[wDevID].dwCurFrame;
282 if (dwFlags & MCI_STATUS_START) {
283 lpParms->dwReturn = CDADev[wDevID].dwFirstOffset;
284 #ifdef DEBUG_CDAUDIO
285 printf("CDAUDIO_mciStatus // get MCI_STATUS_START !\n");
286 #endif
288 if (dwFlags & MCI_TRACK) {
289 if (lpParms->dwTrack > CDADev[wDevID].nTracks)
290 return MCIERR_OUTOFRANGE;
291 lpParms->dwReturn = CDADev[wDevID].lpdwTrackPos[lpParms->dwTrack - 1];
292 #ifdef DEBUG_CDAUDIO
293 printf("CDAUDIO_mciStatus // get MCI_TRACK #%u !\n", lpParms->dwTrack);
294 #endif
296 lpParms->dwReturn = CDAUDIO_CalcTime(wDevID,
297 CDADev[wDevID].dwTimeFormat, lpParms->dwReturn);
298 #ifdef DEBUG_CDAUDIO
299 printf("CDAUDIO_mciStatus // MCI_STATUS_POSITION=%08X !\n",
300 lpParms->dwReturn);
301 #endif
302 return 0;
303 case MCI_STATUS_READY:
304 printf("CDAUDIO_mciStatus // MCI_STATUS_READY !\n");
305 lpParms->dwReturn = TRUE;
306 return 0;
307 case MCI_STATUS_TIME_FORMAT:
308 printf("CDAUDIO_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
309 lpParms->dwReturn = MCI_FORMAT_MILLISECONDS;
310 return 0;
311 default:
312 printf("CDAUDIO_mciStatus // unknowm command %04X !\n", lpParms->dwItem);
313 return MCIERR_UNRECOGNIZED_COMMAND;
316 printf("CDAUDIO_mciStatus // not MCI_STATUS_ITEM !\n");
317 return 0;
321 /**************************************************************************
322 * CDAUDIO_CalcTime [internal]
324 DWORD CDAUDIO_CalcTime(UINT wDevID, DWORD dwFormatType, DWORD dwFrame)
326 DWORD dwTime = 0;
327 UINT wTrack;
328 UINT wMinutes;
329 UINT wSeconds;
330 UINT wFrames;
331 #ifdef DEBUG_CDAUDIO
332 printf("CDAUDIO_CalcTime(%u, %08X, %lu);\n", wDevID, dwFormatType, dwFrame);
333 #endif
334 TryAGAIN:
335 switch (dwFormatType) {
336 case MCI_FORMAT_MILLISECONDS:
337 dwTime = dwFrame / CDFRAMES_PERSEC * 1000;
338 #ifdef DEBUG_CDAUDIO
339 printf("CDAUDIO_CalcTime // MILLISECONDS %u\n", dwTime);
340 #endif
341 break;
342 case MCI_FORMAT_MSF:
343 wMinutes = dwFrame / CDFRAMES_PERMIN;
344 wSeconds = (dwFrame - CDFRAMES_PERMIN * wMinutes) / CDFRAMES_PERSEC;
345 wFrames = dwFrame - CDFRAMES_PERMIN * wMinutes -
346 CDFRAMES_PERSEC * wSeconds;
347 dwTime = MCI_MAKE_MSF(wMinutes, wSeconds, wFrames);
348 #ifdef DEBUG_CDAUDIO
349 printf("CDAUDIO_CalcTime // MSF %02u:%02u:%02u -> dwTime=%u\n",
350 wMinutes, wSeconds, wFrames, dwTime);
351 #endif
352 break;
353 case MCI_FORMAT_TMSF:
354 for (wTrack = 0; wTrack < CDADev[wDevID].nTracks; wTrack++) {
355 /* dwTime += CDADev[wDevID].lpdwTrackLen[wTrack - 1];
356 printf("Adding trk#%u curpos=%u \n", dwTime);
357 if (dwTime >= dwFrame) break; */
358 if (CDADev[wDevID].lpdwTrackPos[wTrack - 1] >= dwFrame) break;
360 wMinutes = dwFrame / CDFRAMES_PERMIN;
361 wSeconds = (dwFrame - CDFRAMES_PERMIN * wMinutes) / CDFRAMES_PERSEC;
362 wFrames = dwFrame - CDFRAMES_PERMIN * wMinutes -
363 CDFRAMES_PERSEC * wSeconds;
364 dwTime = MCI_MAKE_TMSF(wTrack, wMinutes, wSeconds, wFrames);
365 #ifdef DEBUG_CDAUDIO
366 printf("CDAUDIO_CalcTime // %02u-%02u:%02u:%02u\n",
367 wTrack, wMinutes, wSeconds, wFrames);
368 #endif
369 break;
370 default:
371 /* unknown format ! force TMSF ! ... */
372 dwFormatType = MCI_FORMAT_TMSF;
373 goto TryAGAIN;
375 return dwTime;
379 /**************************************************************************
380 * CDAUDIO_CalcFrame [internal]
382 DWORD CDAUDIO_CalcFrame(UINT wDevID, DWORD dwFormatType, DWORD dwTime)
384 DWORD dwFrame = 0;
385 UINT wTrack;
386 #ifdef DEBUG_CDAUDIO
387 printf("CDAUDIO_CalcFrame(%u, %08X, %lu);\n", wDevID, dwFormatType, dwTime);
388 #endif
389 TryAGAIN:
390 switch (dwFormatType) {
391 case MCI_FORMAT_MILLISECONDS:
392 dwFrame = dwTime * CDFRAMES_PERSEC / 1000;
393 #ifdef DEBUG_CDAUDIO
394 printf("CDAUDIO_CalcFrame // MILLISECONDS %u\n", dwFrame);
395 #endif
396 break;
397 case MCI_FORMAT_MSF:
398 #ifdef DEBUG_CDAUDIO
399 printf("CDAUDIO_CalcFrame // MSF %02u:%02u:%02u\n",
400 MCI_MSF_MINUTE(dwTime), MCI_MSF_SECOND(dwTime),
401 MCI_MSF_FRAME(dwTime));
402 #endif
403 dwFrame += CDFRAMES_PERMIN * MCI_MSF_MINUTE(dwTime);
404 dwFrame += CDFRAMES_PERSEC * MCI_MSF_SECOND(dwTime);
405 dwFrame += MCI_MSF_FRAME(dwTime);
406 break;
407 case MCI_FORMAT_TMSF:
408 wTrack = MCI_TMSF_TRACK(dwTime);
409 #ifdef DEBUG_CDAUDIO
410 printf("CDAUDIO_CalcFrame // TMSF %02u-%02u:%02u:%02u\n",
411 MCI_TMSF_TRACK(dwTime), MCI_TMSF_MINUTE(dwTime),
412 MCI_TMSF_SECOND(dwTime), MCI_TMSF_FRAME(dwTime));
413 printf("CDAUDIO_CalcFrame // TMSF trackpos[%u]=%u\n",
414 wTrack, CDADev[wDevID].lpdwTrackPos[wTrack - 1]);
415 #endif
416 dwFrame = CDADev[wDevID].lpdwTrackPos[wTrack - 1];
417 dwFrame += CDFRAMES_PERMIN * MCI_TMSF_MINUTE(dwTime);
418 dwFrame += CDFRAMES_PERSEC * MCI_TMSF_SECOND(dwTime);
419 dwFrame += MCI_TMSF_FRAME(dwTime);
420 break;
421 default:
422 /* unknown format ! force TMSF ! ... */
423 dwFormatType = MCI_FORMAT_TMSF;
424 goto TryAGAIN;
426 return dwFrame;
430 /**************************************************************************
431 * CDAUDIO_GetNumberOfTracks [internal]
433 UINT CDAUDIO_GetNumberOfTracks(UINT wDevID)
435 struct cdrom_tochdr hdr;
436 if (CDADev[wDevID].nTracks == 0) {
437 if (ioctl(CDADev[wDevID].unixdev, CDROMREADTOCHDR, &hdr)) {
438 printf("GetNumberOfTracks(%u) // Error occured !\n", wDevID);
439 return (WORD)-1;
441 CDADev[wDevID].nTracks = hdr.cdth_trk1;
443 return CDADev[wDevID].nTracks;
446 /**************************************************************************
447 * CDAUDIO_GetNumberOfTracks [internal]
449 BOOL CDAUDIO_GetTracksInfo(UINT wDevID)
451 int i, length;
452 int start, last_start;
453 int total_length = 0;
454 struct cdrom_tocentry entry;
455 if (CDADev[wDevID].nTracks == 0) {
456 if (CDAUDIO_GetNumberOfTracks(wDevID) == (WORD)-1) return FALSE;
458 if (CDADev[wDevID].lpdwTrackLen != NULL)
459 free(CDADev[wDevID].lpdwTrackLen);
460 CDADev[wDevID].lpdwTrackLen = (LPDWORD)malloc(
461 (CDADev[wDevID].nTracks + 1) * sizeof(DWORD));
462 if (CDADev[wDevID].lpdwTrackPos != NULL)
463 free(CDADev[wDevID].lpdwTrackPos);
464 CDADev[wDevID].lpdwTrackPos = (LPDWORD)malloc(
465 (CDADev[wDevID].nTracks + 1) * sizeof(DWORD));
466 if (CDADev[wDevID].lpdwTrackLen == NULL ||
467 CDADev[wDevID].lpdwTrackPos == NULL) {
468 printf("CDAUDIO_GetTracksInfo // error allocating track table !\n");
469 return FALSE;
471 memset(CDADev[wDevID].lpdwTrackLen, 0,
472 (CDADev[wDevID].nTracks + 1) * sizeof(DWORD));
473 memset(CDADev[wDevID].lpdwTrackPos, 0,
474 (CDADev[wDevID].nTracks + 1) * sizeof(DWORD));
475 for (i = 0; i <= CDADev[wDevID].nTracks; i++) {
476 if (i == CDADev[wDevID].nTracks)
477 entry.cdte_track = CDROM_LEADOUT;
478 else
479 entry.cdte_track = i + 1;
480 entry.cdte_format = CDROM_MSF;
481 if (ioctl(CDADev[wDevID].unixdev, CDROMREADTOCENTRY, &entry)) {
482 printf("CDAUDIO_GetTracksInfo // error read entry\n");
483 return FALSE;
485 start = CDFRAMES_PERSEC * (SECONDS_PERMIN *
486 entry.cdte_addr.msf.minute + entry.cdte_addr.msf.second) +
487 entry.cdte_addr.msf.frame;
488 if (i == 0) {
489 CDADev[wDevID].dwFirstOffset = last_start = start;
490 printf("CDAUDIO_GetTracksInfo // dwFirstOffset=%u\n", start);
492 else {
493 length = start - last_start;
494 last_start = start;
495 start = last_start - length;
496 total_length += length;
497 CDADev[wDevID].lpdwTrackLen[i - 1] = length;
498 CDADev[wDevID].lpdwTrackPos[i - 1] = start;
499 printf("CDAUDIO_GetTracksInfo // track #%u start=%u len=%u\n",
500 i, start, length);
503 CDADev[wDevID].dwTotalLen = total_length;
504 printf("CDAUDIO_GetTracksInfo // total_len=%u\n", total_length);
505 return TRUE;
509 /**************************************************************************
510 * CDAUDIO_GetNumberOfTracks [internal]
512 BOOL CDAUDIO_GetCDStatus(UINT wDevID)
514 int oldmode = CDADev[wDevID].mode;
515 CDADev[wDevID].sc.cdsc_format = CDROM_MSF;
516 if (ioctl(CDADev[wDevID].unixdev, CDROMSUBCHNL, &CDADev[wDevID].sc)) {
517 #ifdef DEBUG_CDAUDIO
518 printf("CDAUDIO_GetCDStatus // opened or no_media !\n");
519 #endif
520 CDADev[wDevID].mode = MCI_MODE_OPEN;
521 return TRUE;
523 switch (CDADev[wDevID].sc.cdsc_audiostatus) {
524 case CDROM_AUDIO_INVALID:
525 printf("CDAUDIO_GetCDStatus // device doesn't support status !\n");
526 return FALSE;
527 case CDROM_AUDIO_NO_STATUS:
528 CDADev[wDevID].mode = MCI_MODE_STOP;
529 #ifdef DEBUG_CDAUDIO
530 printf("CDAUDIO_GetCDStatus // MCI_MODE_STOP !\n");
531 #endif
532 break;
533 case CDROM_AUDIO_PLAY:
534 CDADev[wDevID].mode = MCI_MODE_PLAY;
535 #ifdef DEBUG_CDAUDIO
536 printf("CDAUDIO_GetCDStatus // MCI_MODE_PLAY !\n");
537 #endif
538 break;
539 case CDROM_AUDIO_PAUSED:
540 CDADev[wDevID].mode = MCI_MODE_PAUSE;
541 #ifdef DEBUG_CDAUDIO
542 printf("CDAUDIO_GetCDStatus // MCI_MODE_PAUSE !\n");
543 #endif
544 break;
545 default:
546 printf("CDAUDIO_GetCDStatus // status=%02X !\n",
547 CDADev[wDevID].sc.cdsc_audiostatus);
549 CDADev[wDevID].nCurTrack = CDADev[wDevID].sc.cdsc_trk;
550 CDADev[wDevID].dwCurFrame =
551 CDFRAMES_PERMIN * CDADev[wDevID].sc.cdsc_absaddr.msf.minute +
552 CDFRAMES_PERSEC * CDADev[wDevID].sc.cdsc_absaddr.msf.second +
553 CDADev[wDevID].sc.cdsc_absaddr.msf.frame;
554 #ifdef DEBUG_CDAUDIO
555 printf("CDAUDIO_GetCDStatus // %02u-%02u:%02u:%02u \n",
556 CDADev[wDevID].sc.cdsc_trk,
557 CDADev[wDevID].sc.cdsc_absaddr.msf.minute,
558 CDADev[wDevID].sc.cdsc_absaddr.msf.second,
559 CDADev[wDevID].sc.cdsc_absaddr.msf.frame);
560 #endif
561 if (oldmode != CDADev[wDevID].mode && oldmode == MCI_MODE_OPEN) {
562 if (!CDAUDIO_GetTracksInfo(wDevID)) {
563 printf("CDAUDIO_GetCDStatus // error updating TracksInfo !\n");
564 return MCIERR_INTERNAL;
567 return TRUE;
570 /**************************************************************************
571 * CDAUDIO_mciPlay [internal]
573 DWORD CDAUDIO_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
575 int start, end;
576 struct cdrom_msf msf;
577 #ifdef DEBUG_CDAUDIO
578 printf("CDAUDIO_mciPlay(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
579 #endif
580 if (lpParms == NULL) return MCIERR_INTERNAL;
581 if (CDADev[wDevID].unixdev == 0) return MMSYSERR_NOTENABLED;
582 start = 0; end = CDADev[wDevID].dwTotalLen;
583 CDADev[wDevID].nCurTrack = 1;
584 if (dwFlags & MCI_FROM) {
585 start = CDAUDIO_CalcFrame(wDevID,
586 CDADev[wDevID].dwTimeFormat, lpParms->dwFrom);
587 #ifdef DEBUG_CDAUDIO
588 printf("CDAUDIO_mciPlay // MCI_FROM=%08X -> %u \n",
589 lpParms->dwFrom, start);
590 #endif
592 if (dwFlags & MCI_TO) {
593 end = CDAUDIO_CalcFrame(wDevID,
594 CDADev[wDevID].dwTimeFormat, lpParms->dwTo);
595 #ifdef DEBUG_CDAUDIO
596 printf("CDAUDIO_mciPlay // MCI_TO=%08X -> %u \n",
597 lpParms->dwTo, end);
598 #endif
600 start += CDADev[wDevID].dwFirstOffset;
601 end += CDADev[wDevID].dwFirstOffset;
602 msf.cdmsf_min0 = start / CDFRAMES_PERMIN;
603 msf.cdmsf_sec0 = (start % CDFRAMES_PERMIN) / CDFRAMES_PERSEC;
604 msf.cdmsf_frame0 = start % CDFRAMES_PERSEC;
605 msf.cdmsf_min1 = end / CDFRAMES_PERMIN;
606 msf.cdmsf_sec1 = (end % CDFRAMES_PERMIN) / CDFRAMES_PERSEC;
607 msf.cdmsf_frame1 = end % CDFRAMES_PERSEC;
608 if (ioctl(CDADev[wDevID].unixdev, CDROMSTART)) {
609 printf("CDAUDIO_mciPlay // motor doesn't start !\n");
610 return MCIERR_HARDWARE;
612 if (ioctl(CDADev[wDevID].unixdev, CDROMPLAYMSF, &msf)) {
613 printf("CDAUDIO_mciPlay // device doesn't play !\n");
614 return MCIERR_HARDWARE;
616 #ifdef DEBUG_CDAUDIO
617 printf("CDAUDIO_mciPlay // msf = %d:%d:%d %d:%d:%d\n",
618 msf.cdmsf_min0, msf.cdmsf_sec0, msf.cdmsf_frame0,
619 msf.cdmsf_min1, msf.cdmsf_sec1, msf.cdmsf_frame1);
620 #endif
621 CDADev[wDevID].mode = MCI_MODE_PLAY;
622 if (dwFlags & MCI_NOTIFY) {
623 printf("CDAUDIO_mciPlay // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback);
624 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
625 CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
627 return 0;
630 /**************************************************************************
631 * CDAUDIO_mciStop [internal]
633 DWORD CDAUDIO_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
635 #ifdef DEBUG_CDAUDIO
636 printf("CDAUDIO_mciStop(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
637 #endif
638 if (lpParms == NULL) return MCIERR_INTERNAL;
639 if (ioctl(CDADev[wDevID].unixdev, CDROMSTOP)) return MCIERR_HARDWARE;
640 CDADev[wDevID].mode = MCI_MODE_STOP;
641 if (dwFlags & MCI_NOTIFY) {
642 printf("CDAUDIO_mciStop // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback);
643 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
644 CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
646 return 0;
649 /**************************************************************************
650 * CDAUDIO_mciPause [internal]
652 DWORD CDAUDIO_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
654 #ifdef DEBUG_CDAUDIO
655 printf("CDAUDIO_mciPause(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
656 #endif
657 if (lpParms == NULL) return MCIERR_INTERNAL;
658 if (ioctl(CDADev[wDevID].unixdev, CDROMPAUSE)) return MCIERR_HARDWARE;
659 CDADev[wDevID].mode = MCI_MODE_PAUSE;
660 if (dwFlags & MCI_NOTIFY) {
661 printf("CDAUDIO_mciPause // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback);
662 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
663 CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
665 return 0;
668 /**************************************************************************
669 * CDAUDIO_mciResume [internal]
671 DWORD CDAUDIO_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
673 #ifdef DEBUG_CDAUDIO
674 printf("CDAUDIO_mciResume(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
675 #endif
676 if (lpParms == NULL) return MCIERR_INTERNAL;
677 if (ioctl(CDADev[wDevID].unixdev, CDROMRESUME)) return MCIERR_HARDWARE;
678 CDADev[wDevID].mode = MCI_MODE_STOP;
679 if (dwFlags & MCI_NOTIFY) {
680 printf("CDAUDIO_mciResume // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback);
681 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
682 CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
684 return 0;
687 /**************************************************************************
688 * CDAUDIO_mciSeek [internal]
690 DWORD CDAUDIO_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
692 DWORD dwRet;
693 MCI_PLAY_PARMS PlayParms;
694 #ifdef DEBUG_CDAUDIO
695 printf("CDAUDIO_mciSeek(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
696 #endif
697 if (lpParms == NULL) return MCIERR_INTERNAL;
698 if (ioctl(CDADev[wDevID].unixdev, CDROMRESUME)) return MCIERR_HARDWARE;
699 CDADev[wDevID].mode = MCI_MODE_SEEK;
700 switch(dwFlags) {
701 case MCI_SEEK_TO_START:
702 PlayParms.dwFrom = 0;
703 break;
704 case MCI_SEEK_TO_END:
705 PlayParms.dwFrom = CDADev[wDevID].dwTotalLen;
706 break;
707 case MCI_TO:
708 PlayParms.dwFrom = lpParms->dwTo;
709 break;
711 dwRet = CDAUDIO_mciPlay(wDevID, MCI_WAIT | MCI_FROM, &PlayParms);
712 if (dwRet != 0) return dwRet;
713 dwRet = CDAUDIO_mciStop(wDevID, MCI_WAIT, (LPMCI_GENERIC_PARMS)&PlayParms);
714 if (dwFlags & MCI_NOTIFY) {
715 printf("CDAUDIO_mciSeek // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback);
716 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
717 CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
719 return dwRet;
723 /**************************************************************************
724 * CDAUDIO_mciSet [internal]
726 DWORD CDAUDIO_mciSet(UINT wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
728 #ifdef DEBUG_CDAUDIO
729 printf("CDAUDIO_mciSet(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
730 #endif
731 if (lpParms == NULL) return MCIERR_INTERNAL;
733 printf("CDAUDIO_mciSet // dwTimeFormat=%08X\n", lpParms->dwTimeFormat);
734 printf("CDAUDIO_mciSet // dwAudio=%08X\n", lpParms->dwAudio);
736 if (dwFlags & MCI_SET_TIME_FORMAT) {
737 switch (lpParms->dwTimeFormat) {
738 case MCI_FORMAT_MILLISECONDS:
739 #ifdef DEBUG_CDAUDIO
740 printf("CDAUDIO_mciSet // MCI_FORMAT_MILLISECONDS !\n");
741 #endif
742 break;
743 case MCI_FORMAT_MSF:
744 #ifdef DEBUG_CDAUDIO
745 printf("CDAUDIO_mciSet // MCI_FORMAT_MSF !\n");
746 #endif
747 break;
748 case MCI_FORMAT_TMSF:
749 #ifdef DEBUG_CDAUDIO
750 printf("CDAUDIO_mciSet // MCI_FORMAT_TMSF !\n");
751 #endif
752 break;
753 default:
754 printf("CDAUDIO_mciSet // bad time format !\n");
755 return MCIERR_BAD_TIME_FORMAT;
757 CDADev[wDevID].dwTimeFormat = lpParms->dwTimeFormat;
759 if (dwFlags & MCI_SET_DOOR_OPEN) {
760 printf("CDAUDIO_mciSet // MCI_SET_DOOR_OPEN !\n");
761 if (ioctl(CDADev[wDevID].unixdev, CDROMEJECT)) return MCIERR_HARDWARE;
762 CDADev[wDevID].nTracks = 0;
764 if (dwFlags & MCI_SET_DOOR_CLOSED) {
765 printf("CDAUDIO_mciSet // MCI_SET_DOOR_CLOSED !\n");
766 if (ioctl(CDADev[wDevID].unixdev, CDROMEJECT)) return MCIERR_HARDWARE;
767 CDADev[wDevID].nTracks = 0;
769 if (dwFlags & MCI_SET_VIDEO) return MCIERR_UNSUPPORTED_FUNCTION;
770 if (dwFlags & MCI_SET_ON) return MCIERR_UNSUPPORTED_FUNCTION;
771 if (dwFlags & MCI_SET_OFF) return MCIERR_UNSUPPORTED_FUNCTION;
772 if (dwFlags & MCI_NOTIFY) {
773 printf("CDAUDIO_mciSet // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback);
774 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
775 CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
777 return 0;
781 /**************************************************************************
782 * CDAUDIO_DriverProc [sample driver]
784 LRESULT CDAUDIO_DriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg,
785 DWORD dwParam1, DWORD dwParam2)
787 switch(wMsg) {
788 case DRV_LOAD:
789 return (LRESULT)1L;
790 case DRV_FREE:
791 return (LRESULT)1L;
792 case DRV_OPEN:
793 case MCI_OPEN_DRIVER:
794 case MCI_OPEN:
795 return CDAUDIO_mciOpen(dwParam1, (LPMCI_OPEN_PARMS)dwParam2);
796 case DRV_CLOSE:
797 case MCI_CLOSE_DRIVER:
798 case MCI_CLOSE:
799 return CDAUDIO_mciClose(dwDevID, dwParam1,
800 (LPMCI_GENERIC_PARMS)dwParam2);
801 case DRV_ENABLE:
802 return (LRESULT)1L;
803 case DRV_DISABLE:
804 return (LRESULT)1L;
805 case DRV_QUERYCONFIGURE:
806 return (LRESULT)1L;
807 case DRV_CONFIGURE:
808 MessageBox((HWND)NULL, "Sample MultiMedia Linux Driver !",
809 "MMLinux Driver", MB_OK);
810 return (LRESULT)1L;
811 case DRV_INSTALL:
812 return (LRESULT)DRVCNF_RESTART;
813 case DRV_REMOVE:
814 return (LRESULT)DRVCNF_RESTART;
815 case MCI_GETDEVCAPS:
816 return CDAUDIO_mciGetDevCaps(dwDevID, dwParam1,
817 (LPMCI_GETDEVCAPS_PARMS)dwParam2);
818 case MCI_INFO:
819 return CDAUDIO_mciInfo(dwDevID, dwParam1,
820 (LPMCI_INFO_PARMS)dwParam2);
821 case MCI_STATUS:
822 return CDAUDIO_mciStatus(dwDevID, dwParam1,
823 (LPMCI_STATUS_PARMS)dwParam2);
824 case MCI_SET:
825 return CDAUDIO_mciSet(dwDevID, dwParam1,
826 (LPMCI_SET_PARMS)dwParam2);
827 case MCI_PLAY:
828 return CDAUDIO_mciPlay(dwDevID, dwParam1,
829 (LPMCI_PLAY_PARMS)dwParam2);
830 case MCI_STOP:
831 return CDAUDIO_mciStop(dwDevID, dwParam1,
832 (LPMCI_GENERIC_PARMS)dwParam2);
833 case MCI_PAUSE:
834 return CDAUDIO_mciPause(dwDevID, dwParam1,
835 (LPMCI_GENERIC_PARMS)dwParam2);
836 case MCI_RESUME:
837 return CDAUDIO_mciResume(dwDevID, dwParam1,
838 (LPMCI_GENERIC_PARMS)dwParam2);
839 case MCI_SEEK:
840 return CDAUDIO_mciSeek(dwDevID, dwParam1,
841 (LPMCI_SEEK_PARMS)dwParam2);
842 case MCI_SET_DOOR_OPEN:
843 printf("CDAUDIO_DriverProc // MCI_SET_DOOR_OPEN !\n");
844 if (ioctl(CDADev[dwDevID].unixdev, CDROMEJECT)) return MCIERR_HARDWARE;
845 CDADev[dwDevID].nTracks = 0;
846 return 0;
847 case MCI_SET_DOOR_CLOSED:
848 printf("CDAUDIO_DriverProc // MCI_SET_DOOR_CLOSED !\n");
849 if (ioctl(CDADev[dwDevID].unixdev, CDROMEJECT, 1)) return MCIERR_HARDWARE;
850 CDADev[dwDevID].nTracks = 0;
851 return 0;
852 default:
853 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
858 /*-----------------------------------------------------------------------*/
860 #endif