1 /* PROJECT: ReactOS sndrec32 2 * LICENSE: GPL - See COPYING in the top level directory 3 * FILE: base/applications/sndrec32/sndrec32.cpp 4 * PURPOSE: Sound recording 5 * PROGRAMMERS: Marco Pagliaricci (irc: rendar) 6 * Robert Naumann (gonzoMD) 7 */ 8 9 #include "stdafx.h" 10 11 #include <commctrl.h> 12 #include <commdlg.h> 13 #include <winnls.h> 14 15 #include "sndrec32.h" 16 #include "shellapi.h" 17 18 #ifndef _UNICODE 19 #define gprintf _snprintf 20 #else 21 #define gprintf _snwprintf 22 #endif 23 24 HINSTANCE hInst; 25 TCHAR szTitle[MAX_LOADSTRING]; 26 TCHAR szWindowClass[MAX_LOADSTRING]; 27 28 ATOM MyRegisterClass(HINSTANCE hInstance); 29 ATOM MyRegisterClass_wave(HINSTANCE hInstance); 30 BOOL InitInstance(HINSTANCE, int); 31 BOOL InitInstance_wave(HWND, HINSTANCE, int); 32 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 33 LRESULT CALLBACK WndProc_wave(HWND, UINT, WPARAM, LPARAM); 34 35 BOOL win_first, wout_first; 36 37 HWND main_win; 38 HWND wave_win; 39 HWND slider; 40 HWND buttons[5]; 41 HBITMAP butbmps[5]; 42 HBITMAP butbmps_dis[5]; 43 WNDPROC buttons_std_proc; 44 45 BOOL butdisabled[5]; 46 BOOL stopped_flag; 47 BOOL isnew; 48 BOOL display_dur; 49 50 DWORD slider_pos; 51 WORD slider_min; 52 WORD slider_max; 53 54 DWORD samples_max; 55 56 OPENFILENAME ofn; 57 TCHAR file_path[MAX_PATH]; 58 TCHAR str_pos[MAX_LOADSTRING]; 59 TCHAR str_dur[MAX_LOADSTRING]; 60 TCHAR str_buf[MAX_LOADSTRING]; 61 TCHAR str_fmt[MAX_LOADSTRING]; 62 TCHAR str_chan[MAX_LOADSTRING]; 63 64 TCHAR str_mono[10]; 65 TCHAR str_stereo[10]; 66 67 BOOL path_set; 68 69 snd::audio_membuffer *AUD_BUF; 70 snd::audio_waveout *AUD_OUT; 71 snd::audio_wavein *AUD_IN; 72 73 BOOL s_recording; 74 75 NONCLIENTMETRICS s_info; 76 77 RECT text_rect; 78 RECT text2_rect; 79 RECT cli; 80 81 int 82 APIENTRY 83 _tWinMain(HINSTANCE hInstance, 84 HINSTANCE hPrevInstance, 85 LPTSTR lpCmdLine, 86 int nCmdShow) 87 { 88 UNREFERENCED_PARAMETER(hPrevInstance); 89 UNREFERENCED_PARAMETER(lpCmdLine); 90 91 MSG msg; 92 HACCEL hAccelTable; 93 94 s_info.cbSize = sizeof( NONCLIENTMETRICS ); 95 96 InitCommonControls(); 97 98 switch (GetUserDefaultUILanguage()) 99 { 100 case MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT): 101 SetProcessDefaultLayout(LAYOUT_RTL); 102 break; 103 104 default: 105 break; 106 } 107 108 win_first = wout_first = FALSE; 109 110 text_rect.left = REFRESHA_X; 111 text_rect.top = REFRESHA_Y; 112 text_rect.right = REFRESHA_CX; 113 text_rect.bottom = REFRESHA_CY; 114 115 text2_rect.left = REFRESHB_X; 116 text2_rect.top = REFRESHB_Y; 117 text2_rect.right = REFRESHB_CX; 118 text2_rect.bottom = REFRESHB_CY; 119 120 /* Retrieving default system font, and others system informations */ 121 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 122 sizeof(NONCLIENTMETRICS), 123 &s_info, 124 0); 125 126 /* Set font size */ 127 s_info.lfMenuFont.lfHeight = 14; 128 129 /* Inits buttons bitmaps */ 130 131 butbmps[0] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_START)); 132 butbmps[1] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_END)); 133 butbmps[2] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_PLAY)); 134 butbmps[3] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_STOP)); 135 butbmps[4] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_REC)); 136 137 butbmps_dis[0] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_START_DIS)); 138 butbmps_dis[1] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_END_DIS)); 139 butbmps_dis[2] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_PLAY_DIS)); 140 butbmps_dis[3] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_STOP_DIS)); 141 butbmps_dis[4] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_REC_DIS)); 142 143 /* Inits audio devices and buffers */ 144 145 snd::audio_membuffer AUD_buffer(snd::A44100_16BIT_STEREO); 146 snd::audio_waveout AUD_waveout(snd::A44100_16BIT_STEREO, AUD_buffer); 147 snd::audio_wavein AUD_wavein(snd::A44100_16BIT_STEREO, AUD_buffer); 148 149 AUD_buffer.play_finished = l_play_finished; 150 AUD_buffer.audio_arrival = l_audio_arrival; 151 AUD_buffer.buffer_resized = l_buffer_resized; 152 153 AUD_buffer.alloc_seconds(INITIAL_BUFREC_SECONDS); 154 155 AUD_IN = &AUD_wavein; 156 AUD_OUT = &AUD_waveout; 157 AUD_BUF = &AUD_buffer; 158 159 /* Inits slider default parameters */ 160 161 slider_pos = 0; 162 slider_min = 0; 163 slider_max = SLIDER_W; 164 165 stopped_flag = FALSE; 166 path_set = FALSE; 167 isnew = TRUE; 168 display_dur = TRUE; 169 170 samples_max = AUD_buffer.total_samples(); 171 172 s_recording = false; 173 174 /* Inits strings */ 175 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); 176 LoadString(hInstance, IDC_REACTOS_SNDREC32, szWindowClass, MAX_LOADSTRING); 177 LoadString(hInstance, IDS_STRPOS, str_pos, MAX_LOADSTRING); 178 LoadString(hInstance, IDS_STRDUR, str_dur, MAX_LOADSTRING); 179 LoadString(hInstance, IDS_STRBUF, str_buf, MAX_LOADSTRING); 180 LoadString(hInstance, IDS_STRFMT, str_fmt, MAX_LOADSTRING); 181 LoadString(hInstance, IDS_STRCHAN, str_chan, MAX_LOADSTRING); 182 LoadString(hInstance, IDS_STRMONO, str_mono, 10); 183 LoadString(hInstance, IDS_STRSTEREO, str_stereo, 10); 184 185 /* Registers sndrec32 window class */ 186 MyRegisterClass(hInstance); 187 MyRegisterClass_wave(hInstance); 188 189 if (!InitInstance(hInstance, nCmdShow)) 190 { 191 MessageBox(0, TEXT("CreateWindow() Error!"), TEXT("ERROR"), MB_ICONERROR); 192 return FALSE; 193 } 194 195 /* Loads key accelerators */ 196 hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_REACTOS_SNDREC32)); 197 198 /* Starts main loop */ 199 while (GetMessage(&msg, NULL, 0, 0)) 200 { 201 if (!TranslateAccelerator(main_win, hAccelTable, &msg)) 202 { 203 TranslateMessage(&msg); 204 DispatchMessage(&msg); 205 } 206 } 207 208 if (wout_first) 209 { 210 AUD_waveout.close(); 211 } 212 213 if (win_first) 214 { 215 AUD_wavein.close(); 216 } 217 218 AUD_buffer.clear(); 219 220 return (int)msg.wParam; 221 } 222 223 ATOM 224 MyRegisterClass(HINSTANCE hInstance) 225 { 226 WNDCLASSEX wcex; 227 228 wcex.cbSize = sizeof(WNDCLASSEX); 229 230 wcex.style = CS_HREDRAW | CS_VREDRAW; 231 wcex.lpfnWndProc = WndProc; 232 wcex.cbClsExtra = 0; 233 wcex.cbWndExtra = 0; 234 wcex.hInstance = hInstance; 235 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SNDREC32)); 236 wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 237 wcex.hbrBackground = GetSysColorBrush(COLOR_BTNFACE); 238 wcex.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1); 239 wcex.lpszClassName = szWindowClass; 240 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SNDREC32)); 241 242 return RegisterClassEx(&wcex); 243 } 244 245 BOOL 246 InitInstance(HINSTANCE hInstance, int nCmdShow) 247 { 248 HWND hWnd; 249 250 hInst = hInstance; 251 252 hWnd = CreateWindow(szWindowClass, 253 szTitle, 254 WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, 255 CW_USEDEFAULT, 256 CW_USEDEFAULT, 257 MAINWINDOW_W, 258 MAINWINDOW_H, 259 NULL, 260 NULL, 261 hInstance, 262 NULL); 263 if (!hWnd) 264 { 265 return FALSE; 266 } 267 268 ShowWindow(hWnd, nCmdShow); 269 UpdateWindow(hWnd); 270 271 main_win = hWnd; 272 273 return TRUE; 274 } 275 276 ATOM 277 MyRegisterClass_wave(HINSTANCE hInstance) 278 { 279 WNDCLASSEX wcex; 280 281 wcex.cbSize = sizeof(WNDCLASSEX); 282 283 wcex.style = CS_HREDRAW | CS_VREDRAW; 284 wcex.lpfnWndProc = WndProc_wave; 285 wcex.cbClsExtra = 0; 286 wcex.cbWndExtra = 0; 287 wcex.hInstance = hInstance; 288 wcex.hIcon = 0; 289 wcex.hCursor = LoadCursor(NULL, IDC_ARROW); 290 wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); 291 wcex.lpszMenuName = 0; 292 wcex.lpszClassName = TEXT("sndrec32_wave"); 293 wcex.hIconSm = 0; 294 295 return RegisterClassEx(&wcex); 296 } 297 298 BOOL 299 InitInstance_wave(HWND f, 300 HINSTANCE hInstance, 301 int nCmdShow) 302 { 303 HWND hWnd; 304 305 hInst = hInstance; 306 307 hWnd = CreateWindowEx(WS_EX_STATICEDGE, 308 TEXT("sndrec32_wave"), 309 TEXT(""), 310 WS_VISIBLE | WS_CHILD, 311 WAVEBAR_X, 312 WAVEBAR_Y, 313 WAVEBAR_CX, 314 WAVEBAR_CY, 315 f, 316 (HMENU)8, 317 hInstance, 318 0); 319 320 if (!hWnd ) 321 { 322 return FALSE; 323 } 324 325 ShowWindow(hWnd, nCmdShow); 326 UpdateWindow(hWnd); 327 328 wave_win = hWnd; 329 330 return TRUE; 331 } 332 333 LRESULT 334 CALLBACK 335 WndProc_wave(HWND hWnd, 336 UINT message, 337 WPARAM wParam, 338 LPARAM lParam) 339 { 340 PAINTSTRUCT ps; 341 HDC hdc; 342 HPEN pen; 343 HPEN oldpen; 344 345 unsigned int max_h = (cli.bottom / 2); 346 unsigned int samples; 347 unsigned int x, line_h; 348 349 switch (message) 350 { 351 case WM_CREATE: 352 GetClientRect(hWnd, &cli); 353 break; 354 355 case WM_PAINT: 356 /* Initialize hdc objects */ 357 hdc = BeginPaint(hWnd, &ps); 358 pen = (HPEN)CreatePen(PS_SOLID, 1, WAVEBAR_COLOR); 359 oldpen = (HPEN) SelectObject(hdc, (HBRUSH)pen); 360 if (AUD_OUT->current_status() == snd::WAVEOUT_PLAYING) 361 { 362 samples = AUD_OUT->tot_samples_buf(); 363 for (unsigned int i = 0; i < WAVEBAR_CX; ++i) 364 { 365 x = (i * samples) / WAVEBAR_CX; 366 line_h = (AUD_OUT->nsample(x) * max_h) / AUD_OUT->samplevalue_max(); 367 if (line_h) 368 { 369 MoveToEx(hdc, i, max_h, 0); 370 LineTo(hdc, i, max_h - (line_h * 2)); 371 LineTo(hdc, i, max_h + (line_h * 2)); 372 } 373 else 374 { 375 SetPixel(hdc, i, max_h, WAVEBAR_COLOR); 376 } 377 } 378 } 379 else if (AUD_IN->current_status() == snd::WAVEIN_RECORDING) 380 { 381 samples = AUD_IN->tot_samples_buf(); 382 for (unsigned int i = 0; i < WAVEBAR_CX; ++i) 383 { 384 x = (i * samples) / WAVEBAR_CX; 385 line_h = (AUD_IN->nsample(x) * max_h) / AUD_IN->samplevalue_max(); 386 if (line_h) 387 { 388 MoveToEx(hdc, i, max_h, 0); 389 LineTo(hdc, i, max_h - (line_h * 2)); 390 LineTo(hdc, i, max_h + (line_h * 2)); 391 } 392 else 393 { 394 SetPixel( hdc, i, max_h, WAVEBAR_COLOR ); 395 } 396 } 397 } 398 else 399 { 400 /* In standby mode draw a simple line */ 401 MoveToEx(hdc, 0, cli.bottom / 2, 0); 402 LineTo(hdc, WAVEBAR_CX, cli.bottom / 2); 403 } 404 405 SelectObject(hdc, oldpen); 406 DeleteObject( pen ); 407 EndPaint( hWnd, &ps ); 408 break; 409 410 case WM_USER: 411 break; 412 413 default: 414 return DefWindowProc(hWnd, message, wParam, lParam); 415 } 416 417 return 0; 418 } 419 420 LRESULT 421 CALLBACK 422 WndProc(HWND hWnd, 423 UINT message, 424 WPARAM wParam, 425 LPARAM lParam) 426 { 427 int wmId; 428 TCHAR str_tmp[MAX_LOADSTRING]; 429 PAINTSTRUCT ps; 430 HDC hdc; 431 HFONT font; 432 HFONT oldfont; 433 long long slid_samp = 0; 434 WCHAR szAppName[100]; 435 HICON hIcon; 436 437 /* Checking for global pointers to buffer and io audio devices */ 438 if ((!AUD_IN) || (!AUD_OUT) || (!AUD_BUF)) 439 { 440 MessageBox(0, TEXT("Buffer Error"), 0, 0); 441 return 1; 442 } 443 444 switch (message) 445 { 446 case WM_CREATE: 447 /* Creating the wave bar */ 448 if (!InitInstance_wave(hWnd, hInst, SW_SHOWNORMAL)) 449 { 450 MessageBox(0, TEXT("InitInstance_wave() Error!"), TEXT("ERROR"), MB_ICONERROR); 451 return FALSE; 452 } 453 454 /* Creating ALL the buttons */ 455 for (int i = 0; i < 5; ++i) 456 { 457 buttons[i] = CreateWindow(TEXT("button"), 458 TEXT(""), 459 WS_CHILD | WS_VISIBLE | BS_BITMAP, 460 BUTTONS_CX + (i * (BUTTONS_W + ((i == 0) ? 0 : BUTTONS_SPACE))), 461 BUTTONS_CY, 462 BUTTONS_W, 463 BUTTONS_H, 464 hWnd, 465 (HMENU)UlongToPtr(i), 466 hInst, 467 0); 468 if (!buttons[i]) 469 { 470 MessageBox(0, 0, TEXT("CreateWindow() Error!"), 0); 471 return FALSE; 472 } 473 474 /* Realize the button bmp image */ 475 SendMessage(buttons[i], BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)butbmps[i]); 476 UpdateWindow(buttons[i]); 477 disable_but(i); 478 } 479 480 /* Creating the SLIDER window */ 481 slider = CreateWindow(TRACKBAR_CLASS, 482 TEXT(""), 483 WS_CHILD | WS_VISIBLE | TBS_NOTICKS | TBS_HORZ | TBS_ENABLESELRANGE, 484 SLIDER_CX, 485 SLIDER_CY, 486 SLIDER_W, 487 SLIDER_H, 488 hWnd, 489 (HMENU)SLIDER_ID, 490 hInst, 491 0); 492 if (!slider) 493 { 494 MessageBox(0, 0, TEXT( "CreateWindow() Error!" ), 0); 495 return FALSE; 496 } 497 498 /* Sets slider limits */ 499 SendMessage(slider, 500 TBM_SETRANGE, 501 (WPARAM)TRUE, 502 (LPARAM)MAKELONG(slider_min, slider_max)); 503 504 UpdateWindow(slider); 505 enable_but(BUTREC_ID); 506 EnableWindow(slider, FALSE); 507 break; 508 509 /* Implements slider logic */ 510 case WM_HSCROLL: 511 { 512 switch (LOWORD(wParam)) 513 { 514 case SB_ENDSCROLL: 515 break; 516 case SB_PAGERIGHT: 517 case SB_PAGELEFT: 518 case TB_THUMBTRACK: 519 /* If the user touch the slider bar, set the 520 audio start position properly */ 521 slider_pos = SendMessage(slider, TBM_GETPOS, 0, 0); 522 slid_samp = (__int64)slider_pos * (__int64)samples_max; 523 AUD_BUF->set_position(AUD_BUF->audinfo().bytes_in_samples((unsigned int)(slid_samp / (__int64)slider_max))); 524 InvalidateRect(hWnd, &text_rect, TRUE); 525 break; 526 } 527 break; 528 } 529 530 case WM_COMMAND: 531 wmId = LOWORD(wParam); 532 if ((wmId >= 0) && (wmId < 5) && (butdisabled[wmId] != FALSE)) 533 break; 534 535 switch (wmId) 536 { 537 case ID_FILE_NEW: 538 if (!isnew) 539 { 540 if (AUD_IN->current_status() == snd::WAVEIN_RECORDING) 541 AUD_IN->stop_recording(); 542 543 if ((AUD_OUT->current_status() == snd::WAVEOUT_PLAYING) || 544 (AUD_OUT->current_status() == snd::WAVEOUT_PAUSED)) 545 AUD_OUT->stop(); 546 547 AUD_BUF->reset(); 548 549 enable_but(BUTREC_ID); 550 disable_but(BUTSTART_ID); 551 disable_but(BUTEND_ID); 552 disable_but(BUTSTOP_ID); 553 disable_but(BUTPLAY_ID); 554 555 samples_max = AUD_BUF->total_samples(); 556 slider_pos = 0; 557 558 SendMessage(slider, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) slider_pos); 559 560 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVEAS, MF_GRAYED); 561 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVE, MF_GRAYED); 562 563 isnew = TRUE; 564 display_dur = TRUE; 565 566 ZeroMemory(file_path, MAX_PATH * sizeof(TCHAR)); 567 568 EnableWindow(slider, FALSE); 569 570 InvalidateRect(hWnd, &text_rect, TRUE); 571 InvalidateRect(hWnd, &text2_rect, TRUE); 572 } 573 break; 574 575 case ID_FILE_OPEN: 576 ZeroMemory(&ofn, sizeof(ofn)); 577 578 ofn.lStructSize = sizeof(ofn); 579 ofn.hwndOwner = hWnd; 580 ofn.lpstrFilter = TEXT("Audio Files (*.wav)\0*.wav\0All Files (*.*)\0*.*\0"); 581 ofn.lpstrFile = file_path; 582 ofn.nMaxFile = MAX_PATH; 583 ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; 584 ofn.lpstrDefExt = TEXT("wav"); 585 586 if (GetOpenFileName(&ofn)) 587 { 588 open_wav(file_path); 589 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVE, MF_ENABLED); 590 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVEAS, MF_ENABLED); 591 592 EnableWindow(slider, TRUE); 593 } 594 595 InvalidateRect(hWnd, &text_rect, TRUE); 596 InvalidateRect(hWnd, &text2_rect, TRUE); 597 break; 598 599 case ID_ABOUT: 600 LoadStringW(hInst, IDS_APP_TITLE, szAppName, _countof(szAppName)); 601 hIcon = LoadIconW(hInst, MAKEINTRESOURCEW(IDI_REACTOS_SNDREC32)); 602 ShellAboutW(hWnd, szAppName, NULL, hIcon); 603 DestroyIcon(hIcon); 604 break; 605 606 case ID_FILE_SAVEAS: 607 ZeroMemory(&ofn, sizeof(ofn)); 608 609 ofn.lStructSize = sizeof(ofn); 610 ofn.hwndOwner = hWnd ; 611 ofn.Flags = OFN_OVERWRITEPROMPT; 612 ofn.lpstrFilter = TEXT("Audio Files (*.wav)\0*.wav\0All Files (*.*)\0*.*\0"); 613 ofn.lpstrFile = file_path; 614 ofn.nMaxFile = MAX_PATH; 615 616 ofn.lpstrDefExt = TEXT("wav"); 617 618 if (GetSaveFileName (&ofn)) 619 { 620 write_wav(file_path); 621 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVE, MF_ENABLED); 622 } 623 break; 624 625 626 case ID_EDIT_AUDIOPROPS: 627 ShellExecute(NULL, NULL, _T("rundll32.exe"), _T("shell32.dll,Control_RunDLL mmsys.cpl,ShowAudioPropertySheet"), NULL, SW_SHOWNORMAL); 628 break; 629 630 case ID_FILE_EXIT: 631 DestroyWindow(hWnd); 632 break; 633 634 /* Sndrec32 buttons routines */ 635 case BUTSTART_ID: 636 AUD_BUF->set_position_start(); 637 slider_pos = 0; 638 SendMessage(slider, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)slider_pos); 639 break; 640 641 case BUTEND_ID: 642 DestroyWindow(hWnd); 643 break; 644 645 case BUTPLAY_ID: 646 if (wout_first == false) 647 { 648 AUD_OUT->open(); 649 wout_first = true; 650 } 651 652 AUD_OUT->play(); 653 654 disable_but(BUTSTART_ID); 655 disable_but(BUTEND_ID); 656 disable_but(BUTREC_ID); 657 disable_but(BUTPLAY_ID); 658 659 SetTimer(hWnd, 1, 250, 0); 660 SetTimer(hWnd, WAVEBAR_TIMERID, WAVEBAR_TIMERTIME, 0); 661 662 break; 663 664 case BUTSTOP_ID: 665 if (s_recording) 666 { 667 s_recording = FALSE; 668 669 AUD_IN->stop_recording(); 670 671 /* Resetting slider position */ 672 slider_pos = 0; 673 SendMessage(slider, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)slider_pos); 674 675 samples_max = AUD_BUF->samples_received(); 676 677 EnableMenuItem((HMENU)IDR_MENU1, ID_FILE_SAVEAS, MF_ENABLED); 678 679 enable_but(BUTSTART_ID); 680 enable_but(BUTEND_ID); 681 enable_but(BUTREC_ID); 682 enable_but(BUTPLAY_ID); 683 684 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVEAS, MF_ENABLED); 685 EnableWindow(slider, TRUE); 686 687 display_dur = FALSE; 688 689 AUD_BUF->truncate(); 690 691 InvalidateRect(hWnd, &text_rect, TRUE); 692 InvalidateRect(wave_win, 0, TRUE); 693 694 } 695 else 696 { 697 AUD_OUT->pause(); 698 699 enable_but(BUTSTART_ID); 700 enable_but(BUTEND_ID); 701 enable_but(BUTREC_ID); 702 enable_but(BUTPLAY_ID); 703 704 } 705 706 KillTimer(hWnd, 1); 707 KillTimer(hWnd, WAVEBAR_TIMERID); 708 709 InvalidateRect(hWnd, &text_rect, TRUE); 710 711 break; 712 713 case BUTREC_ID: 714 if (win_first == false) 715 { 716 AUD_IN->open(); 717 win_first = true; 718 } 719 720 s_recording = TRUE; 721 722 samples_max = AUD_BUF->total_samples(); 723 724 AUD_IN->start_recording(); 725 726 enable_but(BUTSTOP_ID); 727 728 disable_but(BUTSTART_ID); 729 disable_but(BUTEND_ID); 730 disable_but(BUTREC_ID); 731 disable_but(BUTPLAY_ID); 732 733 isnew = FALSE; 734 735 EnableWindow(slider, FALSE); 736 737 SetTimer(hWnd, 1, 150, 0); 738 SetTimer(hWnd, WAVEBAR_TIMERID, WAVEBAR_TIMERTIME, 0); 739 740 break; 741 742 default: 743 return DefWindowProc(hWnd, message, wParam, lParam); 744 } 745 break; 746 747 case WM_TIMER: 748 switch (wParam) 749 { 750 case 1: 751 if (stopped_flag) 752 { 753 KillTimer(hWnd, 1); 754 KillTimer(hWnd, WAVEBAR_TIMERID); 755 slider_pos = 0; 756 enable_but(BUTPLAY_ID); 757 stopped_flag = FALSE; 758 } 759 760 SendMessage(slider, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)slider_pos); 761 InvalidateRect(hWnd, &text_rect, TRUE); 762 break; 763 764 case WAVEBAR_TIMERID: 765 InvalidateRect(wave_win, 0, TRUE); 766 SendMessage(wave_win, WM_USER, 0, 0); 767 break; 768 } 769 break; 770 771 case WM_PAINT: 772 hdc = BeginPaint(hWnd, &ps); 773 font = CreateFontIndirect(&s_info.lfMenuFont); 774 oldfont = (HFONT) SelectObject(hdc, font); 775 SetBkMode(hdc, TRANSPARENT); 776 777 if (AUD_IN->current_status() == snd::WAVEIN_RECORDING) 778 { 779 gprintf(str_tmp, 780 MAX_LOADSTRING, 781 str_pos, 782 (float)((float)AUD_BUF->bytes_recorded() / (float)AUD_BUF->audinfo().byte_rate())); 783 784 } 785 else if (AUD_OUT->current_status() == snd::WAVEOUT_PLAYING) 786 { 787 gprintf(str_tmp, 788 MAX_LOADSTRING, 789 str_pos, 790 (float)((float)AUD_BUF->bytes_played() / (float)AUD_BUF->audinfo().byte_rate())); 791 } 792 else 793 { 794 gprintf(str_tmp, 795 MAX_LOADSTRING, 796 str_pos, 797 (float)((((float)slider_pos * (float)samples_max) / (float)slider_max) / (float)AUD_BUF->audinfo().sample_rate())); 798 } 799 800 ExtTextOut(hdc, 801 STRPOS_X, 802 STRPOS_Y, 803 0, 804 0, 805 str_tmp, 806 _tcslen(str_tmp), 807 0); 808 809 if (display_dur) 810 { 811 gprintf(str_tmp, 812 MAX_LOADSTRING, 813 str_dur, 814 AUD_BUF->fseconds_total()); 815 } 816 else 817 { 818 gprintf(str_tmp, 819 MAX_LOADSTRING, 820 str_dur, 821 AUD_BUF->fseconds_recorded()); 822 } 823 824 ExtTextOut(hdc, 825 STRDUR_X, 826 STRDUR_Y, 827 0, 828 0, 829 str_tmp, 830 _tcslen(str_tmp), 831 0); 832 833 gprintf(str_tmp, 834 MAX_LOADSTRING, 835 str_buf, 836 (float)((float)AUD_BUF->mem_size() / 1024.0f)); 837 838 ExtTextOut(hdc, 839 STRBUF_X, 840 STRBUF_Y, 841 0, 842 0, 843 str_tmp, 844 _tcslen(str_tmp), 845 0); 846 847 gprintf(str_tmp, 848 MAX_LOADSTRING, 849 str_fmt, 850 (float)((float)AUD_BUF->audinfo().sample_rate() / 1000.0f), 851 AUD_BUF->audinfo().bits(), 852 AUD_BUF->audinfo().channels() == 2 ? str_mono : str_stereo); 853 854 ExtTextOut(hdc, 855 STRFMT_X, 856 STRFMT_Y, 857 0, 858 0, 859 str_tmp, 860 _tcslen(str_tmp), 861 0); 862 863 gprintf(str_tmp, 864 MAX_LOADSTRING, 865 str_chan, 866 AUD_BUF->audinfo().channels() == 2 ? str_stereo : str_mono); 867 868 ExtTextOut(hdc, 869 STRCHAN_X, 870 STRCHAN_Y, 871 0, 872 0, 873 str_tmp, 874 _tcslen(str_tmp), 875 0); 876 877 SelectObject(hdc, oldfont); 878 DeleteObject(font); 879 EndPaint(hWnd, &ps); 880 break; 881 882 case WM_DESTROY: 883 PostQuitMessage(0); 884 break; 885 default: 886 return DefWindowProc(hWnd, message, wParam, lParam); 887 } 888 889 return 0; 890 } 891 892 void l_play_finished(void) 893 { 894 stopped_flag = true; 895 896 enable_but(BUTSTART_ID); 897 enable_but(BUTEND_ID); 898 enable_but(BUTREC_ID); 899 enable_but(BUTPLAY_ID); 900 901 InvalidateRect(wave_win, 0, TRUE); 902 } 903 904 void l_audio_arrival(unsigned int samples_arrival) 905 { 906 slider_pos += (DWORD)((slider_max * samples_arrival) / samples_max); 907 } 908 909 void l_buffer_resized(unsigned int new_size) 910 { 911 } 912 913 VOID enable_but(DWORD id) 914 { 915 butdisabled[id] = FALSE; 916 SendMessage(buttons[id], BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)butbmps[id]); 917 } 918 919 VOID disable_but(DWORD id) 920 { 921 butdisabled[id] = TRUE; 922 SendMessage(buttons[id], BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)butbmps_dis[id]); 923 } 924 925 BOOL open_wav(TCHAR *f) 926 { 927 HANDLE file; 928 929 riff_hdr r; 930 wave_hdr w; 931 data_chunk d; 932 933 BOOL b; 934 935 DWORD bytes_recorded_in_wav = 0; 936 DWORD is_read = 0; 937 938 file = CreateFile(f, 939 GENERIC_READ, 940 0, 941 0, 942 OPEN_EXISTING, 943 FILE_ATTRIBUTE_NORMAL, 944 0); 945 if (!file) 946 { 947 MessageBox(main_win, 948 TEXT("Cannot open file. CreateFile() error."), 949 TEXT("ERROR"), 950 MB_OK | MB_ICONERROR); 951 952 return FALSE; 953 } 954 955 b = ReadFile(file, (LPVOID)&r, sizeof(r), &is_read, 0); 956 if (!b) 957 { 958 MessageBox(main_win, 959 TEXT("Cannot read RIFF header."), 960 TEXT("ERROR"), 961 MB_OK | MB_ICONERROR); 962 963 CloseHandle(file); 964 return FALSE; 965 } 966 967 b = ReadFile(file, (LPVOID)&w, sizeof(w), &is_read, 0); 968 if (!b) 969 { 970 MessageBox(main_win, 971 TEXT("Cannot read WAVE header."), 972 TEXT("ERROR"), 973 MB_OK | MB_ICONERROR); 974 975 CloseHandle(file); 976 return FALSE; 977 } 978 979 b = ReadFile(file, (LPVOID)&d, sizeof(d), &is_read, 0); 980 if (!b) 981 { 982 MessageBox(main_win, 983 TEXT("Cannot read WAVE subchunk."), 984 TEXT("ERROR"), 985 MB_OK | MB_ICONERROR); 986 987 CloseHandle(file); 988 return FALSE; 989 } 990 991 bytes_recorded_in_wav = r.chunksize - 36; 992 if (bytes_recorded_in_wav == 0) 993 { 994 MessageBox(main_win, 995 TEXT("Cannot read file. No audio data."), 996 TEXT("ERROR"), 997 MB_OK | MB_ICONERROR); 998 999 CloseHandle(file); 1000 return FALSE; 1001 } 1002 1003 snd::audio_format openfmt(w.SampleRate, w.BitsPerSample, w.NumChannels); 1004 1005 AUD_BUF->clear(); 1006 AUD_BUF->alloc_bytes(bytes_recorded_in_wav); 1007 1008 b = ReadFile(file, 1009 (LPVOID)AUD_BUF->audio_buffer(), 1010 bytes_recorded_in_wav, 1011 &is_read, 1012 0); 1013 1014 AUD_BUF->set_b_received(bytes_recorded_in_wav); 1015 1016 if ((!b) || (is_read != bytes_recorded_in_wav)) 1017 { 1018 MessageBox(main_win, 1019 TEXT("Cannot read file. Error reading audio data."), 1020 TEXT("ERROR"), 1021 MB_OK | MB_ICONERROR); 1022 1023 CloseHandle(file); 1024 1025 AUD_BUF->reset(); 1026 return FALSE; 1027 } 1028 1029 CloseHandle(file); 1030 1031 enable_but(BUTPLAY_ID); 1032 enable_but(BUTSTOP_ID); 1033 enable_but(BUTSTART_ID); 1034 enable_but(BUTEND_ID); 1035 enable_but(BUTREC_ID); 1036 1037 samples_max = AUD_BUF->samples_received(); 1038 1039 isnew = FALSE; 1040 1041 return TRUE; 1042 } 1043 1044 BOOL 1045 write_wav(TCHAR *f) 1046 { 1047 HANDLE file; 1048 DWORD written; 1049 BOOL is_writ; 1050 int i; 1051 riff_hdr r; 1052 wave_hdr w; 1053 data_chunk d; 1054 1055 file = CreateFile(f, GENERIC_WRITE, 0, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); 1056 if (!file) 1057 { 1058 i = MessageBox(main_win, 1059 TEXT("File already exist. Overwrite it?"), 1060 TEXT("Warning"), 1061 MB_YESNO | MB_ICONQUESTION); 1062 1063 if (i == IDYES) 1064 { 1065 file = CreateFile(f, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); 1066 if (!file) 1067 { 1068 MessageBox(main_win, 1069 TEXT("File Error, CreateFile() failed."), 1070 TEXT("ERROR"), 1071 MB_OK | MB_ICONERROR); 1072 1073 return FALSE; 1074 } 1075 1076 } else 1077 return FALSE; 1078 } 1079 1080 r.magic = 0x46464952; 1081 r.format = 0x45564157; 1082 r.chunksize = 36 + AUD_BUF->bytes_recorded(); 1083 1084 w.Subchunkid = 0x20746d66; 1085 w.Subchunk1Size = 16; 1086 w.AudioFormat = 1; 1087 w.NumChannels = AUD_BUF->audinfo().channels(); 1088 w.SampleRate = AUD_BUF->audinfo().sample_rate(); 1089 w.ByteRate = AUD_BUF->audinfo().byte_rate(); 1090 w.BlockAlign = AUD_BUF->audinfo().block_align(); 1091 w.BitsPerSample = AUD_BUF->audinfo().bits(); 1092 1093 d.subc = 0x61746164; 1094 d.subc_size = AUD_BUF->bytes_recorded(); 1095 1096 /* Writing headers */ 1097 is_writ = WriteFile(file, (LPCVOID)&r, sizeof(r), &written, 0); 1098 if (!is_writ) 1099 { 1100 MessageBox(main_win, 1101 TEXT("File Error, WriteFile() failed."), 1102 TEXT("ERROR"), 1103 MB_OK | MB_ICONERROR); 1104 1105 CloseHandle(file); 1106 return FALSE; 1107 } 1108 1109 is_writ = WriteFile(file, (LPCVOID)&w, sizeof(w), &written, 0); 1110 if (!is_writ) 1111 { 1112 MessageBox(main_win, 1113 TEXT("File Error, WriteFile() failed."), 1114 TEXT("ERROR"), 1115 MB_OK | MB_ICONERROR); 1116 1117 CloseHandle(file); 1118 return FALSE; 1119 } 1120 1121 is_writ = WriteFile(file, (LPCVOID)&d, sizeof(d), &written, 0); 1122 if (!is_writ) 1123 { 1124 MessageBox(main_win, 1125 TEXT("File Error, WriteFile() failed."), 1126 TEXT("ERROR"), 1127 MB_OK | MB_ICONERROR); 1128 1129 CloseHandle(file); 1130 return FALSE; 1131 } 1132 1133 is_writ = WriteFile(file, 1134 (LPCVOID)AUD_BUF->audio_buffer(), 1135 AUD_BUF->bytes_recorded(), 1136 &written, 1137 0); 1138 if (!is_writ) 1139 { 1140 MessageBox(main_win, 1141 TEXT("File Error, WriteFile() failed."), 1142 TEXT("ERROR"), 1143 MB_OK | MB_ICONERROR); 1144 1145 CloseHandle(file); 1146 return FALSE; 1147 } 1148 1149 CloseHandle(file); 1150 return TRUE; 1151 } 1152