www.pudn.com > 使用IP网络聊天的VOIP源码.zip > main.cpp


/* 
   Talker - A small program which utilizes the Layer-3 codec (ACM) in windows for voice-over-IP 
   Copyright (C) 1999 Dino Klein 
 
   This program is free software; you can redistribute it and/or modify it under the terms of 
   the GNU General Public License as published by the Free Software Foundation; either 
   version 2 of the License, or (at your option) any later version.  
 
   This program is distributed in the hope that it will be useful, but WITHOUT ANY 
   WARRANTY; without even the implied warranty of MERCHANTABILITY or 
   FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 
   more details.  
 
   You should have received a copy of the GNU General Public License along with this 
   program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, 
   MA 02139, USA. 
 
   email: dinoklein@hotmail.com 
*/ 
 
 
#define  WIN32_LEAN_AND_MEAN 
 
#include  
#include  
#include  
#include  
#include  
#include  
#include "defines.h" 
#include "resource.h" 
 
 
 
// external functions 
char init_sockets (void); 
void close_sockets (void); 
char init_sound (void); 
void close_sound (void); 
DWORD WINAPI sender (LPVOID); 
DWORD WINAPI receiver (LPVOID); 
DWORD WINAPI player (LPVOID); 
BOOL CALLBACK addr_dialog (HWND, UINT, WPARAM, LPARAM); 
BOOL CALLBACK talk_dialog (HWND, UINT, WPARAM, LPARAM); 
 
 
 
int               queue_size; 
sound_sec         sqq[MAX_QUEUE]; 
int               index_put, index_take; 
 
bool              dbl; 
HANDLE            heap;   // maybe will use this for allocating memory dynamically for the ACM 
int               band;   // stupid name 
bool              stereo, use_primary; 
bool              blocks_got[16]; 
unsigned char     total_blocks; 
 
char              acmbuf[44100]; 
char              output_buffer[4096]; 
char              decomp_buf[44100]; 
char              comped_buf[4096]; 
 
CRITICAL_SECTION  cs; 
char              my_addr_txt [16], dst_addr_txt [16]; 
unsigned long     my_addr, dst_addr; 
unsigned short    next_send_id, next_receive_id; 
SOCKET            ssin, sout; 
HACMSTREAM        has, hasd; 
HANDLE            hPlay, hRec[10], hTerminate, hData; 
int               segments, lock_size, input_buffer_size, output_buf_size; 
HANDLE            Thread [3]; 
DWORD             id [3]; 
ACMSTREAMHEADER   ahc, ahd; 
WAVEFORMATEX      wfx; 
MPEG_WFX          mwfx; 
char              listen_mode; 
HWND              talker_dlg; 
 
 
 
 
 
void ErrB (char *msg, int x=0, HWND hwnd=0) 
{ 
   char str[128]; 
 
 
   if (x) sprintf(str, "%s, code: %X", msg, x); 
   else sprintf(str, "%s", msg); 
   MessageBox(hwnd, str, 0, 0); 
} 
 
 
 
void release_vars (void) 
{ 
   DeleteCriticalSection (&cs); 
   CloseHandle (hPlay); 
   CloseHandle (hTerminate); 
   CloseHandle (hData); 
} 
 
 
 
char init_vars (void) 
{ 
   hPlay = CreateEvent (0, 0, 0, 0); 
   if (hPlay) 
   { 
      for (int i=0;i<10;i++) hRec[i] = CreateEvent (0, 0, 0, 0); 
      if (hRec[0]&&hRec[1]&&hRec[2]&&hRec[3]&&hRec[4]&&hRec[5]&&hRec[6]&&hRec[7]&&hRec[8]&&hRec[9]) 
      { 
         hTerminate = CreateEvent (0, 1, 0, 0); 
         if (hTerminate) 
         { 
            hData = CreateSemaphore(0, 0, 63, 0); 
            if (hData) 
            { 
               next_receive_id = 0; 
               next_send_id = 1; 
 
               my_addr = 0; 
 
               memset (&mwfx, 0, sizeof (MPEG_WFX)); 
               mwfx.wfx.wFormatTag = 85; 
               mwfx.wfx.nChannels = (stereo) ? 2 : 1; 
               mwfx.wfx.nSamplesPerSec = 11025; 
               mwfx.wfx.nAvgBytesPerSec = (band==0) ? 1000 : ((band==1) ? 2000 : 2500); 
               mwfx.wfx.nBlockAlign = 1; 
               mwfx.wfx.wBitsPerSample = 0; 
               mwfx.wfx.cbSize = 12; 
               // only 11025hz; adjust channels for number of channels 
               // for 20kbit: data[6]=4,data[7]=1,data[8]=2, avgbytespersec=2500 
               // THE 18kbit is not good since it requires 5 packets which is exactly as the 20kbit which is better 
               // for 18kbit: data[6]=0xD4,data[7]=1,data[8]=4,avg=2250 
               // for 16kbit: data[6]=0x68,avg=2000 
               // for 8kbit: data[6]=0x34,data[8]=1, avg=1000 
               mwfx.data[0] = 1; 
               mwfx.data[2] = 2; 
               mwfx.data[10] = 0x71; 
               mwfx.data[11] = 5; 
               switch (band) 
               { 
                  case 0: 
                     mwfx.data[6] = 0x34; 
                     mwfx.data[8] = 1; 
                     break; 
 
                  case 1: 
                     mwfx.data[6] = 0x68; 
                     mwfx.data[8] = 1; 
                     break; 
 
                  case 2: 
                     mwfx.data[6] = 4; 
                     mwfx.data[7] = 1; 
                     mwfx.data[8] = 2; 
                     break; 
               } 
 
 
 
               wfx.wFormatTag = WAVE_FORMAT_PCM; 
               wfx.nChannels = (stereo) ? 2 : 1; 
               wfx.nSamplesPerSec = 11025; 
               wfx.nAvgBytesPerSec = (stereo) ? 44100 : 22050; 
               wfx.nBlockAlign = (stereo) ? 4 : 2; 
               wfx.wBitsPerSample = 16; 
               wfx.cbSize = 0; 
 
 
               InitializeCriticalSection (&cs); 
               index_put = 0; 
               index_take = -1; 
               queue_size = 0; 
               dbl = false; 
               segments = 4; 
               input_buffer_size = (stereo)?44100:22050; 
               lock_size = (stereo)?11024:5512; 
 
               return (1); 
            } 
            //CloseHandle (hTerminate); 
         } 
         //CloseHandle (hRec); 
      } 
      //CloseHandle (hPlay); 
   } 
   return (0); 
} 
 
 
 
 
 
 
 
char init_threads (void) 
{ 
   Thread[0] = CreateThread (0, 0, sender, 0, 0, &id[0]); 
   if (Thread[0]) 
   { 
      Thread[1] = CreateThread (0, 0, player, 0, CREATE_SUSPENDED, &id[1]); 
      if (Thread[1]) 
      { 
         Thread[2] = CreateThread (0, 0, receiver, 0, CREATE_SUSPENDED, &id[2]); 
         if (Thread[2]) return (1); 
      } 
   } 
 
   SetEvent (hTerminate); 
   return (0); 
} 
 
 
 
void close_threads (void) 
{ 
   SetEvent (hTerminate); 
   ResumeThread (Thread[1]); 
   ResumeThread (Thread[2]); 
   WaitForMultipleObjects (3, Thread, 1, INFINITE); 
} 
 
 
char init_all (void) 
{ 
   if (init_vars ()) 
   { 
      if (init_sound ()) 
      { 
         if (init_sockets ()) 
         { 
            if (init_threads ()) return (1); 
         } 
 
         else ErrB ("socket problem"); 
         close_sound (); 
      } 
      else ErrB ("sound problem"); 
      release_vars (); 
   } 
   else ErrB ("varialbe problem"); 
 
   return (0); 
} 
 
 
void close_all (void) 
{ 
   close_threads (); 
   close_sound (); 
   close_sockets (); 
} 
 
 
 
 
 
 
 
 
int WINAPI WinMain (HINSTANCE h1, HINSTANCE h2, LPSTR cmd, int show) 
{ 
 
   int  r; 
 
 
 
   // after much thought, it seems just right to give ourselves a boost 
   // and anyway, we don't waste that much cycles 
   SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); 
   band = 0; 
   r = DialogBox (h1, MAKEINTRESOURCE (IDD_ADDRESS), 0, (DLGPROC) addr_dialog); 
   switch (r) 
   { 
      case 0 : 
         ErrB ("operation canceled"); 
         break; 
 
      case 1: 
         if (init_all ()) 
         { 
            r = DialogBox (h1, MAKEINTRESOURCE (IDD_TALK), 0, (DLGPROC) talk_dialog); 
            if (r) ErrB ("failed to create dialog box, aborting"); 
            close_all (); 
         } 
         else ErrB ("init failed"); 
         break; 
 
      case -1 : 
         ErrB ("failed to create first dialog box, aborting"); 
         break; 
   } 
 
 
   ExitProcess (0); 
   return (0); 
}