// example_audio_socks.cpp : Defines the entry point for the application. // #include "stdafx.h" #include "example_audio_socks.h" #include #include #include #include #include "audio.h" #include "socks.h" enum Mode {HOLD,RECORD,PLAY}; static Mode mode=HOLD; static bool newnetconfig=true; TCHAR myport[16] = _T("5199"); TCHAR remoteip[16] = _T("129.105.100.176"); TCHAR remoteport[16] = _T("5199"); #define MAX_LOADSTRING 1024 // Global Variables: HINSTANCE g_hInst; // The current instance HWND g_hwndCB; // The command bar handle static SHACTIVATEINFO s_sai; // Forward declarations of functions included in this code module: ATOM MyRegisterClass (HINSTANCE, LPTSTR); BOOL InitInstance (HINSTANCE, int); LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK About (HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK Config (HWND, UINT, WPARAM, LPARAM); HWND CreateRpCommandBar(HWND); DWORD WINAPI HandlerThread(LPVOID param); int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { MSG msg; HACCEL hAccelTable; // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_EXAMPLE_AUDIO_SOCKS); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; } // // FUNCTION: MyRegisterClass() // // PURPOSE: Registers the window class. // // COMMENTS: // // It is important to call this function so that the application // will get 'well formed' small icons associated with it. // ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass) { WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC) WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_EXAMPLE_AUDIO_SOCKS)); wc.hCursor = 0; wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); wc.lpszMenuName = 0; wc.lpszClassName = szWindowClass; return RegisterClass(&wc); } // // FUNCTION: InitInstance(HANDLE, int) // // PURPOSE: Saves instance handle and creates main window // // COMMENTS: // // In this function, we save the instance handle in a global variable and // create and display the main program window. // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd = NULL; TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // The window class name g_hInst = hInstance; // Store instance handle in our global variable // Initialize global strings LoadString(hInstance, IDC_EXAMPLE_AUDIO_SOCKS, szWindowClass, MAX_LOADSTRING); LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); //If it is already running, then focus on the window hWnd = FindWindow(szWindowClass, szTitle); if (hWnd) { // set focus to foremost child window // The "| 0x01" is used to bring any owned windows to the foreground and // activate them. SetForegroundWindow((HWND)((ULONG) hWnd | 0x00000001)); return 0; } MyRegisterClass(hInstance, szWindowClass); hWnd = CreateWindow(szWindowClass, szTitle, WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } //When the main window is created using CW_USEDEFAULT the height of the menubar (if one // is created is not taken into account). So we resize the window after creating it // if a menubar is present if (g_hwndCB) { RECT rc; RECT rcMenuBar; GetWindowRect(hWnd, &rc); GetWindowRect(g_hwndCB, &rcMenuBar); rc.bottom -= (rcMenuBar.bottom - rcMenuBar.top); MoveWindow(hWnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, FALSE); } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // FUNCTION: WndProc(HWND, unsigned, WORD, LONG) // // PURPOSE: Processes messages for the main window. // // WM_COMMAND - process the application menu // WM_PAINT - Paint the main window // WM_DESTROY - post a quit message and return // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; int wmId, wmEvent; PAINTSTRUCT ps; TCHAR buf[MAX_LOADSTRING]; switch (message) { case WM_LBUTTONDOWN: if (mode==HOLD) { mode=RECORD; } else if (mode==RECORD) { mode=PLAY; } else { mode=HOLD; } InvalidateRect(hWnd,NULL,true); break; case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_HELP_ABOUT: DialogBox(g_hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); break; case IDM_CONFIG: if (DialogBox(g_hInst, (LPCTSTR)IDD_CONFIG, hWnd, (DLGPROC)Config)==IDOK) { newnetconfig=true; } break; case IDM_QUIT: exit(0); break; case IDOK: SendMessage (hWnd, WM_CLOSE, 0, 0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_CREATE: g_hwndCB = CreateRpCommandBar(hWnd); // Initialize the shell activate info structure memset (&s_sai, 0, sizeof (s_sai)); s_sai.cbSize = sizeof (s_sai); CreateThread(NULL,0,HandlerThread,0,0,0); break; case WM_PAINT: { ; RECT rt; hdc = BeginPaint(hWnd, &ps); GetClientRect(hWnd, &rt); _stprintf(buf,_T("mode=%s - tap to change"), mode==HOLD ? _T("Hold") : mode==PLAY ? _T("Play") : _T("Record")); DrawText(hdc, buf, _tcslen(buf), &rt, DT_SINGLELINE | DT_VCENTER | DT_CENTER); EndPaint(hWnd, &ps); } break; case WM_DESTROY: CommandBar_Destroy(g_hwndCB); PostQuitMessage(0); break; case WM_ACTIVATE: // Notify shell of our activate message SHHandleWMActivate(hWnd, wParam, lParam, &s_sai, FALSE); break; case WM_SETTINGCHANGE: SHHandleWMSettingChange(hWnd, wParam, lParam, &s_sai); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } HWND CreateRpCommandBar(HWND hwnd) { SHMENUBARINFO mbi; memset(&mbi, 0, sizeof(SHMENUBARINFO)); mbi.cbSize = sizeof(SHMENUBARINFO); mbi.hwndParent = hwnd; mbi.nToolBarId = IDM_MENU; mbi.hInstRes = g_hInst; mbi.nBmpId = 0; mbi.cBmpImages = 0; if (!SHCreateMenuBar(&mbi)) return NULL; return mbi.hwndMB; } // Mesage handler for the About box. LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { SHINITDLGINFO shidi; switch (message) { case WM_INITDIALOG: // Create a Done button and size it. shidi.dwMask = SHIDIM_FLAGS; shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN; shidi.hDlg = hDlg; SHInitDialog(&shidi); return TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK) { EndDialog(hDlg, LOWORD(wParam)); return TRUE; } break; } return FALSE; } // Mesage handler for the Config box. LRESULT CALLBACK Config(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { SHINITDLGINFO shidi; switch (message) { case WM_INITDIALOG: // Create a Done button and size it. shidi.dwMask = SHIDIM_FLAGS; shidi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIPDOWN | SHIDIF_SIZEDLGFULLSCREEN; shidi.hDlg = hDlg; SHInitDialog(&shidi); SetDlgItemText(hDlg,IDC_MYPORT,myport); SetDlgItemText(hDlg,IDC_REMOTEIP,remoteip); SetDlgItemText(hDlg,IDC_REMOTEPORT,remoteport); return TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK) { GetDlgItemText(hDlg,IDC_MYPORT,myport,16); GetDlgItemText(hDlg,IDC_REMOTEIP,remoteip,16); GetDlgItemText(hDlg,IDC_REMOTEPORT,remoteport,16); EndDialog(hDlg, LOWORD(wParam)); return TRUE; } if (LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return TRUE; } break; } return FALSE; } #define MIN(x,y) ((x)<(y) ? (x) : (y)) void ConvertTToC(CHAR* pszDest, const TCHAR* pszSrc, const int n) { for(int i = 0; i < MIN(n,(int)(_tcslen(pszSrc))+1); i++) { pszDest[i] = (CHAR) pszSrc[i]; } pszDest[MIN(n,(int)(_tcslen(pszSrc))+1)]=0; } void ConvertCToT(TCHAR* pszDest, const CHAR* pszSrc, const int n) { for(int i = 0; i < MIN(n,(int)(strlen(pszSrc))+1); i++) { pszDest[i] = (TCHAR) pszSrc[i]; } pszDest[MIN(n,strlen(pszSrc)+1)]=0; } #define BUFSIZE 8000 DWORD WINAPI HandlerThread(LPVOID param) { char recbuf[BUFSIZE]; char playbuf[BUFSIZE]; unsigned nu; int n; bool firstpass; int sendsocket=-1, recvsocket=-1; unsigned targetip; int targetport; int thisport; Mode mymode=HOLD; while (1) { if (newnetconfig || mymode!=mode) { if (sendsocket!=-1) { CLOSE(sendsocket); sendsocket=-1; } if (recvsocket!=-1) { CLOSE(recvsocket); recvsocket=-1; } char buf[16]; ConvertTToC(buf,remoteip,16); targetip=ToIPAddress(buf); ConvertTToC(buf,remoteport,16); targetport=atoi(buf); ConvertTToC(buf,myport,16); thisport=atoi(buf); if (mode==RECORD) { assert((sendsocket=CreateAndSetupUdpSocket(BUFSIZE*4,true)) >=0 ); assert(ConnectToHost(sendsocket,targetip,targetport)==0); } if (mode==PLAY) { assert((recvsocket=CreateAndSetupUdpSocket(BUFSIZE*4,true)) >=0 ); assert(BindSocket(recvsocket,thisport)==0); assert(ListenSocket(recvsocket)==0); } newnetconfig=false; } if (mymode!=mode) { // new mode if (mymode==PLAY) { assert(SoundOutDeinit()==0); } else if (mymode==RECORD) { assert(SoundInDeinit()==0); } mymode=mode; if (mymode==PLAY) { assert(SoundOutInit()==0); } else if (mymode==RECORD) { assert(SoundInInit()==0); } firstpass=true; // indicates we need to buffer } switch (mymode) { case HOLD: Sleep(10); break; case PLAY: // Read from network into playvuffer n=Receive(recvsocket,playbuf,BUFSIZE,false); if (n>0 && n<=BUFSIZE) { nu=(unsigned)n; assert(SoundOutSubmitBlock(playbuf,&nu)>=0); firstpass=false; } else { Sleep(10); } break; case RECORD: nu=BUFSIZE; assert(SoundInSubmitBlock(&nu)>=0); if (firstpass) { // submit a second block nu=BUFSIZE; assert(SoundInSubmitBlock(&nu)>=0); } nu=BUFSIZE; assert(SoundInAwaitBlock(recbuf,&nu)==0); n=(int)nu; n=Send(sendsocket,recbuf,n,false); firstpass=false; } } return 0; }