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 436 /* Checking for global pointers to buffer and io audio devices */ 437 if ((!AUD_IN) || (!AUD_OUT) || (!AUD_BUF)) 438 { 439 MessageBox(0, TEXT("Buffer Error"), 0, 0); 440 return 1; 441 } 442 443 switch (message) 444 { 445 case WM_CREATE: 446 /* Creating the wave bar */ 447 if (!InitInstance_wave(hWnd, hInst, SW_SHOWNORMAL)) 448 { 449 MessageBox(0, TEXT("InitInstance_wave() Error!"), TEXT("ERROR"), MB_ICONERROR); 450 return FALSE; 451 } 452 453 /* Creating ALL the buttons */ 454 for (int i = 0; i < 5; ++i) 455 { 456 buttons[i] = CreateWindow(TEXT("button"), 457 TEXT(""), 458 WS_CHILD | WS_VISIBLE | BS_BITMAP, 459 BUTTONS_CX + (i * (BUTTONS_W + ((i == 0) ? 0 : BUTTONS_SPACE))), 460 BUTTONS_CY, 461 BUTTONS_W, 462 BUTTONS_H, 463 hWnd, 464 (HMENU)UlongToPtr(i), 465 hInst, 466 0); 467 if (!buttons[i]) 468 { 469 MessageBox(0, 0, TEXT("CreateWindow() Error!"), 0); 470 return FALSE; 471 } 472 473 /* Realize the button bmp image */ 474 SendMessage(buttons[i], BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)butbmps[i]); 475 UpdateWindow(buttons[i]); 476 disable_but(i); 477 } 478 479 /* Creating the SLIDER window */ 480 slider = CreateWindow(TRACKBAR_CLASS, 481 TEXT(""), 482 WS_CHILD | WS_VISIBLE | TBS_NOTICKS | TBS_HORZ | TBS_ENABLESELRANGE, 483 SLIDER_CX, 484 SLIDER_CY, 485 SLIDER_W, 486 SLIDER_H, 487 hWnd, 488 (HMENU)SLIDER_ID, 489 hInst, 490 0); 491 if (!slider) 492 { 493 MessageBox(0, 0, TEXT( "CreateWindow() Error!" ), 0); 494 return FALSE; 495 } 496 497 /* Sets slider limits */ 498 SendMessage(slider, 499 TBM_SETRANGE, 500 (WPARAM)TRUE, 501 (LPARAM)MAKELONG(slider_min, slider_max)); 502 503 UpdateWindow(slider); 504 enable_but(BUTREC_ID); 505 EnableWindow(slider, FALSE); 506 break; 507 508 /* Implements slider logic */ 509 case WM_HSCROLL: 510 { 511 switch (LOWORD(wParam)) 512 { 513 case SB_ENDSCROLL: 514 break; 515 case SB_PAGERIGHT: 516 case SB_PAGELEFT: 517 case TB_THUMBTRACK: 518 /* If the user touch the slider bar, set the 519 audio start position properly */ 520 slider_pos = SendMessage(slider, TBM_GETPOS, 0, 0); 521 slid_samp = (__int64)slider_pos * (__int64)samples_max; 522 AUD_BUF->set_position(AUD_BUF->audinfo().bytes_in_samples((unsigned int)(slid_samp / (__int64)slider_max))); 523 InvalidateRect(hWnd, &text_rect, TRUE); 524 break; 525 } 526 break; 527 } 528 529 case WM_COMMAND: 530 wmId = LOWORD(wParam); 531 if ((wmId >= 0) && (wmId < 5) && (butdisabled[wmId] != FALSE)) 532 break; 533 534 switch (wmId) 535 { 536 case ID_FILE_NEW: 537 if (!isnew) 538 { 539 if (AUD_IN->current_status() == snd::WAVEIN_RECORDING) 540 AUD_IN->stop_recording(); 541 542 if ((AUD_OUT->current_status() == snd::WAVEOUT_PLAYING) || 543 (AUD_OUT->current_status() == snd::WAVEOUT_PAUSED)) 544 AUD_OUT->stop(); 545 546 AUD_BUF->reset(); 547 548 enable_but(BUTREC_ID); 549 disable_but(BUTSTART_ID); 550 disable_but(BUTEND_ID); 551 disable_but(BUTSTOP_ID); 552 disable_but(BUTPLAY_ID); 553 554 samples_max = AUD_BUF->total_samples(); 555 slider_pos = 0; 556 557 SendMessage(slider, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) slider_pos); 558 559 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVEAS, MF_GRAYED); 560 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVE, MF_GRAYED); 561 562 isnew = TRUE; 563 display_dur = TRUE; 564 565 ZeroMemory(file_path, MAX_PATH * sizeof(TCHAR)); 566 567 EnableWindow(slider, FALSE); 568 569 InvalidateRect(hWnd, &text_rect, TRUE); 570 InvalidateRect(hWnd, &text2_rect, TRUE); 571 } 572 break; 573 574 case ID_FILE_OPEN: 575 ZeroMemory(&ofn, sizeof(ofn)); 576 577 ofn.lStructSize = sizeof(ofn); 578 ofn.hwndOwner = hWnd; 579 ofn.lpstrFilter = TEXT("Audio Files (*.wav)\0*.wav\0All Files (*.*)\0*.*\0"); 580 ofn.lpstrFile = file_path; 581 ofn.nMaxFile = MAX_PATH; 582 ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; 583 ofn.lpstrDefExt = TEXT("wav"); 584 585 if (GetOpenFileName(&ofn)) 586 { 587 open_wav(file_path); 588 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVE, MF_ENABLED); 589 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVEAS, MF_ENABLED); 590 591 EnableWindow(slider, TRUE); 592 } 593 594 InvalidateRect(hWnd, &text_rect, TRUE); 595 InvalidateRect(hWnd, &text2_rect, TRUE); 596 break; 597 598 case ID_ABOUT: 599 LoadStringW(hInst, IDS_APP_TITLE, szAppName, _countof(szAppName)); 600 ShellAboutW(hWnd, szAppName, NULL, 601 LoadIconW(hInst, MAKEINTRESOURCEW(IDI_REACTOS_SNDREC32))); 602 break; 603 604 case ID_FILE_SAVEAS: 605 ZeroMemory(&ofn, sizeof(ofn)); 606 607 ofn.lStructSize = sizeof(ofn); 608 ofn.hwndOwner = hWnd ; 609 ofn.Flags = OFN_OVERWRITEPROMPT; 610 ofn.lpstrFilter = TEXT("Audio Files (*.wav)\0*.wav\0All Files (*.*)\0*.*\0"); 611 ofn.lpstrFile = file_path; 612 ofn.nMaxFile = MAX_PATH; 613 614 ofn.lpstrDefExt = TEXT("wav"); 615 616 if (GetSaveFileName (&ofn)) 617 { 618 write_wav(file_path); 619 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVE, MF_ENABLED); 620 } 621 break; 622 623 624 case ID_EDIT_AUDIOPROPS: 625 ShellExecute(NULL, NULL, _T("rundll32.exe"), _T("shell32.dll,Control_RunDLL mmsys.cpl,ShowAudioPropertySheet"), NULL, SW_SHOWNORMAL); 626 break; 627 628 case ID_FILE_EXIT: 629 DestroyWindow(hWnd); 630 break; 631 632 /* Sndrec32 buttons routines */ 633 case BUTSTART_ID: 634 AUD_BUF->set_position_start(); 635 slider_pos = 0; 636 SendMessage(slider, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)slider_pos); 637 break; 638 639 case BUTEND_ID: 640 DestroyWindow(hWnd); 641 break; 642 643 case BUTPLAY_ID: 644 if (wout_first == false) 645 { 646 AUD_OUT->open(); 647 wout_first = true; 648 } 649 650 AUD_OUT->play(); 651 652 disable_but(BUTSTART_ID); 653 disable_but(BUTEND_ID); 654 disable_but(BUTREC_ID); 655 disable_but(BUTPLAY_ID); 656 657 SetTimer(hWnd, 1, 250, 0); 658 SetTimer(hWnd, WAVEBAR_TIMERID, WAVEBAR_TIMERTIME, 0); 659 660 break; 661 662 case BUTSTOP_ID: 663 if (s_recording) 664 { 665 s_recording = FALSE; 666 667 AUD_IN->stop_recording(); 668 669 /* Resetting slider position */ 670 slider_pos = 0; 671 SendMessage(slider, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)slider_pos); 672 673 samples_max = AUD_BUF->samples_received(); 674 675 EnableMenuItem((HMENU)IDR_MENU1, ID_FILE_SAVEAS, MF_ENABLED); 676 677 enable_but(BUTSTART_ID); 678 enable_but(BUTEND_ID); 679 enable_but(BUTREC_ID); 680 enable_but(BUTPLAY_ID); 681 682 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVEAS, MF_ENABLED); 683 EnableWindow(slider, TRUE); 684 685 display_dur = FALSE; 686 687 AUD_BUF->truncate(); 688 689 InvalidateRect(hWnd, &text_rect, TRUE); 690 InvalidateRect(wave_win, 0, TRUE); 691 692 } 693 else 694 { 695 AUD_OUT->pause(); 696 697 enable_but(BUTSTART_ID); 698 enable_but(BUTEND_ID); 699 enable_but(BUTREC_ID); 700 enable_but(BUTPLAY_ID); 701 702 } 703 704 KillTimer(hWnd, 1); 705 KillTimer(hWnd, WAVEBAR_TIMERID); 706 707 InvalidateRect(hWnd, &text_rect, TRUE); 708 709 break; 710 711 case BUTREC_ID: 712 if (win_first == false) 713 { 714 AUD_IN->open(); 715 win_first = true; 716 } 717 718 s_recording = TRUE; 719 720 samples_max = AUD_BUF->total_samples(); 721 722 AUD_IN->start_recording(); 723 724 enable_but(BUTSTOP_ID); 725 726 disable_but(BUTSTART_ID); 727 disable_but(BUTEND_ID); 728 disable_but(BUTREC_ID); 729 disable_but(BUTPLAY_ID); 730 731 isnew = FALSE; 732 733 EnableWindow(slider, FALSE); 734 735 SetTimer(hWnd, 1, 150, 0); 736 SetTimer(hWnd, WAVEBAR_TIMERID, WAVEBAR_TIMERTIME, 0); 737 738 break; 739 740 default: 741 return DefWindowProc(hWnd, message, wParam, lParam); 742 } 743 break; 744 745 case WM_TIMER: 746 switch (wParam) 747 { 748 case 1: 749 if (stopped_flag) 750 { 751 KillTimer(hWnd, 1); 752 KillTimer(hWnd, WAVEBAR_TIMERID); 753 slider_pos = 0; 754 enable_but(BUTPLAY_ID); 755 stopped_flag = FALSE; 756 } 757 758 SendMessage(slider, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)slider_pos); 759 InvalidateRect(hWnd, &text_rect, TRUE); 760 break; 761 762 case WAVEBAR_TIMERID: 763 InvalidateRect(wave_win, 0, TRUE); 764 SendMessage(wave_win, WM_USER, 0, 0); 765 break; 766 } 767 break; 768 769 case WM_PAINT: 770 hdc = BeginPaint(hWnd, &ps); 771 font = CreateFontIndirect(&s_info.lfMenuFont); 772 oldfont = (HFONT) SelectObject(hdc, font); 773 SetBkMode(hdc, TRANSPARENT); 774 775 if (AUD_IN->current_status() == snd::WAVEIN_RECORDING) 776 { 777 gprintf(str_tmp, 778 MAX_LOADSTRING, 779 str_pos, 780 (float)((float)AUD_BUF->bytes_recorded() / (float)AUD_BUF->audinfo().byte_rate())); 781 782 } 783 else if (AUD_OUT->current_status() == snd::WAVEOUT_PLAYING) 784 { 785 gprintf(str_tmp, 786 MAX_LOADSTRING, 787 str_pos, 788 (float)((float)AUD_BUF->bytes_played() / (float)AUD_BUF->audinfo().byte_rate())); 789 } 790 else 791 { 792 gprintf(str_tmp, 793 MAX_LOADSTRING, 794 str_pos, 795 (float)((((float)slider_pos * (float)samples_max) / (float)slider_max) / (float)AUD_BUF->audinfo().sample_rate())); 796 } 797 798 ExtTextOut(hdc, 799 STRPOS_X, 800 STRPOS_Y, 801 0, 802 0, 803 str_tmp, 804 _tcslen(str_tmp), 805 0); 806 807 if (display_dur) 808 { 809 gprintf(str_tmp, 810 MAX_LOADSTRING, 811 str_dur, 812 AUD_BUF->fseconds_total()); 813 } 814 else 815 { 816 gprintf(str_tmp, 817 MAX_LOADSTRING, 818 str_dur, 819 AUD_BUF->fseconds_recorded()); 820 } 821 822 ExtTextOut(hdc, 823 STRDUR_X, 824 STRDUR_Y, 825 0, 826 0, 827 str_tmp, 828 _tcslen(str_tmp), 829 0); 830 831 gprintf(str_tmp, 832 MAX_LOADSTRING, 833 str_buf, 834 (float)((float)AUD_BUF->mem_size() / 1024.0f)); 835 836 ExtTextOut(hdc, 837 STRBUF_X, 838 STRBUF_Y, 839 0, 840 0, 841 str_tmp, 842 _tcslen(str_tmp), 843 0); 844 845 gprintf(str_tmp, 846 MAX_LOADSTRING, 847 str_fmt, 848 (float)((float)AUD_BUF->audinfo().sample_rate() / 1000.0f), 849 AUD_BUF->audinfo().bits(), 850 AUD_BUF->audinfo().channels() == 2 ? str_mono : str_stereo); 851 852 ExtTextOut(hdc, 853 STRFMT_X, 854 STRFMT_Y, 855 0, 856 0, 857 str_tmp, 858 _tcslen(str_tmp), 859 0); 860 861 gprintf(str_tmp, 862 MAX_LOADSTRING, 863 str_chan, 864 AUD_BUF->audinfo().channels() == 2 ? str_stereo : str_mono); 865 866 ExtTextOut(hdc, 867 STRCHAN_X, 868 STRCHAN_Y, 869 0, 870 0, 871 str_tmp, 872 _tcslen(str_tmp), 873 0); 874 875 SelectObject(hdc, oldfont); 876 DeleteObject(font); 877 EndPaint(hWnd, &ps); 878 break; 879 880 case WM_DESTROY: 881 PostQuitMessage(0); 882 break; 883 default: 884 return DefWindowProc(hWnd, message, wParam, lParam); 885 } 886 887 return 0; 888 } 889 890 void l_play_finished(void) 891 { 892 stopped_flag = true; 893 894 enable_but(BUTSTART_ID); 895 enable_but(BUTEND_ID); 896 enable_but(BUTREC_ID); 897 enable_but(BUTPLAY_ID); 898 899 InvalidateRect(wave_win, 0, TRUE); 900 } 901 902 void l_audio_arrival(unsigned int samples_arrival) 903 { 904 slider_pos += (DWORD)((slider_max * samples_arrival) / samples_max); 905 } 906 907 void l_buffer_resized(unsigned int new_size) 908 { 909 } 910 911 VOID enable_but(DWORD id) 912 { 913 butdisabled[id] = FALSE; 914 SendMessage(buttons[id], BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)butbmps[id]); 915 } 916 917 VOID disable_but(DWORD id) 918 { 919 butdisabled[id] = TRUE; 920 SendMessage(buttons[id], BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)butbmps_dis[id]); 921 } 922 923 BOOL open_wav(TCHAR *f) 924 { 925 HANDLE file; 926 927 riff_hdr r; 928 wave_hdr w; 929 data_chunk d; 930 931 BOOL b; 932 933 DWORD bytes_recorded_in_wav = 0; 934 DWORD is_read = 0; 935 936 file = CreateFile(f, 937 GENERIC_READ, 938 0, 939 0, 940 OPEN_EXISTING, 941 FILE_ATTRIBUTE_NORMAL, 942 0); 943 if (!file) 944 { 945 MessageBox(main_win, 946 TEXT("Cannot open file. CreateFile() error."), 947 TEXT("ERROR"), 948 MB_OK | MB_ICONERROR); 949 950 return FALSE; 951 } 952 953 b = ReadFile(file, (LPVOID)&r, sizeof(r), &is_read, 0); 954 if (!b) 955 { 956 MessageBox(main_win, 957 TEXT("Cannot read RIFF header."), 958 TEXT("ERROR"), 959 MB_OK | MB_ICONERROR); 960 961 CloseHandle(file); 962 return FALSE; 963 } 964 965 b = ReadFile(file, (LPVOID)&w, sizeof(w), &is_read, 0); 966 if (!b) 967 { 968 MessageBox(main_win, 969 TEXT("Cannot read WAVE header."), 970 TEXT("ERROR"), 971 MB_OK | MB_ICONERROR); 972 973 CloseHandle(file); 974 return FALSE; 975 } 976 977 b = ReadFile(file, (LPVOID)&d, sizeof(d), &is_read, 0); 978 if (!b) 979 { 980 MessageBox(main_win, 981 TEXT("Cannot read WAVE subchunk."), 982 TEXT("ERROR"), 983 MB_OK | MB_ICONERROR); 984 985 CloseHandle(file); 986 return FALSE; 987 } 988 989 bytes_recorded_in_wav = r.chunksize - 36; 990 if (bytes_recorded_in_wav == 0) 991 { 992 MessageBox(main_win, 993 TEXT("Cannot read file. No audio data."), 994 TEXT("ERROR"), 995 MB_OK | MB_ICONERROR); 996 997 CloseHandle(file); 998 return FALSE; 999 } 1000 1001 snd::audio_format openfmt(w.SampleRate, w.BitsPerSample, w.NumChannels); 1002 1003 AUD_BUF->clear(); 1004 AUD_BUF->alloc_bytes(bytes_recorded_in_wav); 1005 1006 b = ReadFile(file, 1007 (LPVOID)AUD_BUF->audio_buffer(), 1008 bytes_recorded_in_wav, 1009 &is_read, 1010 0); 1011 1012 AUD_BUF->set_b_received(bytes_recorded_in_wav); 1013 1014 if ((!b) || (is_read != bytes_recorded_in_wav)) 1015 { 1016 MessageBox(main_win, 1017 TEXT("Cannot read file. Error reading audio data."), 1018 TEXT("ERROR"), 1019 MB_OK | MB_ICONERROR); 1020 1021 CloseHandle(file); 1022 1023 AUD_BUF->reset(); 1024 return FALSE; 1025 } 1026 1027 CloseHandle(file); 1028 1029 enable_but(BUTPLAY_ID); 1030 enable_but(BUTSTOP_ID); 1031 enable_but(BUTSTART_ID); 1032 enable_but(BUTEND_ID); 1033 enable_but(BUTREC_ID); 1034 1035 samples_max = AUD_BUF->samples_received(); 1036 1037 isnew = FALSE; 1038 1039 return TRUE; 1040 } 1041 1042 BOOL 1043 write_wav(TCHAR *f) 1044 { 1045 HANDLE file; 1046 DWORD written; 1047 BOOL is_writ; 1048 int i; 1049 riff_hdr r; 1050 wave_hdr w; 1051 data_chunk d; 1052 1053 file = CreateFile(f, GENERIC_WRITE, 0, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); 1054 if (!file) 1055 { 1056 i = MessageBox(main_win, 1057 TEXT("File already exist. Overwrite it?"), 1058 TEXT("Warning"), 1059 MB_YESNO | MB_ICONQUESTION); 1060 1061 if (i == IDYES) 1062 { 1063 file = CreateFile(f, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); 1064 if (!file) 1065 { 1066 MessageBox(main_win, 1067 TEXT("File Error, CreateFile() failed."), 1068 TEXT("ERROR"), 1069 MB_OK | MB_ICONERROR); 1070 1071 return FALSE; 1072 } 1073 1074 } else 1075 return FALSE; 1076 } 1077 1078 r.magic = 0x46464952; 1079 r.format = 0x45564157; 1080 r.chunksize = 36 + AUD_BUF->bytes_recorded(); 1081 1082 w.Subchunkid = 0x20746d66; 1083 w.Subchunk1Size = 16; 1084 w.AudioFormat = 1; 1085 w.NumChannels = AUD_BUF->audinfo().channels(); 1086 w.SampleRate = AUD_BUF->audinfo().sample_rate(); 1087 w.ByteRate = AUD_BUF->audinfo().byte_rate(); 1088 w.BlockAlign = AUD_BUF->audinfo().block_align(); 1089 w.BitsPerSample = AUD_BUF->audinfo().bits(); 1090 1091 d.subc = 0x61746164; 1092 d.subc_size = AUD_BUF->bytes_recorded(); 1093 1094 /* Writing headers */ 1095 is_writ = WriteFile(file, (LPCVOID)&r, sizeof(r), &written, 0); 1096 if (!is_writ) 1097 { 1098 MessageBox(main_win, 1099 TEXT("File Error, WriteFile() failed."), 1100 TEXT("ERROR"), 1101 MB_OK | MB_ICONERROR); 1102 1103 CloseHandle(file); 1104 return FALSE; 1105 } 1106 1107 is_writ = WriteFile(file, (LPCVOID)&w, sizeof(w), &written, 0); 1108 if (!is_writ) 1109 { 1110 MessageBox(main_win, 1111 TEXT("File Error, WriteFile() failed."), 1112 TEXT("ERROR"), 1113 MB_OK | MB_ICONERROR); 1114 1115 CloseHandle(file); 1116 return FALSE; 1117 } 1118 1119 is_writ = WriteFile(file, (LPCVOID)&d, sizeof(d), &written, 0); 1120 if (!is_writ) 1121 { 1122 MessageBox(main_win, 1123 TEXT("File Error, WriteFile() failed."), 1124 TEXT("ERROR"), 1125 MB_OK | MB_ICONERROR); 1126 1127 CloseHandle(file); 1128 return FALSE; 1129 } 1130 1131 is_writ = WriteFile(file, 1132 (LPCVOID)AUD_BUF->audio_buffer(), 1133 AUD_BUF->bytes_recorded(), 1134 &written, 1135 0); 1136 if (!is_writ) 1137 { 1138 MessageBox(main_win, 1139 TEXT("File Error, WriteFile() failed."), 1140 TEXT("ERROR"), 1141 MB_OK | MB_ICONERROR); 1142 1143 CloseHandle(file); 1144 return FALSE; 1145 } 1146 1147 CloseHandle(file); 1148 return TRUE; 1149 } 1150