//Toney.h #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 #ifndef Toneyh #define Toneyh #include "Thread.h" #include #include #include #ifndef Languageh static const CString sNoNotification (""); static const CString sSilent (""); static const CString sBeep (""); #endif /* Usage: BOOL CMyDlg::OnInitDialog() { CDialog::OnInitDialog(); Toney.LoadCombo((CComboBox*)GetDlgItem(IDC_ToneList), "RingTones.RTTTL"); return TRUE; // return TRUE unless you set the focus to a control } void CMyDlg::OnStop() {Toney.Stop();} void CMyDlg::OnPlay() { CString S; CComboBox* List=(CComboBox*)GetDlgItem(nID); List->GetLBText(List->GetCurSel(), S); Toney.Play(S, "RingTones.RTTTL"); } */ class CToney : public CThread { bool WinNT; CString Path; CString Tune; public: CToney() { OSVERSIONINFO OSVersionInfo; // Find out what Operating System we're running OSVersionInfo.dwOSVersionInfoSize=sizeof(OSVERSIONINFO); WinNT=(GetVersionEx(&OSVersionInfo) ? (OSVersionInfo.dwPlatformId>=VER_PLATFORM_WIN32_NT) : false); } virtual ~CToney() {} void LoadCombo(CComboBox* List, CString Path) { List->AddString(sNoNotification); List->AddString(sSilent); List->AddString(sBeep); CFile File; if(File.Open(Path, CFile::modeRead|CFile::shareDenyNone)) { CArchive Ar(&File, CArchive::load); CString S; while(Ar.ReadString(S)) { if(S.IsEmpty()) break; int i=S.Find(':'); if(i!=-1) { S=S.Left(i); List->AddString(S); } } File.Close(); } List->SetCurSel(List->FindStringExact(-1, sNoNotification)); } void Play(const CString& _Tune, const CString& _Path="") { if(_Tune.IsEmpty() || _Tune==sNoNotification) return; else if(_Tune==sBeep) MessageBeep(-1); //Play a default beep else if(_Tune!=sSilent) { Tune=_Tune; Path=_Path; Start(); } Notify(); } virtual void Notify() {} // Your Notification here // void Stop(); is defined in CThread private: void Main() {PlayTune();} void PlayTune() { if(Path.IsEmpty()) { PlayTune(Tune); return; } CFile File; if(File.Open(Path, CFile::modeRead|CFile::shareDenyNone)) { CArchive Ar(&File,CArchive::load); CString S,lS; Tune.MakeLower(); int i; while(Ar.ReadString(S) && !S.IsEmpty() && !Abort) { i=S.Find(':'); if((i!=-1) && !Tune.CompareNoCase(S.Left(i))) PlayTune(S); } } } void PlayTune(const char* ptr) { // Scale 8 (Max Audible) A A# B (B#) C C# D D# E (E#) F F# G G# static const WORD Notes[14]={28160,29888,31616,16736,16736,17760,18784,19936,21088,22336,22336,23712,25088,26624}; char c; while((c=*ptr++)!=':') if(!c) return; //Get past the name int dDuration=4; int dScale=6; int dTempo=63; while(c=*ptr++) { //Get Defaults if(Abort) return; if(c==',') continue; if(c==':') break; c|=0x20; //tolower if(c=='d') { //Default Duration if(*ptr++!='=') return; if(((c=*ptr++)<'0') || (c>'9')) return; dDuration=c-'0'; if((c=*ptr++)!=',' && (c!=':')) { if((c<'0') || (c>'9')) return; dDuration=dDuration*10+c-'0'; } }else if(c=='o') { //Default Scale if(*ptr++!='=') return; if(((c=*ptr++)<'0') || (c>'9')) return; dScale=c-'0'; }else if(c=='b') { //Default Tempo if(*ptr++!='=') return; if(((c=*ptr++)<'0') || (c>'9')) return; dTempo=c-'0'; if((c=*ptr++)!=',' && (c!=':')) { if((c<'0') || (c>'9')) return; dTempo=dTempo*10+c-'0'; if((c=*ptr)!=',' && (c!=':')) { if((c<'0') || (c>'9')) return; ptr++; dTempo=dTempo*10+c-'0'; } } }else return; } if(!c) return; int Note; int Duration; int Scale; int Tempo=(60000<<2)/dTempo; //milliseconds per beat while(TRUE) { //Get Notes if(!(c=*ptr++) || Abort) return; if(c==',') continue; Duration=dDuration; //set defaults Scale=dScale; if((c>'0') && (c<'9')) { //Get optional duration Duration=c-'0'; if(!(c=*ptr++)) return; if((c>'0') && (c<'9')) { Duration=Duration*10+c-'0'; if(!(c=*ptr++)) return; } } c|=0x20; //tolower if(c=='p') { //A rest (Pause) Note=0; if(!(c=*ptr++)) return; }else{ if(((c-='a')<0) || (c>'g')) return; //Get Note Note=c<<1; if((c=*ptr++)=='#') { c=*ptr++; Note++; //Sharpen } Note=Notes[Note]; } Duration=Tempo/Duration;//Get a big number for if(c=='.') { //Dotted Note (in badly formatted RTTTL files) c=*ptr++; Duration+=Duration>>1; } if((c>'0') && (c<'9')) { //Get optional scale Scale=c-'0'; } if(Note) Note=Note>>(8-Scale+1); if(*ptr=='.') { //Dotted Note ptr++; Duration+=Duration>>1; } Beep(Note, (DWORD)(Duration)); //Play the note } } //The following code enables Win9x to play the tune: /* Beep C0 = 262, D0 = 296, E0 = 330, F0 = 349, G0 = 392, A0 = 440, B0 = 494, C1 = 523, D1 = 587, E1 = 659, F1 = 698, G1 = 784, A1 = 880, B1 = 988, EIGHTH = 125, QUARTER = 250, HALF = 500, WHOLE = 1000, END = 0 Sounds the speaker for a time specified in microseconds by duration at a pitch specified in hertz by frequency. //Use intrinsic versions of _outp and _inp #pragma intrinsic( _outp, _inp ) */ void Beep(int frequency, int duration) { if(WinNT) { ::Beep(frequency ? frequency : 0x7FFF, duration); return; } int control; if(frequency) { /* static DWORD Sound[]={ //Create a 52 Byte .wav file in memory: 'FFIR', //'RIFF' 44, //Structure size 'EVAW', //'WAVE' ' tmf', //'fmt ' 16, //fmt chunk size (1<<16)|1,//[fmt].w, [channels].w (mono) 0x2256, //[ 6] [sample rate] 0x2256, //[ 7] [average bytes per second]=[sample rate] (8<<16)|1,//[block align].w, [bits per sample].w 'atad', //'data' 8, //data length (disregarding padding bytes) 0,-1//3F3F,0x3F3F0000 //data (0,-1)=Loud //0,0x01010101 //data (0xC3C3C3C3,0x3C3C3C3C)=Normal }; //You need to add winmm.lib to [Project][Settings...][Link][object/library modules] to use the PlaySound function Sound[6]=Sound[7]=frequency<<4; //Use sample rate to vary the frequency of the beep played. if(PlaySound((LPCSTR)Sound,0,SND_MEMORY|SND_LOOP|SND_NODEFAULT|SND_ASYNC)) { Pause(duration); PlaySound(NULL,0,SND_PURGE); return; } */ // if(duration<75 && duration!=-1) duration=75; //75 is about the shortest reliable duration of a sound _outp(0x43, 0%10110110); //Prepare timer by sending 10110110 to port 43 //Divide input frequency by timer ticks per second and write (byte by byte) to timer. frequency = (unsigned)(((3579545./3)/frequency)+0.5); _outp(0x42, (char)frequency); _outp(0x42, (char)(frequency>>8)); control=_inp(0x61); _outp(0x61, control | 0x3); //Turn on the speaker (with bits 0 and 1) } if(duration!=-1) { Pause((clock_t)duration); _outp(0x61, control & ~0x3); //Turn speaker back on if necessary } } private: void Pause(clock_t wait) { //Pauses for a specified number of milliseconds. clock_t goal; goal=wait+clock(); while(goal>clock()); } }; /* ; Ringing Tones text transfer language (RTTTL) ; ; Version 1.0 / 29-July-1998 ; - First version by John Mostelo ; ; http://members.tripod.com/~ringtones/note_syntax.txt ; := [] + := + ; maximum name length 10 characters := ":" := | | := "d=" := "o=" := "b=" := 25,28,...,900 ; decimal value ; If not specified, defaults are ; ; 4 = duration ; 6 = scale ; 63 = beats-per-minute := [] [] [] := "1" | ; Full 1/1 note "2" | ; 1/2 note "4" | ; 1/4 note "8" | ; 1/8 note "16" | ; 1/16 note "32" | ; 1/32 note := "P" | ; pause "C" | "C#" | "D" | "D#" | "E" | "F" | "F#" | "G" | "G#" | "A" | "A#" | "B" := "5" | ; Note A is 440Hz "6" | ; Note A is 880Hz "7" | ; Note A is 1.76 kHz "8" ; Note A is 3.52 kHz := "." ; Dotted note := "," ; End of specification */ #endif //ndef Toneyh