// This is the source to Dido 4. // // Lossless digital sound copy from AUDIO CD to WAV files, without crackle & // pops. No sampling involved. The best quality you can get. // // Windows 3.1 freeware by // Michiel Overtoom (motoom@xs4all.nl) // Bases on work done by // Yeng-Chee Su (yenchee@csie.nctu.edu.tw) // and // Klaas Hemstra (hst@mh.nl) // // and of course... source available. #include #include #include #include #include #include #include #include #include #include // for mciSendstring #include "dido.h" // defines for program resources #define HELPFILE "dido.hlp" HINSTANCE hinst; WORD nbuf; // number of low memory dos buffers (set by allocating routine) #define MAXNBUF 20 // Max. number of low mem buffers that can be allocated int CDROM; // CDROM unit. 0==a, 1==b, etc int lowest, highest; // Lowest and highest track on the CD int lineinc=4,pageinc=12; // skipping factors for scrollbar (in seconds) DWORD total_time; // Total time on CD char s[160],t[80],u[80]; // scratch strings char waveditor[160]="MPLAYER.EXE"; // editor for WAV files (INI setting) BOOL bit16=1,hz44=1,stereo=1; // settings from recording dialog; options for // thinning out the recorded sound. #define mb(x) MessageBox(0,x,"Error",0); #include "didod.h" // low level cd defines/structs #include "didod.c" // low level cd routines via DPMI #include "didologo.c" // logo routines // Set all the controls in a Dialog to the same font BOOL CALLBACK EnumDialogChild(HWND hw,LPARAM font) { SendMessage(hw,WM_SETFONT,(WPARAM)font,0); return 1; } void SetDialogFont(HWND dialog,HFONT font) { EnumChildWindows(dialog,EnumDialogChild,(LPARAM)font); } // Center a window void CenterWindow(HWND hwnd) { RECT r; GetWindowRect(hwnd, &r); SetWindowPos(hwnd, NULL, ((GetSystemMetrics(SM_CXSCREEN) - (r.right - r.left)) / 2), ((GetSystemMetrics(SM_CYSCREEN) - (r.bottom - r.top)) / 2), 0, 0, SWP_NOSIZE | SWP_NOACTIVATE); } #include "didorec.c" // recording routine // Delay routine, used in initialization void delay(long ticks) { long expire=clock()+ticks; while(clock()val); SetDlgItemText(hdlg,VALUE,s); } if (msg==WM_COMMAND && wp==IDOK) { GetDlgItemText(hdlg,VALUE,s,19); value->val=atol(s); if (value->val < value->from) value->val=value->from; else if (value->val > value->to) value->val=value->to; EndDialog(hdlg,1); } return 0; } // Wrapper for get-a-value dialog. Provides default, ranges, etc... DWORD GetValue(HWND caller,DWORD defalt,DWORD from,DWORD to) { struct values value; value.from=from; value.to=to; value.val=defalt; DialogBoxParam(hinst,"ValueDlg",caller,ValueDlgProc,(LPARAM)&value); return value.val; } // Record dialog #pragma argsused BOOL CALLBACK RecDlgProc(HWND hdlg, UINT msg, WPARAM wp, LPARAM lp) { static int restartsound=0,autorewind=1,autorepeat=1; static int refresh=0; static int tnr; // track number static DWORD start,end; // Start/ending recording position, redbook format static WORD sm,ss,sf; // Start recording position: minute, second, frame static WORD em,es,ef; // idem, End position static DWORD sc,ec; // Start/ending recording sectors static char fn[80]; // Last used filename DWORD dur; WORD div; if (msg==WM_INITDIALOG) { // Initialize record dialog fn[0]=0; // Zap filename tnr=(WORD)lp; // Remember track number sprintf(s,"Search (track %d)",tracknr[tnr]); // put it also in the SetWindowText(hdlg,s); // dialog title CenterWindow(hdlg); SetDialogFont(hdlg,GetStockObject(ANSI_VAR_FONT)); // Fill inputs with track defaults Red2MSFC(start=trackloc[tnr],&sm,&ss,&sf,&sc); Red2MSFC(end=trackloc[tnr+1],&em,&es,&ef,&ec); // Set scroll bar extents en posities SetScrollRange(GetDlgItem(hdlg,SBAR),SB_CTL,0,Red2Sierra(total_time)/75L,0); SetScrollRange(GetDlgItem(hdlg,EBAR),SB_CTL,0,Red2Sierra(total_time)/75L,0); SetScrollPos(GetDlgItem(hdlg,SBAR),SB_CTL,Red2Sierra(start)/75L,0); SetScrollPos(GetDlgItem(hdlg,EBAR),SB_CTL,Red2Sierra(end)/75L,0); // Assure all fields will be refreshed; also start playing the track refresh=1; restartsound=1; } // Button pressed! #define FRESH refresh=1; if (autorewind) restartsound=1 if (msg==WM_COMMAND) { if (wp==LISTEN) restartsound=1; if (wp==IDOK) {StopAudio(); EndDialog(hdlg,1);} if (wp==STEREO) {stereo=1; refresh=1;} if (wp==MONO) {stereo=0; refresh=1;} if (wp==HZ44) {hz44=1; refresh=1;} if (wp==HZ22) {hz44=0; refresh=1;} if (wp==BIT16) {bit16=1; refresh=1;} if (wp==BIT8) {bit16=0; refresh=1;} if (wp==RECORD) { StopAudio(); PlayAudio(start,10); // This prevents sync errors (? beats me but it does!) EnableWindow(hdlg,0); sprintf(fn,"%d-%d-%d.wav",sm,ss,sf); // Compose a filename using start time if (ChooseWavFile(hdlg,fn)) { // File selection box dur=Red2Sierra(end)-Red2Sierra(start); if (!record(fn,Red2Sierra(start),dur)) mb(error); // record it. FRESH; } EnableWindow(hdlg,1); SetFocus(hdlg); } if (wp==EDIT) { if (access(fn,0)==0) { // Edit only allowed when last used sprintf(s,"%s %s",waveditor,fn); // is present, and if the file exist. StopAudio(); if (WinExec(s,SW_SHOWNORMAL)<32) // Spawn the WAV editor MessageBox(hdlg,s,"cant execute editor",MB_OK); } } if (wp==AUTOREWIND) {autorewind=1-autorewind; refresh=1;} if (wp==AUTOREPEAT) {autorepeat=1-autorepeat; refresh=1;} // Adjusting start time... if (wp==SM) { sm=GetValue(hdlg,sm,0,99); MSF2Red(sm,ss,sf,&start,&sc); FRESH; } if (wp==SMDOWN) { if (sm) sm--; MSF2Red(sm,ss,sf,&start,&sc); FRESH; } if (wp==SMUP) { sm++; MSF2Red(sm,ss,sf,&start,&sc); FRESH; } if (wp==SS) { ss=GetValue(hdlg,ss,0,59); MSF2Red(sm,ss,sf,&start,&sc); FRESH; } if (wp==SSDOWN) { if (ss) ss--; else if (sm) {sm--; ss=59;} MSF2Red(sm,ss,sf,&start,&sc); FRESH; } if (wp==SSUP) { ss++; if (ss>59) {ss=0; sm++;} MSF2Red(sm,ss,sf,&start,&sc); FRESH; } if (wp==SF) { sf=GetValue(hdlg,sf,0,74); MSF2Red(sm,ss,sf,&start,&sc); FRESH; } if ((wp==SFDOWN)||(wp==SCDOWN)) { if (sf) { sf--; } else if (ss) { ss--; sf=74; } else if (sm) { sm--; ss=59; sf=74; } MSF2Red(sm,ss,sf,&start,&sc); FRESH; } if ((wp==SFUP)||(wp==SCUP)) { sf++; if (sf>74) { sf=0; ss++; if (ss>59) { sm++; ss=0; } } MSF2Red(sm,ss,sf,&start,&sc); FRESH; } // Adjusting end time... if (wp==EM) { em=GetValue(hdlg,em,0,99); MSF2Red(em,es,ef,&end,&ec); FRESH; } if (wp==EMDOWN) { if (em) em--; MSF2Red(em,es,ef,&end,&ec); FRESH; } if (wp==EMUP) { em++; MSF2Red(em,es,ef,&end,&ec); FRESH; } if (wp==ES) { es=GetValue(hdlg,es,0,59); MSF2Red(em,es,ef,&end,&ec); FRESH; } if (wp==ESDOWN) { if (es) es--; else if (em) {em--; es=59;} MSF2Red(em,es,ef,&end,&ec); FRESH; } if (wp==ESUP) { es++; if (es>59) {es=0; em++;} MSF2Red(em,es,ef,&end,&ec); FRESH; } if (wp==EF) { ef=GetValue(hdlg,ef,0,74); MSF2Red(em,es,ef,&end,&ec); FRESH; } if ((wp==EFDOWN)||(wp==ECDOWN)) { if (ef) { ef--; } else if (es) { es--; ef=74; } else if (em) { em--; es=59; ef=74; } MSF2Red(em,es,ef,&end,&ec); FRESH; } if ((wp==EFUP)||(wp==ECUP)) { ef++; if (ef>74) { ef=0; es++; if (es>59) { em++; es=0; } } MSF2Red(em,es,ef,&end,&ec); FRESH; } } // Scroll bar? if (msg==WM_HSCROLL) { // SBAR, EBAR BOOL isstart=0; int sc=wp; // Scrollcode int pos=LOWORD(lp); // position if (GetDlgItem(hdlg,SBAR)==(HWND)HIWORD(lp)) isstart=1; if (sc==SB_THUMBPOSITION || sc==SB_THUMBTRACK) { if (isstart) Red2MSFC(start=Sierra2Red(75L*pos),&sm,&ss,&sf,&sc); else Red2MSFC(end=Sierra2Red(75L*pos),&em,&es,&ef,&ec); FRESH; } if (sc==SB_LINEUP) { if (isstart) { long newstart=Red2Sierra(start)-75L*lineinc; if (newstart<0) newstart=0; Red2MSFC(start=Sierra2Red(newstart),&sm,&ss,&sf,&sc); } else { long newend=Red2Sierra(end)-75L*lineinc; if (newend<0) newend=0; Red2MSFC(end=Sierra2Red(newend),&em,&es,&ef,&ec); } FRESH; } if (sc==SB_LINEDOWN) { if (isstart) { long newstart=Red2Sierra(start)+75L*lineinc; Red2MSFC(start=Sierra2Red(newstart),&sm,&ss,&sf,&sc); } else { long newend=Red2Sierra(end)+75L*lineinc; Red2MSFC(end=Sierra2Red(newend),&em,&es,&ef,&ec); } FRESH; } if (sc==SB_PAGEUP) { if (isstart) { long newstart=Red2Sierra(start)-75L*pageinc; if (newstart<0) newstart=0; Red2MSFC(start=Sierra2Red(newstart),&sm,&ss,&sf,&sc); } else { long newend=Red2Sierra(end)-75L*pageinc; if (newend<0) newend=0; Red2MSFC(end=Sierra2Red(newend),&em,&es,&ef,&ec); } FRESH; } if (sc==SB_PAGEDOWN) { if (isstart) { long newstart=Red2Sierra(start)+75L*pageinc; Red2MSFC(start=Sierra2Red(newstart),&sm,&ss,&sf,&sc); } else { long newend=Red2Sierra(end)+75L*pageinc; Red2MSFC(end=Sierra2Red(newend),&em,&es,&ef,&ec); } FRESH; } } // Something needs redrawing? Well, redraw them all. if (refresh) { refresh=0; // Never play outside CD tracks - may hang the driver if (starttrackloc[ntrack]) Red2MSFC(start=trackloc[ntrack],&sm,&ss,&sf,&sc); if (endtrackloc[ntrack]) Red2MSFC(end=trackloc[ntrack],&em,&es,&ef,&ec); if (start>end) Red2MSFC(end=start,&em,&es,&ef,&ec); // Update the numerals in the edit controls Red2MSFC(start,&sm,&ss,&sf,&sc); Red2MSFC(end,&em,&es,&ef,&ec); SetDlgItemInt(hdlg,SM,sm,0); SetDlgItemInt(hdlg,SS,ss,0); SetDlgItemInt(hdlg,SF,sf,0); sprintf(s,"%lu",sc); SetDlgItemText(hdlg,SC,s); SetDlgItemInt(hdlg,EM,em,0); SetDlgItemInt(hdlg,ES,es,0); SetDlgItemInt(hdlg,EF,ef,0); sprintf(s,"%lu",ec); SetDlgItemText(hdlg,EC,s); // Update scroll bars SetScrollPos(GetDlgItem(hdlg,SBAR),SB_CTL,Red2Sierra(start)/75L,1); SetScrollPos(GetDlgItem(hdlg,EBAR),SB_CTL,Red2Sierra(end)/75L,1); // Set radiobuttons if (!bit16) { hz44=0; stereo=0; EnableWindow(GetDlgItem(hdlg,HZ22),0); EnableWindow(GetDlgItem(hdlg,HZ44),0); EnableWindow(GetDlgItem(hdlg,MONO),0); EnableWindow(GetDlgItem(hdlg,STEREO),0); } else { EnableWindow(GetDlgItem(hdlg,HZ22),1); EnableWindow(GetDlgItem(hdlg,HZ44),1); EnableWindow(GetDlgItem(hdlg,MONO),1); EnableWindow(GetDlgItem(hdlg,STEREO),1); } CheckRadioButton(hdlg,MONO,STEREO,stereo?STEREO:MONO); CheckRadioButton(hdlg,HZ22,HZ44,hz44?HZ44:HZ22); CheckRadioButton(hdlg,BIT8,BIT16,bit16?BIT16:BIT8); CheckDlgButton(hdlg,AUTOREWIND,autorewind); CheckDlgButton(hdlg,AUTOREPEAT,autorepeat); if (*fn && access(fn,0)==0) EnableWindow(GetDlgItem(hdlg,EDIT),1); else EnableWindow(GetDlgItem(hdlg,EDIT),0); // Calculate projected file size and duration dur=Red2Sierra(end)-Red2Sierra(start); div=0; if (!stereo) div++; if (!hz44) div++; if (!bit16) div++; sprintf(s,"%ld Kbytes",((dur*2352)>>div)/1024); SetDlgItemText(hdlg,FSIZE,s); sprintf(s,"%s / %ld sectors",Sector2MSF(dur),dur); SetDlgItemText(hdlg,DUR,s); } // Issue a play command to the CD player if (restartsound) { restartsound=0; StopAudio(); PlayAudio(start,Red2Sierra(end)-Red2Sierra(start)); } return 0; } // Preferences dialog proc #pragma argsused BOOL CALLBACK PrefDlgProc(HWND hdlg, UINT msg, WPARAM wp, LPARAM lp) { if (msg==WM_INITDIALOG) { SetDialogFont(hdlg,GetStockObject(ANSI_VAR_FONT)); sprintf(s,"%d audio buffers allocated",nbuf); SetDlgItemText(hdlg,BUFRESULT,s); if (CheckSmartdrv()) { if (CheckCDROMCached()) strcpy(s,"Smartdrv caches the CDROM"); else strcpy(s,"Smartdrv does not cache the CDROM"); } else strcpy(s,"Smartdrv not installed"); SetDlgItemText(hdlg,CACHERESULT,s); SetDlgItemText(hdlg,WAVEDITOR,waveditor); } if (msg==WM_COMMAND && wp==IDOK) { GetDlgItemText(hdlg,WAVEDITOR,waveditor,159); WriteProfileString("Dido","WAVeditor",waveditor); EndDialog(hdlg,1); } return 0; } // Sync error dialog proc #pragma argsused BOOL CALLBACK SyncErrDlgProc(HWND hdlg, UINT msg, WPARAM wp, LPARAM lp) { if (msg==WM_INITDIALOG) SetDialogFont(hdlg,GetStockObject(ANSI_VAR_FONT)); if (msg==WM_COMMAND) { if (wp==ABOUT) { WinHelp(hdlg,HELPFILE,HELP_KEY,"SyncErr"); EndDialog(hdlg,1); } if (wp==IDCANCEL) { EndDialog(hdlg,1); } } return 0; } // Memalloc error dialog proc #pragma argsused BOOL CALLBACK MemErrDlgProc(HWND hdlg, UINT msg, WPARAM wp, LPARAM lp) { if (msg==WM_INITDIALOG) SetDialogFont(hdlg,GetStockObject(ANSI_VAR_FONT)); if (msg==WM_COMMAND) { if (wp==ABOUT) { WinHelp(hdlg,HELPFILE,HELP_KEY,"MemErr"); EndDialog(hdlg,1); } if (wp==IDCANCEL) { EndDialog(hdlg,1); } } return 0; } // Main dialog proc #pragma argsused BOOL CALLBACK MainDlgProc(HWND hdlg, UINT msg, WPARAM wp, LPARAM lp) { int i; if (msg==WM_INITDIALOG) { SetDialogFont(hdlg,GetStockObject(ANSI_VAR_FONT)); // Infoheaderts at top SetDlgItemText(hdlg,PLAYINGTIME,Sector2MSF(Red2Sierra(total_time))); sprintf(s,"%d",highest-lowest+1); SetDlgItemText(hdlg,NRTRACKS,s); // Track table if (!BuildTrackTable()) mb("Error building the track table"); SendDlgItemMessage(hdlg,TRACKLIST,LB_RESETCONTENT,0,0); for (i=0;i=3) { if (MessageBox(0,"Insert an audio CD in the drive","CDROM is busy",MB_RETRYCANCEL)==IDCANCEL) { // ieks... terminate stopinterfacing(); return 0; } try=0; } status=GetDiskInfo(); } // Do the interaction GetProfileString("Dido","WAVeditor",waveditor,waveditor,159); result=DialogBox(hinst,"MainDlg",0,MainDlgProc); if (result==EJECT) { // Try MCI, for a change mciSendString("SET CDAUDIO DOOR OPEN", NULL, 0, NULL ); // This one works OK on my drive... MessageBox(0,"You can change the CD now","Dido",MB_OK); mciSendString("SET CDAUDIO DOOR CLOSED", NULL, 0, NULL ); // This does NOT work on my drive... delay(6*CLK_TCK); goto Rescan; } WinHelp(GetDesktopWindow(),HELPFILE,HELP_QUIT,0); // Free up stopinterfacing(); if (hlogo) ToggleLogo(); return 0; }