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