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