]> icculus.org git repositories - btb/d2x.git/blob - unused/win95/rbaudio.c
Rename include/error.h to include/dxxerror.h
[btb/d2x.git] / unused / win95 / rbaudio.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14
15 #define _WIN32
16 #define WIN32_LEAN_AND_MEAN
17
18 #include <windows.h>
19 #include <mmsystem.h>
20
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include "winapp.h"
25 #include "mono.h"
26 #include "dxxerror.h"
27 #include "rbaudio.h"
28 #include "fix.h"
29 #include "winapp.h"
30
31
32 #define HSG_CD_PLAYBACK 0
33 #define MSF_CD_PLAYBACK 1
34
35
36 #pragma pack(1)
37
38 typedef struct CDTrack {
39         DWORD msf;
40         DWORD length;
41 } CDTrack;
42
43 int RBCDROM_State = 0;                                                  // CD is not used = 0
44                                                                                                                 // CD is used = 1
45                                                                                                                 // CD is already used = -1
46
47 static CDTrack  CDTrackInfo[255];
48 static UINT CDDiscID = 0;
49
50 static int              RedBookEnabled=0, RedBookInstalled = 0;
51 static UINT     CDDeviceID = 0;
52 static DWORD    CDNumTracks = 0;
53 static fix Playback_Start_Time = 0;
54 static fix Playback_Pause_Time = 0;
55 static fix Playback_Length = 0;
56 static int Playback_first_track,Playback_last_track;
57 static int AUXDevice = -1;
58 static char MCIErrorMsg[256];
59
60 //      Function Prototypes
61
62 unsigned long lsn_to_msf(unsigned long lsn);
63 unsigned long msf_to_lsn(unsigned long msf);
64 unsigned long msf_add(unsigned long msf1, unsigned long msf2);
65 unsigned long msf_sub(unsigned long msf1, unsigned long msf2);
66
67 UINT MakeCDDiscID(int tracks, unsigned long msflen, unsigned long msftrack1);
68 UINT GetCDDiscID();
69
70
71 //      Functions
72
73 void RBClose()
74 {
75         if (RedBookInstalled) {
76                 mciSendCommand(CDDeviceID, MCI_CLOSE, 0, NULL);
77                 RedBookEnabled = 0;
78                 RedBookInstalled = 0;
79         }
80 }
81
82
83 void RBAInit(void)
84 {
85         MCI_OPEN_PARMS  mciOpenParms;
86         MCI_SET_PARMS   mciSetParms;
87         DWORD                           retval = 0;
88         int                             num_devs, i;
89
90         atexit(RBClose);
91
92         num_devs = auxGetNumDevs();
93         
94 //      Find CD-AUDIO device if there is one.
95         for (i = 0; i < num_devs; i++)
96         {
97                 AUXCAPS caps;
98                 auxGetDevCaps(i, &caps, sizeof(caps));
99                 if (caps.wTechnology == AUXCAPS_CDAUDIO) {
100                         AUXDevice = i;
101                         mprintf((0, "CD operating on AUX %d.\n", AUXDevice));
102                         break;
103                 }
104         }
105                                         
106         if (AUXDevice == -1) {
107                 mprintf((1, "Unable to find CD-AUDIO device. No Redbook music.\n"));
108                 RedBookEnabled = 0;
109                 return;
110         }
111
112 //      We need to identify that a cd audio driver exists
113         mciOpenParms.lpstrDeviceType = "cdaudio";
114
115         retval = mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_SHAREABLE, (DWORD)(LPVOID)&mciOpenParms);
116         if (retval) {
117                 if (retval == MCIERR_MUST_USE_SHAREABLE) RBCDROM_State = -1;
118                 else RBCDROM_State = 0;
119                 mciGetErrorString(retval, MCIErrorMsg, 256);
120                 mprintf((1,"RBA (%x) MCI:%s.\n", retval, MCIErrorMsg));
121                 RedBookEnabled = 0;
122         }
123         else {
124         // Now we need to set the time format to MSF for Redbook Compatablity.
125                 RedBookInstalled = 1;
126                 RBCDROM_State = 1;
127                 CDDeviceID = mciOpenParms.wDeviceID;
128
129                 logentry("Initializing Redbook device %d.\n", CDDeviceID);
130
131                 mciSetParms.dwTimeFormat = MCI_FORMAT_MSF;
132                 retval = mciSendCommand(CDDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD)(LPVOID)&mciSetParms);
133                 if (retval) {
134                         mciSendCommand(CDDeviceID, MCI_CLOSE, 0, NULL);
135                         mprintf((0, "Error %d.  Unable to set Redbook Format.\n", retval));
136                         RedBookEnabled = 0;
137                 }
138                 else RedBookEnabled = 1;
139         }
140 }
141
142
143 void RBARegisterCD(void)
144 {
145         DWORD                                   i, numtracks, retval = 0;
146         MCI_STATUS_PARMS        mciStatusParms;
147
148 //      Insure that CD is Redbook, then get track information
149         mciStatusParms.dwItem = MCI_STATUS_NUMBER_OF_TRACKS; 
150         retval = mciSendCommand(CDDeviceID, MCI_STATUS, MCI_STATUS_ITEM, 
151                                                 (DWORD)(LPVOID)&mciStatusParms);
152         if (retval) {
153                 mciGetErrorString(retval, MCIErrorMsg, 256);
154                 mprintf((1,"RBA MCI:%s.\n", MCIErrorMsg));
155                 CDNumTracks = 0;
156                 return;
157         }
158         
159         CDNumTracks = numtracks = mciStatusParms.dwReturn;
160
161         for (i = 0; i < numtracks; i++)
162         {
163                 mciStatusParms.dwTrack = i+1;
164                 mciStatusParms.dwItem = MCI_STATUS_POSITION;
165                 retval = mciSendCommand(CDDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK, (DWORD)(LPVOID)&mciStatusParms);   
166                 if (retval) {
167                         mprintf((0, "Could not retrieve information on track %d.\n", i+1));
168                 }
169                 CDTrackInfo[i].msf = mciStatusParms.dwReturn;
170                 
171                 mciStatusParms.dwTrack = i+1;
172                 mciStatusParms.dwItem = MCI_STATUS_LENGTH;
173                 retval = mciSendCommand(CDDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK, (DWORD)(LPVOID)&mciStatusParms);
174                 if (retval) { 
175                         mprintf((0, "Couldn't get length of track %d.\n", i+1));
176                 }
177                 CDTrackInfo[i].length = mciStatusParms.dwReturn;
178
179 //              logentry("[%d] (%d:%d):(%d:%d)\n", i+1, MCI_MSF_MINUTE(CDTrackInfo[i].msf), MCI_MSF_SECOND(CDTrackInfo[i].msf), MCI_MSF_MINUTE(CDTrackInfo[i].length), MCI_MSF_SECOND(CDTrackInfo[i].length));
180         }       
181
182         CDDiscID = GetCDDiscID();
183
184
185
186 long RBAGetDeviceStatus()
187 {
188         return 0;
189 }
190
191
192 int get_track_time(int first,int last)
193 {
194         unsigned long playlen;
195         int min, sec;
196
197         playlen = msf_sub(msf_add(CDTrackInfo[last-1].msf,CDTrackInfo[last-1].length), CDTrackInfo[first-1].msf);
198
199         min   = MCI_MSF_MINUTE(playlen);
200         sec   = MCI_MSF_SECOND(playlen);
201
202         return (min*60+sec);
203 }
204
205
206 int RBAPlayTrack(int track)
207 {
208         MCI_PLAY_PARMS  mciPlayParms;
209         int min=0; 
210         int retval;
211
212 //      Register CD if media has changed
213         if (!RedBookEnabled) return 0;
214         if (RBACheckMediaChange()) {
215                 mprintf((0, "Unable to play track due to CD change.\n"));
216                 return 0;
217         }
218
219 //      Play the track
220         min = min + MCI_MSF_MINUTE(CDTrackInfo[track-1].msf) + MCI_MSF_MINUTE(CDTrackInfo[track-1].length);
221         mciPlayParms.dwFrom = CDTrackInfo[track-1].msf; // MCI_MAKE_TMSF(track, 0, 0, 0);
222         mciPlayParms.dwTo = msf_add(CDTrackInfo[track-1].msf, CDTrackInfo[track-1].length);
223         retval = mciSendCommand(CDDeviceID, MCI_PLAY, MCI_FROM | MCI_TO, (DWORD)(LPVOID)&mciPlayParms);
224
225         if (retval) {
226                 mciGetErrorString(retval, MCIErrorMsg, 256);
227                 mprintf((1,"RBA MCI:%s.\n", MCIErrorMsg));
228                 mprintf((0, "Unable to play CD track %d.\n", track));
229                 return 0;
230         }
231         else {
232                 Playback_Length = i2f(get_track_time(track,track));
233                 Playback_Start_Time = timer_get_fixed_seconds();
234
235                 Playback_first_track = Playback_last_track = track;
236
237                 mprintf( (0,"Playing Track %d (len: %d secs)\n", track, f2i(Playback_Length)) );
238         }
239
240         return 1;
241 }
242
243
244 int RBAPlayTracks(int start, int end)
245 {
246         MCI_PLAY_PARMS  mciPlayParms;
247         int retval;
248
249         Playback_Start_Time = 0;
250         Playback_Length = 0;
251
252 //      Register CD if media has changed
253         if (!RedBookEnabled) return 0;
254         if (RBACheckMediaChange()) {
255                 mprintf((0, "Unable to play track due to CD change.\n"));
256                 return 0;
257         }
258
259 //      Play the track
260         mciPlayParms.dwFrom = CDTrackInfo[start-1].msf; // MCI_MAKE_TMSF(track, 0, 0, 0);
261         mciPlayParms.dwTo = msf_add(CDTrackInfo[end-1].msf, CDTrackInfo[end-1].length);
262         retval = mciSendCommand(CDDeviceID, MCI_PLAY, MCI_FROM | MCI_TO, (DWORD)(LPVOID)&mciPlayParms);
263
264         if (retval) {
265                 mciGetErrorString(retval, MCIErrorMsg, 256);
266                 mprintf((1,"RBA MCI:%s.\n", MCIErrorMsg));
267                 mprintf((0, "Unable to play CD tracks %d-%d.\n", start,end));
268                 return 0;               
269         }
270         else {
271                 Playback_Length = i2f(get_track_time(start,end));
272                 Playback_Start_Time = timer_get_fixed_seconds();
273
274                 Playback_first_track = start;
275                 Playback_last_track = end;
276
277                 mprintf( (0,"Playing Tracks %d-%d (len: %d secs)\n", start,end,f2i(Playback_Length)) );
278         }
279
280         return 1;
281 }
282
283
284 void RBAStop()
285 {
286         int retval;
287
288         if (!RedBookEnabled) return;
289         
290         retval = mciSendCommand(CDDeviceID, MCI_STOP,0,NULL);
291         if (retval) {
292                 mciGetErrorString(retval, MCIErrorMsg, 256);
293                 mprintf((1,"RBA MCI:%s.\n", MCIErrorMsg));
294                 mprintf((0, "CD Stop command failed.\n"));
295         } 
296 }
297
298
299 void RBASetStereoAudio(RBACHANNELCTL *channels)
300 {
301
302 }
303
304
305 void RBASetQuadAudio(RBACHANNELCTL *channels)
306 {
307
308 }
309
310
311 void RBAGetAudioInfo(RBACHANNELCTL *channels)
312 {
313
314 }
315
316
317 static unsigned rba_paused_head_loc = 0;
318
319 void RBAPause()
320 {
321         int retval;
322         MCI_GENERIC_PARMS mciGenParms;
323         int frame, sec, min;
324
325
326   if (!RedBookEnabled) return;
327
328         rba_paused_head_loc = RBAGetHeadLoc(&min, &sec, &frame);        
329
330         mciGenParms.dwCallback = GetLibraryWindow();
331         retval = mciSendCommand(CDDeviceID, MCI_PAUSE, MCI_NOTIFY, 
332                 (DWORD)(LPVOID)&mciGenParms);
333         if (retval)     {
334                 mprintf((1,"ERROR: Unable to pause CD.\n"));
335         }
336         else {
337                 mprintf((0, "Pausing CD...\n"));
338                 Playback_Pause_Time = timer_get_fixed_seconds();
339         }
340
341 }
342
343
344 int RBAResume()
345 {
346         int retval;
347         MCI_PLAY_PARMS mciPlayParms;
348
349         if (!RedBookEnabled) return 0;
350    
351         if (RBACheckMediaChange()) {
352                 RBARegisterCD();
353                 return RBA_MEDIA_CHANGED;
354         }
355
356         mciPlayParms.dwFrom = rba_paused_head_loc; // MCI_MAKE_TMSF(track, 0, 0, 0);
357         mciPlayParms.dwTo = msf_add(CDTrackInfo[Playback_last_track-1].msf, 
358                                                                         CDTrackInfo[Playback_last_track-1].length);
359         retval = mciSendCommand(CDDeviceID, MCI_PLAY, MCI_FROM | MCI_TO, (DWORD)(LPVOID)&mciPlayParms);
360
361         if (retval) {
362                 mprintf((1, "ERROR: Resume CD play failed.\n"));
363         }
364         else 
365                 Playback_Start_Time += timer_get_fixed_seconds() - Playback_Pause_Time;
366
367         return 1;
368 }
369
370
371 void RBASetChannelVolume(int channel, int volume) 
372 {
373         DWORD vol;
374         
375         volume = volume << 8;
376         
377         if (channel == 0) 
378                 vol = MAKELONG(0,volume);
379         else if (channel == 1) 
380                 vol = MAKELONG(volume,0);
381
382         auxSetVolume(AUXDevice, vol);
383 }
384
385
386 void RBASetVolume(int volume)
387 {
388         DWORD vol;
389         WORD wvol;
390
391         wvol = (WORD)(volume) << 8;
392
393         vol = MAKELONG(wvol, wvol);
394         auxSetVolume(AUXDevice, vol);
395 }
396
397
398 long RBAGetHeadLoc(int *min, int *sec, int *frame)
399 {
400         MCI_STATUS_PARMS mciStatusParms;
401         int retval;
402
403         if (!RedBookEnabled) return 0;
404
405         if (RBACheckMediaChange())
406                 return RBA_MEDIA_CHANGED;
407
408         mciStatusParms.dwItem = MCI_STATUS_POSITION;
409         retval = mciSendCommand(CDDeviceID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD)(LPVOID)&mciStatusParms);
410         
411         if (retval) {
412                 mprintf((0, "Couldn't get location of CD head.\n"));
413         }
414
415         *min = MCI_MSF_MINUTE(mciStatusParms.dwReturn);
416         *sec = MCI_MSF_SECOND(mciStatusParms.dwReturn);
417         *frame = MCI_MSF_FRAME(mciStatusParms.dwReturn);
418
419         return mciStatusParms.dwReturn;
420 }               
421
422
423 int RBAGetTrackNum()
424 {
425         int track;
426         int delta_time; //in seconds
427
428         if (!RBAPeekPlayStatus())
429                 return 0;
430
431         delta_time = f2i(timer_get_fixed_seconds()-Playback_Start_Time+f1_0/2);
432
433         for (track=Playback_first_track;track<=Playback_last_track && delta_time>0;track++) {
434
435                 delta_time -= get_track_time(track,track);
436
437                 if (delta_time < 0)
438                         break;
439         }
440
441         Assert(track <= Playback_last_track);
442
443         return track;
444 }
445
446
447 int RBAPeekPlayStatus()
448 {
449 //@@    MCI_STATUS_PARMS mciStatusParms;
450 //@@    int retval;
451
452         if (!RedBookEnabled) return 0;
453
454
455         if ((timer_get_fixed_seconds()-Playback_Start_Time) > Playback_Length) return 0;
456         else return 1; 
457
458
459 //@@    mciStatusParms.dwItem = MCI_STATUS_MODE;
460 //@@    retval = mciSendCommand(CDDeviceID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD)(LPVOID)&mciStatusParms);
461 //@@    if (retval) {
462 //@@            mprintf((0, "Unable to obtain current status of CD.\n"));
463 //@@    }
464 //@@    
465 //@@    if (mciStatusParms.dwReturn == MCI_MODE_PLAY) return 1;
466 //@@    else return 0;
467 }
468         
469
470
471 int RBAEnabled()
472 {
473         if (RedBookEnabled < 1) return 0;
474         else return 1;
475 }
476
477
478 void RBAEnable()
479 {
480         RedBookEnabled = 1;
481         mprintf((0, "Enabling Redbook...\n"));
482 }
483
484
485 void RBADisable()
486 {
487         RedBookEnabled = 0;
488         mprintf((0, "Disabling Redbook...\n"));
489 }
490
491
492 int RBAGetNumberOfTracks(void)
493 {
494         MCI_STATUS_PARMS        mciStatusParms;
495         int retval;     
496
497         if (!RedBookEnabled) return 0;
498
499         if (RBACheckMediaChange())  
500                 RBARegisterCD();
501                 
502         mciStatusParms.dwItem = MCI_STATUS_NUMBER_OF_TRACKS; 
503         retval = mciSendCommand(CDDeviceID, MCI_STATUS, MCI_STATUS_ITEM, 
504                                                 (DWORD)(LPVOID)&mciStatusParms);
505
506         if (retval) {
507                 mprintf((0, "Get number of CD tracks failed.\n"));
508                 return 0;
509         }
510
511         return mciStatusParms.dwReturn;
512 }
513
514
515 //      RB functions:  Internal to RBA library  -----------------------------
516
517 int RBACheckMediaChange()
518 {
519         if (!RedBookEnabled) return 0;
520
521         if (CDDiscID != GetCDDiscID() || !CDDiscID) return 1;
522         else return 0;
523 }
524
525
526 //      Converts Logical Sector Number to Minutes Seconds Frame Format
527
528 unsigned long lsn_to_msf(unsigned long lsn)
529 {
530    unsigned long min,sec,frame;
531    lsn += 150;
532
533         min   =  lsn / (60*75);
534    lsn   =  lsn % (60*75);
535         sec   =  lsn / 75;
536    lsn   =  lsn % 75;
537         frame =  lsn;
538
539         return((min << 16) + (sec << 8) + (frame << 0));
540 }
541
542 // convert minutes seconds frame format to a logical sector number.
543
544 unsigned long msf_to_lsn(unsigned long msf)
545 {
546         unsigned long min,sec,frame;
547
548         min   = (msf >> 16) & 0xFF;
549    sec   = (msf >>  8) & 0xFF;
550    frame = (msf >>  0) & 0xFF;
551
552         return(  (min * 60*75) + (sec * 75) + frame - 150  );
553 }
554
555 unsigned long msf_add(unsigned long msf1, unsigned long msf2)
556 {
557         uint min1, sec1, frame1;
558         uint min2, sec2, frame2;
559
560 //      we don't take frames into account, which may not be right.
561         min1 = MCI_MSF_MINUTE(msf1);
562         sec1 = MCI_MSF_SECOND(msf1);
563         frame1 = MCI_MSF_FRAME(msf1);
564
565         frame2 = 0;
566         min2 = 0;
567
568         if ((sec1 + MCI_MSF_SECOND(msf2)) > 59) {
569                 sec2 = (sec1+MCI_MSF_SECOND(msf2)) - 60;
570                 min1++;
571         }
572         else sec2 = sec1 + MCI_MSF_SECOND(msf2);
573         min2 = min1+MCI_MSF_MINUTE(msf2);
574         frame2 = 0;
575         
576 //      logentry("msf_add:(%d:%d)\n", min2, sec2);
577
578         return MCI_MAKE_MSF(min2, sec2, 0);
579
580
581
582 unsigned long msf_sub(unsigned long msf1, unsigned long msf2)
583 {
584         int min1, sec1, frame1;
585         int min2, sec2, frame2;
586
587 //      we don't take frames into account, which may not be right.
588         min1 = MCI_MSF_MINUTE(msf1);
589         sec1 = MCI_MSF_SECOND(msf1);
590         frame1 = MCI_MSF_FRAME(msf1);
591
592         frame2 = 0;
593         min2 = 0;
594
595         if ((sec1 - (int)MCI_MSF_SECOND(msf2)) < 0) {
596                 sec2 = 60 - ((int)MCI_MSF_SECOND(msf2)-sec1);
597                 min1--;                                 // This is a shortcut to min2 = min1-(MSF_MIN(msf2)-1)
598         }
599         else sec2 = sec1 - (int)MCI_MSF_SECOND(msf2);
600         min2 = min1-(int)MCI_MSF_MINUTE(msf2);
601         frame2 = 0;
602
603 //      logentry("msf_sub:(%d:%d)\n", min2, sec2);
604         
605         return MCI_MAKE_MSF(min2, sec2, 0);
606
607
608
609 unsigned long msf_to_sec(unsigned long msf)
610 {
611         unsigned long min,sec,frame;
612
613         min   = (msf >> 16) & 0xFF;
614    sec   = (msf >>  8) & 0xFF;
615    frame = (msf >>  0) & 0xFF;
616
617         return (min*60) + sec;  
618 }
619
620
621 UINT GetCDDiscID()
622 {
623         MCI_STATUS_PARMS        mciStatusParms;
624         int retval;     
625         unsigned long msflen, tracks, msftrack1;
626
627         mciStatusParms.dwItem = MCI_STATUS_NUMBER_OF_TRACKS; 
628         if (retval = mciSendCommand(CDDeviceID, MCI_STATUS, MCI_STATUS_ITEM, 
629                                                 (DWORD)(LPVOID)&mciStatusParms)) {
630                 mprintf((1, "RBA: Get number of CD tracks failed.\n"));
631                 return 0;
632         }
633         tracks = mciStatusParms.dwReturn;
634
635         mciStatusParms.dwItem = MCI_STATUS_LENGTH;
636         if (retval = mciSendCommand(CDDeviceID, MCI_STATUS, MCI_STATUS_ITEM, 
637                                                 (DWORD)(LPVOID)&mciStatusParms)) {
638                 mprintf((1,     "RBA: Get media length failed.\n"));
639                 return 0;
640         }
641         msflen = mciStatusParms.dwReturn;
642
643         mciStatusParms.dwTrack = 1;
644         mciStatusParms.dwItem = MCI_STATUS_POSITION;
645         if (retval = mciSendCommand(CDDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK, (DWORD)(LPVOID)&mciStatusParms)) {     
646                 mprintf((1, "Could not retrieve information on track %d.\n", 1));
647                 return 0;
648         }
649         msftrack1 = mciStatusParms.dwReturn;
650
651         return MakeCDDiscID(tracks, msflen, msftrack1);
652 }
653
654
655 UINT MakeCDDiscID(int tracks, unsigned long msflen, unsigned long msftrack1)
656 {
657         UINT code=0;
658         
659         code = (UINT)(msf_to_sec(msftrack1) << 19);
660         code |= (UINT)(msf_to_sec(msflen) << 6);
661
662         code |= (UINT)(tracks&0xffffffc0);
663
664         return code;
665 }
666         
667
668