Release 940722
[wine/multimedia.git] / misc / mcicda.c
blobc96fb279cd9196b2bd4d68638032929a7eb1f5dc
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 #ifdef linux
22 #include <linux/soundcard.h>
23 #include <linux/cdrom.h>
24 #endif
26 #define SOUND_DEV "/dev/dsp"
27 #define CDAUDIO_DEV "/dev/sbpcd"
29 #ifdef SOUND_VERSION
30 #define IOCTL(a,b,c) ioctl(a,b,&c)
31 #else
32 #define IOCTL(a,b,c) (c = ioctl(a,b,c) )
33 #endif
35 #define MAX_CDAUDIODRV 2
36 #define MAX_CDAUDIO_TRACKS 256
38 #define CDFRAMES_PERSEC 75
39 #define CDFRAMES_PERMIN 4500
40 #define SECONDS_PERMIN 60
42 #ifdef linux
43 typedef struct {
44 int nUseCount; /* Incremented for each shared open */
45 BOOL fShareable; /* TRUE if first open was shareable */
46 WORD wNotifyDeviceID; /* MCI device ID with a pending notification */
47 HANDLE hCallback; /* Callback handle for pending notification */
48 MCI_OPEN_PARMS openParms;
49 DWORD dwTimeFormat;
50 int unixdev;
51 struct cdrom_subchnl sc;
52 int mode;
53 UINT nCurTrack;
54 DWORD dwCurFrame;
55 UINT nTracks;
56 DWORD dwTotalLen;
57 LPDWORD lpdwTrackLen;
58 LPDWORD lpdwTrackPos;
59 DWORD dwFirstOffset;
60 } LINUX_CDAUDIO;
62 static LINUX_CDAUDIO CDADev[MAX_CDAUDIODRV];
63 #endif
65 UINT CDAUDIO_GetNumberOfTracks(UINT wDevID);
66 BOOL CDAUDIO_GetTracksInfo(UINT wDevID);
67 BOOL CDAUDIO_GetCDStatus(UINT wDevID);
68 DWORD CDAUDIO_CalcTime(UINT wDevID, DWORD dwFormatType, DWORD dwFrame);
71 /*-----------------------------------------------------------------------*/
74 /**************************************************************************
75 * CDAUDIO_mciOpen [internal]
77 DWORD CDAUDIO_mciOpen(DWORD dwFlags, LPMCI_OPEN_PARMS lpParms)
79 #ifdef linux
80 UINT wDevID;
81 int cdrom;
82 #ifdef DEBUG_CDAUDIO
83 printf("CDAUDIO_mciOpen(%08X, %08X);\n", dwFlags, lpParms);
84 #endif
85 if (lpParms == NULL) return MCIERR_INTERNAL;
86 wDevID = lpParms->wDeviceID;
87 if (CDADev[wDevID].nUseCount > 0) {
88 /* The driver already open on this channel */
89 /* If the driver was% op, ened shareable before and this open specifies */
90 /* shareable then increment the use count */
91 if (CDADev[wDevID].fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
92 ++CDADev[wDevID].nUseCount;
93 else
94 return MCIERR_MUST_USE_SHAREABLE;
96 else {
97 CDADev[wDevID].nUseCount = 1;
98 CDADev[wDevID].fShareable = dwFlags & MCI_OPEN_SHAREABLE;
100 if (dwFlags & MCI_OPEN_ELEMENT) {
101 printf("CDAUDIO_mciOpen // MCI_OPEN_ELEMENT !\n");
102 /* return MCIERR_NO_ELEMENT_ALLOWED; */
104 memcpy(&CDADev[wDevID].openParms, lpParms, sizeof(MCI_OPEN_PARMS));
105 CDADev[wDevID].wNotifyDeviceID = lpParms->wDeviceID;
106 CDADev[wDevID].unixdev = open (CDAUDIO_DEV, O_RDONLY, 0);
107 if (CDADev[wDevID].unixdev == -1) {
108 printf("CDAUDIO_mciOpen // can't open '%s' !\n", CDAUDIO_DEV);
109 return MCIERR_HARDWARE;
111 CDADev[wDevID].mode = 0;
112 CDADev[wDevID].dwTimeFormat = MCI_FORMAT_TMSF;
113 CDADev[wDevID].nCurTrack = 0;
114 CDADev[wDevID].nTracks = 0;
115 CDADev[wDevID].dwTotalLen = 0;
116 CDADev[wDevID].dwFirstOffset = 0;
117 CDADev[wDevID].lpdwTrackLen = NULL;
118 CDADev[wDevID].lpdwTrackPos = NULL;
119 if (!CDAUDIO_GetTracksInfo(wDevID)) {
120 printf("CDAUDIO_mciOpen // error reading TracksInfo !\n");
121 /* return MCIERR_INTERNAL; */
123 if (dwFlags & MCI_NOTIFY) {
124 printf("CDAUDIO_mciOpen // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback);
125 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
126 CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
128 return 0;
129 #else
130 return MCIERR_HARDWARE;
131 #endif
134 /**************************************************************************
135 * CDAUDIO_mciClose [internal]
137 DWORD CDAUDIO_mciClose(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
139 #ifdef linux
140 #ifdef DEBUG_CDAUDIO
141 printf("CDAUDIO_mciClose(%u, %08X, %08X);\n", wDevID, dwParam, lpParms);
142 #endif
143 if (CDADev[wDevID].lpdwTrackLen != NULL) free(CDADev[wDevID].lpdwTrackLen);
144 if (CDADev[wDevID].lpdwTrackPos != NULL) free(CDADev[wDevID].lpdwTrackPos);
145 close(CDADev[wDevID].unixdev);
146 #endif
149 /**************************************************************************
150 * CDAUDIO_mciGetDevCaps [internal]
152 DWORD CDAUDIO_mciGetDevCaps(UINT wDevID, DWORD dwFlags,
153 LPMCI_GETDEVCAPS_PARMS lpParms)
155 #ifdef linux
156 #ifdef DEBUG_CDAUDIO
157 printf("CDAUDIO_mciGetDevCaps(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
158 #endif
159 if (lpParms == NULL) return MCIERR_INTERNAL;
160 if (dwFlags & MCI_GETDEVCAPS_ITEM) {
161 printf("CDAUDIO_mciGetDevCaps // MCI_GETDEVCAPS_ITEM dwItem=%08X);\n",
162 lpParms->dwItem);
163 switch(lpParms->dwItem) {
164 case MCI_GETDEVCAPS_CAN_RECORD:
165 lpParms->dwReturn = FALSE;
166 break;
167 case MCI_GETDEVCAPS_HAS_AUDIO:
168 lpParms->dwReturn = TRUE;
169 break;
170 case MCI_GETDEVCAPS_HAS_VIDEO:
171 lpParms->dwReturn = FALSE;
172 break;
173 case MCI_GETDEVCAPS_DEVICE_TYPE:
174 lpParms->dwReturn = MCI_DEVTYPE_CD_AUDIO;
175 break;
176 case MCI_GETDEVCAPS_USES_FILES:
177 lpParms->dwReturn = FALSE;
178 break;
179 case MCI_GETDEVCAPS_COMPOUND_DEVICE:
180 lpParms->dwReturn = FALSE;
181 break;
182 case MCI_GETDEVCAPS_CAN_EJECT:
183 lpParms->dwReturn = TRUE;
184 break;
185 case MCI_GETDEVCAPS_CAN_PLAY:
186 lpParms->dwReturn = TRUE;
187 break;
188 case MCI_GETDEVCAPS_CAN_SAVE:
189 lpParms->dwReturn = FALSE;
190 break;
191 default:
192 return MCIERR_UNRECOGNIZED_COMMAND;
195 printf("CDAUDIO_mciGetDevCaps // lpParms->dwReturn=%08X);\n", lpParms->dwReturn);
196 return 0;
197 #else
198 return MCIERR_INTERNAL;
199 #endif
202 /**************************************************************************
203 * CDAUDIO_mciInfo [internal]
205 DWORD CDAUDIO_mciInfo(UINT wDevID, DWORD dwFlags, LPMCI_INFO_PARMS lpParms)
207 #ifdef linux
208 #ifdef DEBUG_CDAUDIO
209 printf("CDAUDIO_mciInfo(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
210 #endif
211 if (lpParms == NULL) return MCIERR_INTERNAL;
212 lpParms->lpstrReturn = NULL;
213 switch(dwFlags) {
214 case MCI_INFO_PRODUCT:
215 lpParms->lpstrReturn = "Linux CDROM 0.5";
216 break;
217 default:
218 return MCIERR_UNRECOGNIZED_COMMAND;
220 if (lpParms->lpstrReturn != NULL)
221 lpParms->dwRetSize = strlen(lpParms->lpstrReturn);
222 else
223 lpParms->dwRetSize = 0;
224 return 0;
225 #else
226 return MCIERR_INTERNAL;
227 #endif
230 /**************************************************************************
231 * CDAUDIO_mciStatus [internal]
233 DWORD CDAUDIO_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
235 #ifdef linux
236 #ifdef DEBUG_CDAUDIO
237 printf("CDAUDIO_mciStatus(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
238 #endif
239 if (lpParms == NULL) return MCIERR_INTERNAL;
240 if (CDADev[wDevID].unixdev == 0) return MMSYSERR_NOTENABLED;
241 if (dwFlags & MCI_NOTIFY) {
242 #ifdef DEBUG_CDAUDIO
243 printf("CDAUDIO_mciStatus // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback);
244 #endif
245 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
246 CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
248 if (dwFlags & MCI_STATUS_ITEM) {
249 switch(lpParms->dwItem) {
250 case MCI_STATUS_CURRENT_TRACK:
251 if (!CDAUDIO_GetCDStatus(wDevID)) return MCIERR_INTERNAL;
252 lpParms->dwReturn = CDADev[wDevID].nCurTrack;
253 #ifdef DEBUG_CDAUDIO
254 printf("CDAUDIO_mciStatus // CURRENT_TRACK=%u!\n", lpParms->dwReturn);
255 #endif
256 return 0;
257 case MCI_STATUS_LENGTH:
258 if (CDADev[wDevID].nTracks == 0) {
259 if (!CDAUDIO_GetTracksInfo(wDevID)) {
260 printf("CDAUDIO_mciStatus // error reading TracksInfo !\n");
261 return MCIERR_INTERNAL;
264 if (dwFlags & MCI_TRACK) {
265 printf("CDAUDIO_mciStatus // MCI_TRACK #%u LENGTH=??? !\n",
266 lpParms->dwTrack);
267 if (lpParms->dwTrack > CDADev[wDevID].nTracks)
268 return MCIERR_OUTOFRANGE;
269 lpParms->dwReturn = CDADev[wDevID].lpdwTrackLen[lpParms->dwTrack];
271 else
272 lpParms->dwReturn = CDADev[wDevID].dwTotalLen;
273 lpParms->dwReturn = CDAUDIO_CalcTime(wDevID,
274 CDADev[wDevID].dwTimeFormat, lpParms->dwReturn);
275 printf("CDAUDIO_mciStatus // LENGTH=%u !\n", lpParms->dwReturn);
276 return 0;
277 case MCI_STATUS_MODE:
278 if (!CDAUDIO_GetCDStatus(wDevID)) return MCIERR_INTERNAL;
279 lpParms->dwReturn = CDADev[wDevID].mode;
280 #ifdef DEBUG_CDAUDIO
281 printf("CDAUDIO_mciStatus // MCI_STATUS_MODE=%08X !\n",
282 lpParms->dwReturn);
283 #endif
284 return 0;
285 case MCI_STATUS_MEDIA_PRESENT:
286 lpParms->dwReturn = (CDADev[wDevID].nTracks > 0) ? TRUE : FALSE;
287 if (lpParms->dwReturn == FALSE)
288 printf("CDAUDIO_mciStatus // MEDIA_NOT_PRESENT !\n");
289 else
290 printf("CDAUDIO_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
291 return 0;
292 case MCI_STATUS_NUMBER_OF_TRACKS:
293 lpParms->dwReturn = CDAUDIO_GetNumberOfTracks(wDevID);
294 printf("CDAUDIO_mciStatus // MCI_STATUS_NUMBER_OF_TRACKS = %u !\n",
295 lpParms->dwReturn);
296 if (lpParms->dwReturn == (WORD)-1) return MCIERR_INTERNAL;
297 return 0;
298 case MCI_STATUS_POSITION:
299 if (!CDAUDIO_GetCDStatus(wDevID)) return MCIERR_INTERNAL;
300 lpParms->dwReturn = CDADev[wDevID].dwCurFrame;
301 if (dwFlags & MCI_STATUS_START) {
302 lpParms->dwReturn = CDADev[wDevID].dwFirstOffset;
303 #ifdef DEBUG_CDAUDIO
304 printf("CDAUDIO_mciStatus // get MCI_STATUS_START !\n");
305 #endif
307 if (dwFlags & MCI_TRACK) {
308 if (lpParms->dwTrack > CDADev[wDevID].nTracks)
309 return MCIERR_OUTOFRANGE;
310 lpParms->dwReturn = CDADev[wDevID].lpdwTrackPos[lpParms->dwTrack - 1];
311 #ifdef DEBUG_CDAUDIO
312 printf("CDAUDIO_mciStatus // get MCI_TRACK #%u !\n", lpParms->dwTrack);
313 #endif
315 lpParms->dwReturn = CDAUDIO_CalcTime(wDevID,
316 CDADev[wDevID].dwTimeFormat, lpParms->dwReturn);
317 #ifdef DEBUG_CDAUDIO
318 printf("CDAUDIO_mciStatus // MCI_STATUS_POSITION=%08X !\n",
319 lpParms->dwReturn);
320 #endif
321 return 0;
322 case MCI_STATUS_READY:
323 printf("CDAUDIO_mciStatus // MCI_STATUS_READY !\n");
324 lpParms->dwReturn = TRUE;
325 return 0;
326 case MCI_STATUS_TIME_FORMAT:
327 printf("CDAUDIO_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
328 lpParms->dwReturn = MCI_FORMAT_MILLISECONDS;
329 return 0;
330 default:
331 printf("CDAUDIO_mciStatus // unknowm command %04X !\n", lpParms->dwItem);
332 return MCIERR_UNRECOGNIZED_COMMAND;
335 printf("CDAUDIO_mciStatus // not MCI_STATUS_ITEM !\n");
336 return 0;
337 #else
338 return MMSYSERR_NOTENABLED;
339 #endif
343 /**************************************************************************
344 * CDAUDIO_CalcTime [internal]
346 DWORD CDAUDIO_CalcTime(UINT wDevID, DWORD dwFormatType, DWORD dwFrame)
348 DWORD dwTime = 0;
349 #ifdef linux
350 UINT wTrack;
351 UINT wMinutes;
352 UINT wSeconds;
353 UINT wFrames;
354 #ifdef DEBUG_CDAUDIO
355 printf("CDAUDIO_CalcTime(%u, %08X, %lu);\n", wDevID, dwFormatType, dwFrame);
356 #endif
357 TryAGAIN:
358 switch (dwFormatType) {
359 case MCI_FORMAT_MILLISECONDS:
360 dwTime = dwFrame / CDFRAMES_PERSEC * 1000;
361 #ifdef DEBUG_CDAUDIO
362 printf("CDAUDIO_CalcTime // MILLISECONDS %u\n", dwTime);
363 #endif
364 break;
365 case MCI_FORMAT_MSF:
366 wMinutes = dwFrame / CDFRAMES_PERMIN;
367 wSeconds = (dwFrame - CDFRAMES_PERMIN * wMinutes) / CDFRAMES_PERSEC;
368 wFrames = dwFrame - CDFRAMES_PERMIN * wMinutes -
369 CDFRAMES_PERSEC * wSeconds;
370 dwTime = MCI_MAKE_MSF(wMinutes, wSeconds, wFrames);
371 #ifdef DEBUG_CDAUDIO
372 printf("CDAUDIO_CalcTime // MSF %02u:%02u:%02u -> dwTime=%u\n",
373 wMinutes, wSeconds, wFrames, dwTime);
374 #endif
375 break;
376 case MCI_FORMAT_TMSF:
377 for (wTrack = 0; wTrack < CDADev[wDevID].nTracks; wTrack++) {
378 /* dwTime += CDADev[wDevID].lpdwTrackLen[wTrack - 1];
379 printf("Adding trk#%u curpos=%u \n", dwTime);
380 if (dwTime >= dwFrame) break; */
381 if (CDADev[wDevID].lpdwTrackPos[wTrack - 1] >= dwFrame) break;
383 wMinutes = dwFrame / CDFRAMES_PERMIN;
384 wSeconds = (dwFrame - CDFRAMES_PERMIN * wMinutes) / CDFRAMES_PERSEC;
385 wFrames = dwFrame - CDFRAMES_PERMIN * wMinutes -
386 CDFRAMES_PERSEC * wSeconds;
387 dwTime = MCI_MAKE_TMSF(wTrack, wMinutes, wSeconds, wFrames);
388 #ifdef DEBUG_CDAUDIO
389 printf("CDAUDIO_CalcTime // %02u-%02u:%02u:%02u\n",
390 wTrack, wMinutes, wSeconds, wFrames);
391 #endif
392 break;
393 default:
394 /* unknown format ! force TMSF ! ... */
395 dwFormatType = MCI_FORMAT_TMSF;
396 goto TryAGAIN;
398 #endif
399 return dwTime;
403 /**************************************************************************
404 * CDAUDIO_CalcFrame [internal]
406 DWORD CDAUDIO_CalcFrame(UINT wDevID, DWORD dwFormatType, DWORD dwTime)
408 DWORD dwFrame = 0;
409 #ifdef linux
410 UINT wTrack;
411 #ifdef DEBUG_CDAUDIO
412 printf("CDAUDIO_CalcFrame(%u, %08X, %lu);\n", wDevID, dwFormatType, dwTime);
413 #endif
414 TryAGAIN:
415 switch (dwFormatType) {
416 case MCI_FORMAT_MILLISECONDS:
417 dwFrame = dwTime * CDFRAMES_PERSEC / 1000;
418 #ifdef DEBUG_CDAUDIO
419 printf("CDAUDIO_CalcFrame // MILLISECONDS %u\n", dwFrame);
420 #endif
421 break;
422 case MCI_FORMAT_MSF:
423 #ifdef DEBUG_CDAUDIO
424 printf("CDAUDIO_CalcFrame // MSF %02u:%02u:%02u\n",
425 MCI_MSF_MINUTE(dwTime), MCI_MSF_SECOND(dwTime),
426 MCI_MSF_FRAME(dwTime));
427 #endif
428 dwFrame += CDFRAMES_PERMIN * MCI_MSF_MINUTE(dwTime);
429 dwFrame += CDFRAMES_PERSEC * MCI_MSF_SECOND(dwTime);
430 dwFrame += MCI_MSF_FRAME(dwTime);
431 break;
432 case MCI_FORMAT_TMSF:
433 wTrack = MCI_TMSF_TRACK(dwTime);
434 #ifdef DEBUG_CDAUDIO
435 printf("CDAUDIO_CalcFrame // TMSF %02u-%02u:%02u:%02u\n",
436 MCI_TMSF_TRACK(dwTime), MCI_TMSF_MINUTE(dwTime),
437 MCI_TMSF_SECOND(dwTime), MCI_TMSF_FRAME(dwTime));
438 printf("CDAUDIO_CalcFrame // TMSF trackpos[%u]=%u\n",
439 wTrack, CDADev[wDevID].lpdwTrackPos[wTrack - 1]);
440 #endif
441 dwFrame = CDADev[wDevID].lpdwTrackPos[wTrack - 1];
442 dwFrame += CDFRAMES_PERMIN * MCI_TMSF_MINUTE(dwTime);
443 dwFrame += CDFRAMES_PERSEC * MCI_TMSF_SECOND(dwTime);
444 dwFrame += MCI_TMSF_FRAME(dwTime);
445 break;
446 default:
447 /* unknown format ! force TMSF ! ... */
448 dwFormatType = MCI_FORMAT_TMSF;
449 goto TryAGAIN;
451 #endif
452 return dwFrame;
456 /**************************************************************************
457 * CDAUDIO_GetNumberOfTracks [internal]
459 UINT CDAUDIO_GetNumberOfTracks(UINT wDevID)
461 #ifdef linux
462 struct cdrom_tochdr hdr;
463 if (CDADev[wDevID].nTracks == 0) {
464 if (ioctl(CDADev[wDevID].unixdev, CDROMREADTOCHDR, &hdr)) {
465 printf("GetNumberOfTracks(%u) // Error occured !\n", wDevID);
466 return (WORD)-1;
468 CDADev[wDevID].nTracks = hdr.cdth_trk1;
470 return CDADev[wDevID].nTracks;
471 #else
472 return (WORD)-1;
473 #endif
476 /**************************************************************************
477 * CDAUDIO_GetNumberOfTracks [internal]
479 BOOL CDAUDIO_GetTracksInfo(UINT wDevID)
481 #ifdef linux
482 int i, length;
483 int start, last_start;
484 int total_length = 0;
485 struct cdrom_tocentry entry;
486 if (CDADev[wDevID].nTracks == 0) {
487 if (CDAUDIO_GetNumberOfTracks(wDevID) == (WORD)-1) return FALSE;
489 if (CDADev[wDevID].lpdwTrackLen != NULL)
490 free(CDADev[wDevID].lpdwTrackLen);
491 CDADev[wDevID].lpdwTrackLen = (LPDWORD)malloc(
492 (CDADev[wDevID].nTracks + 1) * sizeof(DWORD));
493 if (CDADev[wDevID].lpdwTrackPos != NULL)
494 free(CDADev[wDevID].lpdwTrackPos);
495 CDADev[wDevID].lpdwTrackPos = (LPDWORD)malloc(
496 (CDADev[wDevID].nTracks + 1) * sizeof(DWORD));
497 if (CDADev[wDevID].lpdwTrackLen == NULL ||
498 CDADev[wDevID].lpdwTrackPos == NULL) {
499 printf("CDAUDIO_GetTracksInfo // error allocating track table !\n");
500 return FALSE;
502 memset(CDADev[wDevID].lpdwTrackLen, 0,
503 (CDADev[wDevID].nTracks + 1) * sizeof(DWORD));
504 memset(CDADev[wDevID].lpdwTrackPos, 0,
505 (CDADev[wDevID].nTracks + 1) * sizeof(DWORD));
506 for (i = 0; i <= CDADev[wDevID].nTracks; i++) {
507 if (i == CDADev[wDevID].nTracks)
508 entry.cdte_track = CDROM_LEADOUT;
509 else
510 entry.cdte_track = i + 1;
511 entry.cdte_format = CDROM_MSF;
512 if (ioctl(CDADev[wDevID].unixdev, CDROMREADTOCENTRY, &entry)) {
513 printf("CDAUDIO_GetTracksInfo // error read entry\n");
514 return FALSE;
516 start = CDFRAMES_PERSEC * (SECONDS_PERMIN *
517 entry.cdte_addr.msf.minute + entry.cdte_addr.msf.second) +
518 entry.cdte_addr.msf.frame;
519 if (i == 0) {
520 CDADev[wDevID].dwFirstOffset = last_start = start;
521 printf("CDAUDIO_GetTracksInfo // dwFirstOffset=%u\n", start);
523 else {
524 length = start - last_start;
525 last_start = start;
526 start = last_start - length;
527 total_length += length;
528 CDADev[wDevID].lpdwTrackLen[i - 1] = length;
529 CDADev[wDevID].lpdwTrackPos[i - 1] = start;
530 printf("CDAUDIO_GetTracksInfo // track #%u start=%u len=%u\n",
531 i, start, length);
534 CDADev[wDevID].dwTotalLen = total_length;
535 printf("CDAUDIO_GetTracksInfo // total_len=%u\n", total_length);
536 return TRUE;
537 #else
538 return FALSE;
539 #endif
543 /**************************************************************************
544 * CDAUDIO_GetNumberOfTracks [internal]
546 BOOL CDAUDIO_GetCDStatus(UINT wDevID)
548 #ifdef linux
549 int oldmode = CDADev[wDevID].mode;
550 CDADev[wDevID].sc.cdsc_format = CDROM_MSF;
551 if (ioctl(CDADev[wDevID].unixdev, CDROMSUBCHNL, &CDADev[wDevID].sc)) {
552 #ifdef DEBUG_CDAUDIO
553 printf("CDAUDIO_GetCDStatus // opened or no_media !\n");
554 #endif
555 CDADev[wDevID].mode = MCI_MODE_OPEN;
556 return TRUE;
558 switch (CDADev[wDevID].sc.cdsc_audiostatus) {
559 case CDROM_AUDIO_INVALID:
560 printf("CDAUDIO_GetCDStatus // device doesn't support status !\n");
561 return FALSE;
562 case CDROM_AUDIO_NO_STATUS:
563 CDADev[wDevID].mode = MCI_MODE_STOP;
564 #ifdef DEBUG_CDAUDIO
565 printf("CDAUDIO_GetCDStatus // MCI_MODE_STOP !\n");
566 #endif
567 break;
568 case CDROM_AUDIO_PLAY:
569 CDADev[wDevID].mode = MCI_MODE_PLAY;
570 #ifdef DEBUG_CDAUDIO
571 printf("CDAUDIO_GetCDStatus // MCI_MODE_PLAY !\n");
572 #endif
573 break;
574 case CDROM_AUDIO_PAUSED:
575 CDADev[wDevID].mode = MCI_MODE_PAUSE;
576 #ifdef DEBUG_CDAUDIO
577 printf("CDAUDIO_GetCDStatus // MCI_MODE_PAUSE !\n");
578 #endif
579 break;
580 default:
581 printf("CDAUDIO_GetCDStatus // status=%02X !\n",
582 CDADev[wDevID].sc.cdsc_audiostatus);
584 CDADev[wDevID].nCurTrack = CDADev[wDevID].sc.cdsc_trk;
585 CDADev[wDevID].dwCurFrame =
586 CDFRAMES_PERMIN * CDADev[wDevID].sc.cdsc_absaddr.msf.minute +
587 CDFRAMES_PERSEC * CDADev[wDevID].sc.cdsc_absaddr.msf.second +
588 CDADev[wDevID].sc.cdsc_absaddr.msf.frame;
589 #ifdef DEBUG_CDAUDIO
590 printf("CDAUDIO_GetCDStatus // %02u-%02u:%02u:%02u \n",
591 CDADev[wDevID].sc.cdsc_trk,
592 CDADev[wDevID].sc.cdsc_absaddr.msf.minute,
593 CDADev[wDevID].sc.cdsc_absaddr.msf.second,
594 CDADev[wDevID].sc.cdsc_absaddr.msf.frame);
595 #endif
596 if (oldmode != CDADev[wDevID].mode && oldmode == MCI_MODE_OPEN) {
597 if (!CDAUDIO_GetTracksInfo(wDevID)) {
598 printf("CDAUDIO_GetCDStatus // error updating TracksInfo !\n");
599 return MCIERR_INTERNAL;
602 return TRUE;
603 #else
604 return FALSE;
605 #endif
608 /**************************************************************************
609 * CDAUDIO_mciPlay [internal]
611 DWORD CDAUDIO_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
613 #ifdef linux
614 int start, end;
615 struct cdrom_msf msf;
616 #ifdef DEBUG_CDAUDIO
617 printf("CDAUDIO_mciPlay(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
618 #endif
619 if (lpParms == NULL) return MCIERR_INTERNAL;
620 if (CDADev[wDevID].unixdev == 0) return MMSYSERR_NOTENABLED;
621 start = 0; end = CDADev[wDevID].dwTotalLen;
622 CDADev[wDevID].nCurTrack = 1;
623 if (dwFlags & MCI_FROM) {
624 start = CDAUDIO_CalcFrame(wDevID,
625 CDADev[wDevID].dwTimeFormat, lpParms->dwFrom);
626 #ifdef DEBUG_CDAUDIO
627 printf("CDAUDIO_mciPlay // MCI_FROM=%08X -> %u \n",
628 lpParms->dwFrom, start);
629 #endif
631 if (dwFlags & MCI_TO) {
632 end = CDAUDIO_CalcFrame(wDevID,
633 CDADev[wDevID].dwTimeFormat, lpParms->dwTo);
634 #ifdef DEBUG_CDAUDIO
635 printf("CDAUDIO_mciPlay // MCI_TO=%08X -> %u \n",
636 lpParms->dwTo, end);
637 #endif
639 start += CDADev[wDevID].dwFirstOffset;
640 end += CDADev[wDevID].dwFirstOffset;
641 msf.cdmsf_min0 = start / CDFRAMES_PERMIN;
642 msf.cdmsf_sec0 = (start % CDFRAMES_PERMIN) / CDFRAMES_PERSEC;
643 msf.cdmsf_frame0 = start % CDFRAMES_PERSEC;
644 msf.cdmsf_min1 = end / CDFRAMES_PERMIN;
645 msf.cdmsf_sec1 = (end % CDFRAMES_PERMIN) / CDFRAMES_PERSEC;
646 msf.cdmsf_frame1 = end % CDFRAMES_PERSEC;
647 if (ioctl(CDADev[wDevID].unixdev, CDROMSTART)) {
648 printf("CDAUDIO_mciPlay // motor doesn't start !\n");
649 return MCIERR_HARDWARE;
651 if (ioctl(CDADev[wDevID].unixdev, CDROMPLAYMSF, &msf)) {
652 printf("CDAUDIO_mciPlay // device doesn't play !\n");
653 return MCIERR_HARDWARE;
655 #ifdef DEBUG_CDAUDIO
656 printf("CDAUDIO_mciPlay // msf = %d:%d:%d %d:%d:%d\n",
657 msf.cdmsf_min0, msf.cdmsf_sec0, msf.cdmsf_frame0,
658 msf.cdmsf_min1, msf.cdmsf_sec1, msf.cdmsf_frame1);
659 #endif
660 CDADev[wDevID].mode = MCI_MODE_PLAY;
661 if (dwFlags & MCI_NOTIFY) {
662 printf("CDAUDIO_mciPlay // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback);
663 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
664 CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
666 return 0;
667 #else
668 return MCIERR_HARDWARE;
669 #endif
672 /**************************************************************************
673 * CDAUDIO_mciStop [internal]
675 DWORD CDAUDIO_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
677 #ifdef linux
678 #ifdef DEBUG_CDAUDIO
679 printf("CDAUDIO_mciStop(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
680 #endif
681 if (lpParms == NULL) return MCIERR_INTERNAL;
682 if (ioctl(CDADev[wDevID].unixdev, CDROMSTOP)) return MCIERR_HARDWARE;
683 CDADev[wDevID].mode = MCI_MODE_STOP;
684 if (dwFlags & MCI_NOTIFY) {
685 printf("CDAUDIO_mciStop // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback);
686 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
687 CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
689 return 0;
690 #else
691 return MCIERR_HARDWARE;
692 #endif
695 /**************************************************************************
696 * CDAUDIO_mciPause [internal]
698 DWORD CDAUDIO_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
700 #ifdef linux
701 #ifdef DEBUG_CDAUDIO
702 printf("CDAUDIO_mciPause(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
703 #endif
704 if (lpParms == NULL) return MCIERR_INTERNAL;
705 if (ioctl(CDADev[wDevID].unixdev, CDROMPAUSE)) return MCIERR_HARDWARE;
706 CDADev[wDevID].mode = MCI_MODE_PAUSE;
707 if (dwFlags & MCI_NOTIFY) {
708 printf("CDAUDIO_mciPause // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback);
709 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
710 CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
712 return 0;
713 #else
714 return MCIERR_HARDWARE;
715 #endif
718 /**************************************************************************
719 * CDAUDIO_mciResume [internal]
721 DWORD CDAUDIO_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
723 #ifdef linux
724 #ifdef DEBUG_CDAUDIO
725 printf("CDAUDIO_mciResume(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
726 #endif
727 if (lpParms == NULL) return MCIERR_INTERNAL;
728 if (ioctl(CDADev[wDevID].unixdev, CDROMRESUME)) return MCIERR_HARDWARE;
729 CDADev[wDevID].mode = MCI_MODE_STOP;
730 if (dwFlags & MCI_NOTIFY) {
731 printf("CDAUDIO_mciResume // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback);
732 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
733 CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
735 return 0;
736 #else
737 return MCIERR_HARDWARE;
738 #endif
741 /**************************************************************************
742 * CDAUDIO_mciSeek [internal]
744 DWORD CDAUDIO_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
746 #ifdef linux
747 DWORD dwRet;
748 MCI_PLAY_PARMS PlayParms;
749 #ifdef DEBUG_CDAUDIO
750 printf("CDAUDIO_mciSeek(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
751 #endif
752 if (lpParms == NULL) return MCIERR_INTERNAL;
753 if (ioctl(CDADev[wDevID].unixdev, CDROMRESUME)) return MCIERR_HARDWARE;
754 CDADev[wDevID].mode = MCI_MODE_SEEK;
755 switch(dwFlags) {
756 case MCI_SEEK_TO_START:
757 PlayParms.dwFrom = 0;
758 break;
759 case MCI_SEEK_TO_END:
760 PlayParms.dwFrom = CDADev[wDevID].dwTotalLen;
761 break;
762 case MCI_TO:
763 PlayParms.dwFrom = lpParms->dwTo;
764 break;
766 dwRet = CDAUDIO_mciPlay(wDevID, MCI_WAIT | MCI_FROM, &PlayParms);
767 if (dwRet != 0) return dwRet;
768 dwRet = CDAUDIO_mciStop(wDevID, MCI_WAIT, (LPMCI_GENERIC_PARMS)&PlayParms);
769 if (dwFlags & MCI_NOTIFY) {
770 printf("CDAUDIO_mciSeek // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback);
771 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
772 CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
774 return dwRet;
775 #else
776 return MCIERR_HARDWARE;
777 #endif
781 /**************************************************************************
782 * CDAUDIO_mciSet [internal]
784 DWORD CDAUDIO_mciSet(UINT wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
786 #ifdef linux
787 #ifdef DEBUG_CDAUDIO
788 printf("CDAUDIO_mciSet(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
789 #endif
790 if (lpParms == NULL) return MCIERR_INTERNAL;
792 printf("CDAUDIO_mciSet // dwTimeFormat=%08X\n", lpParms->dwTimeFormat);
793 printf("CDAUDIO_mciSet // dwAudio=%08X\n", lpParms->dwAudio);
795 if (dwFlags & MCI_SET_TIME_FORMAT) {
796 switch (lpParms->dwTimeFormat) {
797 case MCI_FORMAT_MILLISECONDS:
798 #ifdef DEBUG_CDAUDIO
799 printf("CDAUDIO_mciSet // MCI_FORMAT_MILLISECONDS !\n");
800 #endif
801 break;
802 case MCI_FORMAT_MSF:
803 #ifdef DEBUG_CDAUDIO
804 printf("CDAUDIO_mciSet // MCI_FORMAT_MSF !\n");
805 #endif
806 break;
807 case MCI_FORMAT_TMSF:
808 #ifdef DEBUG_CDAUDIO
809 printf("CDAUDIO_mciSet // MCI_FORMAT_TMSF !\n");
810 #endif
811 break;
812 default:
813 printf("CDAUDIO_mciSet // bad time format !\n");
814 return MCIERR_BAD_TIME_FORMAT;
816 CDADev[wDevID].dwTimeFormat = lpParms->dwTimeFormat;
818 if (dwFlags & MCI_SET_DOOR_OPEN) {
819 printf("CDAUDIO_mciSet // MCI_SET_DOOR_OPEN !\n");
820 if (ioctl(CDADev[wDevID].unixdev, CDROMEJECT)) return MCIERR_HARDWARE;
821 CDADev[wDevID].nTracks = 0;
823 if (dwFlags & MCI_SET_DOOR_CLOSED) {
824 printf("CDAUDIO_mciSet // MCI_SET_DOOR_CLOSED !\n");
825 if (ioctl(CDADev[wDevID].unixdev, CDROMEJECT)) return MCIERR_HARDWARE;
826 CDADev[wDevID].nTracks = 0;
828 if (dwFlags & MCI_SET_VIDEO) return MCIERR_UNSUPPORTED_FUNCTION;
829 if (dwFlags & MCI_SET_ON) return MCIERR_UNSUPPORTED_FUNCTION;
830 if (dwFlags & MCI_SET_OFF) return MCIERR_UNSUPPORTED_FUNCTION;
831 if (dwFlags & MCI_NOTIFY) {
832 printf("CDAUDIO_mciSet // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback);
833 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
834 CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
836 return 0;
837 #else
838 return MCIERR_HARDWARE;
839 #endif
843 /**************************************************************************
844 * CDAUDIO_DriverProc [sample driver]
846 LRESULT CDAUDIO_DriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg,
847 DWORD dwParam1, DWORD dwParam2)
849 #ifdef linux
850 switch(wMsg) {
851 case DRV_LOAD:
852 return (LRESULT)1L;
853 case DRV_FREE:
854 return (LRESULT)1L;
855 case DRV_OPEN:
856 case MCI_OPEN_DRIVER:
857 case MCI_OPEN:
858 return CDAUDIO_mciOpen(dwParam1, (LPMCI_OPEN_PARMS)dwParam2);
859 case DRV_CLOSE:
860 case MCI_CLOSE_DRIVER:
861 case MCI_CLOSE:
862 return CDAUDIO_mciClose(dwDevID, dwParam1,
863 (LPMCI_GENERIC_PARMS)dwParam2);
864 case DRV_ENABLE:
865 return (LRESULT)1L;
866 case DRV_DISABLE:
867 return (LRESULT)1L;
868 case DRV_QUERYCONFIGURE:
869 return (LRESULT)1L;
870 case DRV_CONFIGURE:
871 MessageBox((HWND)NULL, "Sample MultiMedia Linux Driver !",
872 "MMLinux Driver", MB_OK);
873 return (LRESULT)1L;
874 case DRV_INSTALL:
875 return (LRESULT)DRVCNF_RESTART;
876 case DRV_REMOVE:
877 return (LRESULT)DRVCNF_RESTART;
878 case MCI_GETDEVCAPS:
879 return CDAUDIO_mciGetDevCaps(dwDevID, dwParam1,
880 (LPMCI_GETDEVCAPS_PARMS)dwParam2);
881 case MCI_INFO:
882 return CDAUDIO_mciInfo(dwDevID, dwParam1,
883 (LPMCI_INFO_PARMS)dwParam2);
884 case MCI_STATUS:
885 return CDAUDIO_mciStatus(dwDevID, dwParam1,
886 (LPMCI_STATUS_PARMS)dwParam2);
887 case MCI_SET:
888 return CDAUDIO_mciSet(dwDevID, dwParam1,
889 (LPMCI_SET_PARMS)dwParam2);
890 case MCI_PLAY:
891 return CDAUDIO_mciPlay(dwDevID, dwParam1,
892 (LPMCI_PLAY_PARMS)dwParam2);
893 case MCI_STOP:
894 return CDAUDIO_mciStop(dwDevID, dwParam1,
895 (LPMCI_GENERIC_PARMS)dwParam2);
896 case MCI_PAUSE:
897 return CDAUDIO_mciPause(dwDevID, dwParam1,
898 (LPMCI_GENERIC_PARMS)dwParam2);
899 case MCI_RESUME:
900 return CDAUDIO_mciResume(dwDevID, dwParam1,
901 (LPMCI_GENERIC_PARMS)dwParam2);
902 case MCI_SEEK:
903 return CDAUDIO_mciSeek(dwDevID, dwParam1,
904 (LPMCI_SEEK_PARMS)dwParam2);
905 case MCI_SET_DOOR_OPEN:
906 printf("CDAUDIO_DriverProc // MCI_SET_DOOR_OPEN !\n");
907 if (ioctl(CDADev[dwDevID].unixdev, CDROMEJECT)) return MCIERR_HARDWARE;
908 CDADev[dwDevID].nTracks = 0;
909 return 0;
910 case MCI_SET_DOOR_CLOSED:
911 printf("CDAUDIO_DriverProc // MCI_SET_DOOR_CLOSED !\n");
912 if (ioctl(CDADev[dwDevID].unixdev, CDROMEJECT, 1)) return MCIERR_HARDWARE;
913 CDADev[dwDevID].nTracks = 0;
914 return 0;
915 default:
916 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
918 #else
919 return MCIERR_HARDWARE;
920 #endif
924 /*-----------------------------------------------------------------------*/
926 #endif