Merge my current work done on the kd++ branch:
[reactos.git] / reactos / base / applications / sndrec32 / sndrec32.cpp
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 */
7
8 #ifndef _UNICODE
9 #define gprintf _snprintf
10 #else
11 #define gprintf _snwprintf
12 #endif
13
14 #include "stdafx.h"
15 #include "sndrec32.h"
16
17 HINSTANCE hInst;
18 TCHAR szTitle[MAX_LOADSTRING];
19 TCHAR szWindowClass[MAX_LOADSTRING];
20
21
22 ATOM MyRegisterClass( HINSTANCE hInstance );
23 ATOM MyRegisterClass_wave( HINSTANCE hInstance );
24 BOOL InitInstance( HINSTANCE, int );
25 BOOL InitInstance_wave( HWND, HINSTANCE, int );
26 LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
27 LRESULT CALLBACK WndProc_wave( HWND, UINT, WPARAM, LPARAM );
28
29 BOOL win_first, wout_first;
30
31 HWND main_win;
32 HWND wave_win;
33 HWND slider;
34 HWND buttons[5];
35 HBITMAP butbmps[5];
36 HBITMAP butbmps_dis[5];
37 WNDPROC buttons_std_proc;
38
39 BOOL butdisabled[5];
40 BOOL stopped_flag;
41 BOOL isnew;
42 BOOL display_dur;
43
44
45 DWORD slider_pos;
46 WORD slider_min;
47 WORD slider_max;
48
49 DWORD samples_max;
50
51 OPENFILENAME ofn;
52 TCHAR file_path[MAX_PATH];
53 TCHAR str_pos[MAX_LOADSTRING];
54 TCHAR str_dur[MAX_LOADSTRING];
55 TCHAR str_buf[MAX_LOADSTRING];
56 TCHAR str_fmt[MAX_LOADSTRING];
57 TCHAR str_chan[MAX_LOADSTRING];
58
59 TCHAR str_mono[10];
60 TCHAR str_stereo[10];
61
62 BOOL path_set;
63
64 snd::audio_membuffer * AUD_BUF;
65 snd::audio_waveout * AUD_OUT;
66 snd::audio_wavein * AUD_IN;
67
68
69 BOOL s_recording;
70
71
72 NONCLIENTMETRICS s_info;
73
74
75 RECT text_rect;
76 RECT text2_rect;
77 RECT cli;
78
79
80 INT_PTR CALLBACK AboutDlgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
81 {
82 switch (msg)
83 {
84 case WM_COMMAND:
85 switch (LOWORD(wp))
86 {
87 case IDOK:
88 EndDialog(hWnd, 0);
89 return TRUE;
90 }
91 break;
92 case WM_CLOSE:
93 EndDialog(hWnd, 0);
94 return TRUE;
95 }
96 return FALSE;
97 }
98
99
100
101 int APIENTRY _tWinMain(HINSTANCE hInstance,
102 HINSTANCE hPrevInstance,
103 LPTSTR lpCmdLine,
104 int nCmdShow)
105 {
106
107 UNREFERENCED_PARAMETER(hPrevInstance);
108 UNREFERENCED_PARAMETER(lpCmdLine);
109
110
111 MSG msg;
112 HACCEL hAccelTable;
113
114 s_info.cbSize = sizeof( NONCLIENTMETRICS );
115
116 InitCommonControls();
117
118 win_first = wout_first = FALSE;
119
120 text_rect.left = REFRESHA_X;
121 text_rect.top = REFRESHA_Y;
122 text_rect.right = REFRESHA_CX;
123 text_rect.bottom = REFRESHA_CY;
124
125 text2_rect.left = REFRESHB_X;
126 text2_rect.top = REFRESHB_Y;
127 text2_rect.right = REFRESHB_CX;
128 text2_rect.bottom = REFRESHB_CY;
129
130 //
131 // Retrieving defaul system font, and others
132 // system informations.
133 //
134
135 SystemParametersInfo(
136 SPI_GETNONCLIENTMETRICS,
137 sizeof( NONCLIENTMETRICS ),
138 &s_info,
139 0
140 );
141
142 //
143 // Set font size
144 //
145
146 s_info.lfMenuFont.lfHeight = 14;
147
148 //
149 // Inits buttons bitmaps
150 //
151
152 butbmps[0] = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BITMAP2_START ));
153 butbmps[1] = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BITMAP2_END ));
154 butbmps[2] = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BITMAP2_PLAY ));
155 butbmps[3] = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BITMAP2_STOP ));
156 butbmps[4] = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BITMAP2_REC ));
157
158 butbmps_dis[0] = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BITMAP2_START_DIS ));
159 butbmps_dis[1] = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BITMAP2_END_DIS ));
160 butbmps_dis[2] = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BITMAP2_PLAY_DIS ));
161 butbmps_dis[3] = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BITMAP2_STOP_DIS ));
162 butbmps_dis[4] = LoadBitmap( hInstance, MAKEINTRESOURCE( IDB_BITMAP2_REC_DIS ));
163
164
165
166 //
167 // Inits audio devices and buffers
168 //
169
170 snd::audio_membuffer AUD_buffer( snd::A44100_16BIT_STEREO );
171 snd::audio_waveout AUD_waveout( snd::A44100_16BIT_STEREO, AUD_buffer );
172 snd::audio_wavein AUD_wavein( snd::A44100_16BIT_STEREO, AUD_buffer );
173
174 AUD_buffer.play_finished = l_play_finished;
175 AUD_buffer.audio_arrival = l_audio_arrival;
176 AUD_buffer.buffer_resized = l_buffer_resized;
177
178 AUD_buffer.alloc_seconds( INITIAL_BUFREC_SECONDS );
179
180 AUD_IN = &AUD_wavein;
181 AUD_OUT = &AUD_waveout;
182 AUD_BUF = &AUD_buffer;
183
184 //
185 // Inits slider default parameters
186 //
187
188 slider_pos = 0;
189 slider_min = 0;
190 slider_max = SLIDER_W;
191
192
193 stopped_flag = FALSE;
194 path_set = FALSE;
195 isnew = TRUE;
196 display_dur = TRUE;
197
198 samples_max = AUD_buffer.total_samples();
199
200 s_recording = false;
201
202 //
203 // Inits strings
204 //
205
206 LoadString( hInstance,
207 IDS_APP_TITLE, szTitle, MAX_LOADSTRING );
208
209 LoadString( hInstance,
210 IDC_REACTOS_SNDREC32, szWindowClass, MAX_LOADSTRING );
211
212
213 LoadString( hInstance,
214 IDS_STRPOS, str_pos, MAX_LOADSTRING );
215
216
217 LoadString( hInstance,
218 IDS_STRDUR, str_dur, MAX_LOADSTRING );
219
220 LoadString( hInstance,
221 IDS_STRBUF, str_buf, MAX_LOADSTRING );
222
223 LoadString( hInstance,
224 IDS_STRFMT, str_fmt, MAX_LOADSTRING );
225
226 LoadString( hInstance,
227 IDS_STRCHAN, str_chan, MAX_LOADSTRING );
228
229 LoadString( hInstance,
230 IDS_STRMONO, str_mono, 10 );
231
232 LoadString( hInstance,
233 IDS_STRSTEREO, str_stereo, 10 );
234
235
236 //
237 // Registers sndrec32 window class
238 //
239
240 MyRegisterClass( hInstance );
241
242 MyRegisterClass_wave( hInstance );
243
244
245 if ( !InitInstance( hInstance, nCmdShow ))
246 {
247 MessageBox( 0, TEXT( "CreateWindow() Error!" ), TEXT( "ERROR" ), MB_ICONERROR );
248 return FALSE;
249 }
250
251 //
252 // Loads key accelerators
253 //
254
255 hAccelTable = LoadAccelerators(hInstance,
256 MAKEINTRESOURCE( IDC_REACTOS_SNDREC32 ));
257
258
259
260 //
261 // Starts main loop
262 //
263
264 while ( GetMessage( &msg, NULL, 0, 0 ))
265 {
266 if ( !TranslateAccelerator( msg.hwnd, hAccelTable, &msg ))
267 {
268 TranslateMessage( &msg );
269 DispatchMessage( &msg );
270 }
271 }
272
273 if ( wout_first )
274 {
275 AUD_waveout.close();
276
277 }
278
279
280 if ( win_first )
281 {
282 AUD_wavein.close();
283
284 }
285
286 AUD_buffer.clear();
287
288 return ( int )msg.wParam;
289 }
290
291
292
293
294 ATOM
295 MyRegisterClass( HINSTANCE hInstance )
296 {
297 WNDCLASSEX wcex;
298
299 wcex.cbSize = sizeof(WNDCLASSEX);
300
301 wcex.style = CS_HREDRAW | CS_VREDRAW;
302 wcex.lpfnWndProc = WndProc;
303 wcex.cbClsExtra = 0;
304 wcex.cbWndExtra = 0;
305 wcex.hInstance = hInstance;
306 wcex.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE( IDI_SNDREC32 ));
307 wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
308 wcex.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
309 wcex.lpszMenuName = MAKEINTRESOURCE( IDR_MENU1 );
310 wcex.lpszClassName = szWindowClass;
311 wcex.hIconSm = LoadIcon( wcex.hInstance, MAKEINTRESOURCE( IDI_SNDREC32 ));
312
313
314 return RegisterClassEx( &wcex );
315 }
316
317 BOOL
318 InitInstance( HINSTANCE hInstance, int nCmdShow )
319 {
320 HWND hWnd;
321
322 hInst = hInstance;
323
324 hWnd = CreateWindow(
325 szWindowClass,
326 szTitle,
327 WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
328 CW_USEDEFAULT,
329 CW_USEDEFAULT,
330 MAINWINDOW_W,
331 MAINWINDOW_H,
332 NULL, NULL,
333 hInstance, NULL
334 );
335
336 if (!hWnd)
337 {
338 return FALSE;
339 }
340
341 ShowWindow(hWnd, nCmdShow);
342 UpdateWindow(hWnd);
343
344 main_win = hWnd;
345
346
347 return TRUE;
348 }
349
350
351
352
353
354 ATOM
355 MyRegisterClass_wave( HINSTANCE hInstance )
356 {
357 WNDCLASSEX wcex;
358
359 wcex.cbSize = sizeof( WNDCLASSEX );
360
361 wcex.style = CS_HREDRAW | CS_VREDRAW;
362 wcex.lpfnWndProc = WndProc_wave;
363 wcex.cbClsExtra = 0;
364 wcex.cbWndExtra = 0;
365 wcex.hInstance = hInstance;
366 wcex.hIcon = 0;
367 wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
368 wcex.hbrBackground = ( HBRUSH )GetStockObject( BLACK_BRUSH );
369 wcex.lpszMenuName = 0;
370 wcex.lpszClassName = TEXT( "sndrec32_wave" );
371 wcex.hIconSm = 0;
372
373
374 return RegisterClassEx( &wcex );
375 }
376
377 BOOL
378 InitInstance_wave( HWND f, HINSTANCE hInstance, int nCmdShow )
379 {
380 HWND hWnd;
381
382 hInst = hInstance;
383
384 hWnd = CreateWindow(
385 TEXT( "sndrec32_wave" ),
386 TEXT(""),
387 WS_DLGFRAME|WS_VISIBLE|WS_CHILD,
388 WAVEBAR_X,
389 WAVEBAR_Y,
390 WAVEBAR_CX,
391 WAVEBAR_CY,
392 f, ( HMENU ) 8,
393 hInstance, 0
394 );
395
396 if ( !hWnd )
397 {
398 return FALSE;
399 }
400
401 ShowWindow( hWnd, nCmdShow );
402 UpdateWindow( hWnd );
403
404 wave_win = hWnd;
405
406
407 return TRUE;
408 }
409
410
411 LRESULT CALLBACK
412 WndProc_wave( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
413 {
414 PAINTSTRUCT ps;
415 HDC hdc;
416 HPEN pen;
417
418
419
420 unsigned int max_h = ( cli.bottom / 2 );
421 unsigned int samples;
422 unsigned int x, line_h;
423
424
425
426 switch ( message )
427 {
428
429
430 case WM_CREATE:
431
432
433 GetClientRect( hWnd, &cli );
434
435 break;
436
437
438 case WM_PAINT:
439
440 //
441 // Initialize hdc objects
442 //
443
444 hdc = BeginPaint( hWnd, &ps );
445
446 pen = ( HPEN ) CreatePen( PS_SOLID, 1, WAVEBAR_COLOR );
447
448 SelectObject( hdc, ( HBRUSH )pen );
449
450 if ( AUD_OUT->current_status() == snd::WAVEOUT_PLAYING )
451 {
452
453 samples = AUD_OUT->tot_samples_buf();
454
455
456 for ( unsigned int i = 0; i < WAVEBAR_CX; ++i )
457 {
458
459 x = ( i * samples ) / WAVEBAR_CX;
460
461 line_h = ( AUD_OUT->nsample( x ) * max_h ) / AUD_OUT->samplevalue_max();
462
463
464 if ( line_h )
465 {
466 MoveToEx( hdc, i, max_h, 0 );
467 LineTo( hdc, i, max_h - ( line_h * 2 ));
468 LineTo( hdc, i, max_h + ( line_h * 2 ));
469 } else
470 SetPixel( hdc, i, max_h, WAVEBAR_COLOR );
471
472 }
473
474
475 } else if ( AUD_IN->current_status() == snd::WAVEIN_RECORDING ) {
476
477
478 samples = AUD_IN->tot_samples_buf();
479
480
481 for ( unsigned int i = 0; i < WAVEBAR_CX; ++i )
482 {
483
484 x = ( i * samples ) / WAVEBAR_CX;
485
486 line_h = ( AUD_IN->nsample( x ) * max_h ) / AUD_IN->samplevalue_max();
487
488
489 if ( line_h )
490 {
491 MoveToEx( hdc, i, max_h, 0 );
492 LineTo( hdc, i, max_h - ( line_h * 2 ));
493 LineTo( hdc, i, max_h + ( line_h * 2 ));
494 } else
495 SetPixel( hdc, i, max_h, WAVEBAR_COLOR );
496
497 }
498
499
500 } else {
501
502 //
503 // In standby mode draw a simple line.
504 //
505
506 MoveToEx( hdc, 0, cli.bottom / 2, 0 );
507 LineTo( hdc, WAVEBAR_CX, cli.bottom / 2 );
508
509 }
510
511
512 DeleteObject( pen );
513
514 EndPaint( hWnd, &ps );
515
516 break;
517
518
519 case WM_USER:
520
521
522 break;
523
524
525 default:
526 return DefWindowProc( hWnd, message, wParam, lParam );
527
528
529 }
530
531
532 return 0;
533
534 }
535
536
537
538 LRESULT CALLBACK
539 WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
540 {
541 int wmId;
542 TCHAR str_tmp[MAX_LOADSTRING];
543 PAINTSTRUCT ps;
544 HDC hdc;
545 HFONT font;
546 long long slid_samp = 0;
547
548
549
550 //
551 // Checking for global pointers to buffer and
552 // io audio devices.
553 //
554
555 if (( !AUD_IN ) || ( !AUD_OUT ) || ( !AUD_BUF ))
556 {
557 MessageBox( 0, TEXT("Buffer Error"), 0, 0 );
558 return 1;
559 }
560
561
562 switch ( message )
563 {
564
565
566 case WM_CREATE:
567
568
569 //
570 // Creating the wave bar
571 //
572
573 if ( !InitInstance_wave( hWnd, hInst, SW_SHOWNORMAL ))
574 {
575 MessageBox(
576 0,
577 TEXT( "CreateWindow() Error!" ),
578 TEXT( "ERROR" ),
579 MB_ICONERROR
580 );
581
582 return FALSE;
583 }
584
585
586
587
588 //
589 // Creating ALL the buttons
590 //
591
592 for ( int i = 0; i < 5; ++ i )
593 {
594
595 buttons[i] = CreateWindow(
596 TEXT("button"),
597 TEXT(""),
598 WS_CHILD|WS_VISIBLE|BS_BITMAP,
599 BUTTONS_CX + ( i * (BUTTONS_W+((i == 0)?0:BUTTONS_SPACE))),
600 BUTTONS_CY, BUTTONS_W, BUTTONS_H, hWnd,
601 (HMENU)i, hInst, 0
602 );
603
604 if ( !buttons[i] )
605 {
606 MessageBox(0, 0, TEXT("CreateWindow() Error!"), 0);
607 return FALSE;
608
609 }
610
611
612 //
613 // Realize the button bmp image
614 //
615
616 SendMessage(buttons[i], BM_SETIMAGE, ( WPARAM )IMAGE_BITMAP, ( LPARAM )butbmps[i]);
617
618 UpdateWindow( buttons[i] );
619
620 disable_but( i );
621
622 }
623
624
625 //
626 // Creating the SLIDER window
627 //
628
629 slider = CreateWindow(
630 TRACKBAR_CLASS,
631 TEXT(""),
632 WS_CHILD|WS_VISIBLE|TBS_NOTICKS|TBS_HORZ|TBS_ENABLESELRANGE,
633 SLIDER_CX, SLIDER_CY, SLIDER_W, SLIDER_H, hWnd,
634 ( HMENU )SLIDER_ID, hInst, 0
635 );
636
637
638 if ( !slider )
639 {
640 MessageBox( 0, 0, TEXT( "CreateWindow() Error!" ), 0 );
641 return FALSE;
642
643 }
644
645
646 //
647 // Sets slider limits
648 //
649
650
651 SendMessage(
652 slider,
653 TBM_SETRANGE,
654 ( WPARAM )TRUE,
655 ( LPARAM )MAKELONG( slider_min, slider_max )
656 );
657
658
659 UpdateWindow( slider );
660
661 enable_but( BUTREC_ID );
662
663 EnableWindow( slider, FALSE );
664
665
666
667
668 break;
669
670
671
672 //
673 // Implements slider logic
674 //
675
676 case WM_HSCROLL :
677 {
678 switch( LOWORD( wParam ))
679 {
680
681 case SB_ENDSCROLL:
682 break;
683
684 case SB_PAGERIGHT:
685 case SB_PAGELEFT:
686 case TB_THUMBTRACK:
687
688
689 //
690 // If the user touch the slider bar,
691 // set the audio start position properly
692 //
693
694
695 slider_pos = SendMessage( slider, TBM_GETPOS, 0, 0 );
696
697 slid_samp = ( __int64 )slider_pos * ( __int64 )samples_max;
698
699 AUD_BUF->set_position(
700 AUD_BUF->audinfo().bytes_in_samples(
701 ( unsigned int )( slid_samp / ( __int64 )slider_max )
702 )
703 );
704
705 InvalidateRect( hWnd, &text_rect, TRUE );
706
707
708 break;
709
710 }
711
712 break;
713 }
714
715
716
717
718
719
720 case WM_COMMAND:
721
722 wmId = LOWORD( wParam );
723
724 if (( wmId >= 0 ) && ( wmId < 5 ) && ( butdisabled[wmId] == TRUE ))
725 break;
726
727 switch ( wmId )
728 {
729
730 case ID_NEW:
731
732 if ( !isnew )
733 {
734
735 if ( AUD_IN->current_status() == snd::WAVEIN_RECORDING )
736 AUD_IN->stop_recording();
737
738
739 if (( AUD_OUT->current_status() == snd::WAVEOUT_PLAYING ) ||
740 ( AUD_OUT->current_status() == snd::WAVEOUT_PAUSED ))
741 AUD_OUT->stop();
742
743
744 AUD_BUF->reset();
745
746 enable_but( BUTREC_ID );
747 disable_but( BUTSTART_ID );
748 disable_but( BUTEND_ID );
749 disable_but( BUTSTOP_ID );
750 disable_but( BUTPLAY_ID );
751
752
753 samples_max = AUD_BUF->total_samples();
754 slider_pos = 0;
755
756 SendMessage(slider, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) slider_pos);
757
758 EnableMenuItem( GetMenu( hWnd ), ID_FILE_SAVEAS, MF_GRAYED );
759 EnableMenuItem( GetMenu( hWnd ), ID_FILE_SAVE, MF_GRAYED );
760
761 isnew = TRUE;
762 display_dur = TRUE;
763
764 ZeroMemory( file_path, MAX_PATH * sizeof(TCHAR) );
765
766 EnableWindow( slider, FALSE );
767
768 InvalidateRect( hWnd, &text_rect, TRUE );
769 InvalidateRect( hWnd, &text2_rect, TRUE );
770
771 }
772
773
774
775 break;
776
777
778
779
780 case ID_FILE_OPEN:
781
782 ZeroMemory( &ofn, sizeof( ofn ));
783
784 ofn.lStructSize = sizeof( ofn );
785 ofn.hwndOwner = hWnd;
786 ofn.lpstrFilter = TEXT("Audio Files (*.wav)\0*.wav\0All Files (*.*)\0*.*\0");
787 ofn.lpstrFile = file_path;
788 ofn.nMaxFile = MAX_PATH;
789 ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
790 ofn.lpstrDefExt = TEXT("wav");
791
792 if( GetOpenFileName( &ofn ))
793 {
794 open_wav( file_path );
795 EnableMenuItem( GetMenu( hWnd ), ID_FILE_SAVE, MF_ENABLED );
796 EnableMenuItem( GetMenu( hWnd ), ID_FILE_SAVEAS, MF_ENABLED );
797
798 EnableWindow( slider, TRUE );
799
800 }
801
802 InvalidateRect( hWnd, &text_rect, TRUE );
803 InvalidateRect( hWnd, &text2_rect, TRUE );
804
805 break;
806
807
808
809
810 case ID__ABOUT:
811
812 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, AboutDlgProc);
813 return TRUE;
814 break;
815
816
817 case ID_FILE_SAVEAS:
818
819 ZeroMemory( &ofn, sizeof( ofn ));
820
821 ofn.lStructSize = sizeof( ofn );
822 ofn.hwndOwner = hWnd ;
823 ofn.Flags = OFN_OVERWRITEPROMPT;
824 ofn.lpstrFilter = TEXT("Audio Files (*.wav)\0*.wav\0All Files (*.*)\0*.*\0");
825 ofn.lpstrFile = file_path;
826 ofn.nMaxFile = MAX_PATH;
827
828 ofn.lpstrDefExt = TEXT("wav");
829
830 if ( GetSaveFileName ( &ofn ))
831 {
832 write_wav( file_path );
833
834 EnableMenuItem( GetMenu( hWnd ), ID_FILE_SAVE, MF_ENABLED );
835 }
836
837 break;
838
839 case ID_EXIT:
840 DestroyWindow( hWnd );
841 break;
842
843
844 //
845 // Sndrec32 buttons routines
846 //
847
848 case BUTSTART_ID:
849
850 AUD_BUF->set_position_start();
851
852 slider_pos = 0;
853
854 SendMessage( slider, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) slider_pos );
855
856 break;
857
858
859 case BUTEND_ID:
860 DestroyWindow( hWnd );
861 break;
862
863 case BUTPLAY_ID:
864
865 if ( wout_first == false )
866 {
867 AUD_OUT->open();
868 wout_first = true;
869 }
870
871
872 AUD_OUT->play();
873
874 disable_but( BUTSTART_ID );
875 disable_but( BUTEND_ID );
876 disable_but( BUTREC_ID );
877 disable_but( BUTPLAY_ID );
878
879
880 SetTimer( hWnd, 1, 250, 0 );
881 SetTimer( hWnd, WAVEBAR_TIMERID, WAVEBAR_TIMERTIME, 0 );
882
883 break;
884
885 case BUTSTOP_ID:
886 if ( s_recording )
887 {
888 s_recording = FALSE;
889
890 AUD_IN->stop_recording();
891
892
893
894 //
895 // Resetting slider position
896 //
897
898 slider_pos = 0;
899 SendMessage(slider, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) slider_pos);
900
901
902 samples_max = AUD_BUF->samples_received();
903
904 EnableMenuItem((HMENU)IDR_MENU1, ID_FILE_SAVEAS, MF_ENABLED );
905
906
907 enable_but( BUTSTART_ID );
908 enable_but( BUTEND_ID );
909 enable_but( BUTREC_ID );
910 enable_but( BUTPLAY_ID );
911
912 EnableMenuItem( GetMenu( hWnd ), ID_FILE_SAVEAS, MF_ENABLED );
913 EnableWindow( slider, TRUE );
914
915 display_dur = FALSE;
916
917 AUD_BUF->truncate();
918
919 InvalidateRect( hWnd, &text_rect, TRUE );
920 InvalidateRect( wave_win, 0, TRUE );
921
922
923 } else {
924
925 AUD_OUT->pause();
926
927 enable_but( BUTSTART_ID );
928 enable_but( BUTEND_ID );
929 enable_but( BUTREC_ID );
930 enable_but( BUTPLAY_ID );
931
932 }
933
934 KillTimer( hWnd, 1 );
935 KillTimer( hWnd, WAVEBAR_TIMERID );
936
937 InvalidateRect( hWnd, &text_rect, TRUE );
938
939 break;
940
941 case BUTREC_ID:
942
943 if ( win_first == false )
944 {
945 AUD_IN->open();
946 win_first = true;
947 }
948
949 s_recording = TRUE;
950
951 samples_max = AUD_BUF->total_samples();
952
953 AUD_IN->start_recording();
954
955 enable_but( BUTSTOP_ID );
956
957 disable_but( BUTSTART_ID );
958 disable_but( BUTEND_ID );
959 disable_but( BUTREC_ID );
960 disable_but( BUTPLAY_ID );
961
962 isnew = FALSE;
963
964 EnableWindow( slider, FALSE );
965
966 SetTimer( hWnd, 1, 150, 0 );
967
968 SetTimer( hWnd, WAVEBAR_TIMERID, WAVEBAR_TIMERTIME, 0 );
969
970 break;
971
972
973 default:
974 return DefWindowProc(hWnd, message, wParam, lParam);
975 }
976 break;
977
978
979 case WM_TIMER:
980
981 switch ( wParam )
982 {
983
984 case 1:
985 if ( stopped_flag )
986 {
987 KillTimer( hWnd, 1 );
988 KillTimer( hWnd, WAVEBAR_TIMERID );
989 slider_pos = 0;
990
991 enable_but( BUTPLAY_ID );
992
993 stopped_flag = FALSE;
994 }
995
996
997
998 SendMessage(
999 slider,
1000 TBM_SETPOS,
1001 ( WPARAM ) TRUE,
1002 ( LPARAM ) slider_pos
1003 );
1004
1005 InvalidateRect( hWnd, &text_rect, TRUE );
1006 break;
1007
1008
1009
1010 case WAVEBAR_TIMERID:
1011 InvalidateRect( wave_win, 0, TRUE );
1012 SendMessage( wave_win, WM_USER, 0, 0 );
1013 break;
1014
1015 }
1016
1017 break;
1018
1019
1020
1021 case WM_PAINT:
1022
1023
1024 hdc = BeginPaint(hWnd, &ps);
1025
1026
1027 font = CreateFontIndirect( &s_info.lfMenuFont );
1028
1029
1030 SelectObject( hdc, font );
1031
1032 SetBkMode( hdc, TRANSPARENT );
1033
1034
1035 if ( AUD_IN->current_status() == snd::WAVEIN_RECORDING )
1036 {
1037 gprintf(
1038 str_tmp,
1039 MAX_LOADSTRING,
1040 str_pos,
1041 ( float )(( float )AUD_BUF->bytes_recorded( ) / ( float )AUD_BUF->audinfo().byte_rate( ))
1042 );
1043
1044 } else if ( AUD_OUT->current_status() == snd::WAVEOUT_PLAYING ) {
1045
1046 gprintf(
1047 str_tmp,
1048 MAX_LOADSTRING,
1049 str_pos,
1050 ( float )(( float )AUD_BUF->bytes_played() / ( float )AUD_BUF->audinfo().byte_rate( ))
1051 );
1052
1053 } else {
1054
1055 gprintf(
1056 str_tmp,
1057 MAX_LOADSTRING,
1058 str_pos,
1059 ( float )(((( float )slider_pos * ( float )samples_max ) / ( float )slider_max ) / ( float )AUD_BUF->audinfo().sample_rate())
1060 );
1061 }
1062
1063
1064 ExtTextOut( hdc, STRPOS_X, STRPOS_Y, ETO_OPAQUE,
1065 0, str_tmp, _tcslen( str_tmp ), 0 );
1066
1067
1068 if ( display_dur )
1069 {
1070
1071 gprintf( str_tmp, MAX_LOADSTRING, str_dur,
1072 AUD_BUF->fseconds_total( ));
1073
1074 } else {
1075
1076
1077 gprintf( str_tmp, MAX_LOADSTRING, str_dur,
1078 AUD_BUF->fseconds_recorded( ));
1079 }
1080
1081
1082
1083 ExtTextOut( hdc, STRDUR_X, STRDUR_Y, ETO_OPAQUE,
1084 0, str_tmp, _tcslen( str_tmp ), 0 );
1085
1086
1087
1088 gprintf(
1089 str_tmp,
1090 MAX_LOADSTRING,
1091 str_buf,
1092 ( float )(( float )AUD_BUF->mem_size() / 1024.0f )
1093 );
1094
1095
1096 ExtTextOut( hdc, STRBUF_X, STRBUF_Y, ETO_OPAQUE,
1097 0, str_tmp, _tcslen( str_tmp ), 0 );
1098
1099
1100
1101 gprintf(
1102 str_tmp,
1103 MAX_LOADSTRING,
1104 str_fmt,
1105 ( float )(( float )AUD_BUF->audinfo().sample_rate() / 1000.0f ),
1106 AUD_BUF->audinfo().bits(),
1107 AUD_BUF->audinfo().channels() == 2 ? str_mono : str_stereo
1108 );
1109
1110
1111 ExtTextOut( hdc, STRFMT_X, STRFMT_Y, ETO_OPAQUE,
1112 0, str_tmp, _tcslen( str_tmp ), 0 );
1113
1114
1115
1116 gprintf(
1117 str_tmp,
1118 MAX_LOADSTRING,
1119 str_chan,
1120 AUD_BUF->audinfo().channels() == 2 ? str_stereo : str_mono
1121 );
1122
1123
1124 ExtTextOut( hdc, STRCHAN_X, STRCHAN_Y, ETO_OPAQUE,
1125 0, str_tmp, _tcslen( str_tmp ), 0 );
1126
1127
1128
1129 DeleteObject( font );
1130
1131 EndPaint(hWnd, &ps);
1132
1133
1134 break;
1135
1136
1137
1138
1139 case WM_DESTROY:
1140 PostQuitMessage(0);
1141 break;
1142 default:
1143 return DefWindowProc( hWnd, message, wParam, lParam );
1144 }
1145 return 0;
1146 }
1147
1148
1149
1150
1151
1152 void l_play_finished ( void )
1153 {
1154
1155 stopped_flag = true;
1156
1157
1158 enable_but( BUTSTART_ID );
1159 enable_but( BUTEND_ID );
1160 enable_but( BUTREC_ID );
1161 enable_but( BUTPLAY_ID );
1162
1163 InvalidateRect( wave_win, 0, TRUE );
1164
1165 }
1166
1167 void l_audio_arrival ( unsigned int samples_arrival )
1168 {
1169
1170
1171 slider_pos += ( DWORD ) (( slider_max * samples_arrival ) / samples_max );
1172
1173
1174 }
1175
1176 void l_buffer_resized ( unsigned int new_size )
1177 {
1178
1179
1180
1181
1182
1183 }
1184
1185 VOID enable_but( DWORD id )
1186 {
1187
1188 butdisabled[ id ] = FALSE;
1189
1190 SendMessage(buttons[ id ], BM_SETIMAGE, ( WPARAM )IMAGE_BITMAP, ( LPARAM )butbmps[ id ]);
1191
1192
1193 }
1194 VOID disable_but( DWORD id )
1195 {
1196
1197 butdisabled[ id ] = TRUE;
1198
1199 SendMessage(buttons[ id ], BM_SETIMAGE, ( WPARAM )IMAGE_BITMAP, ( LPARAM )butbmps_dis[ id ]);
1200
1201 }
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218 BOOL open_wav( TCHAR * f )
1219 {
1220
1221
1222 HANDLE file;
1223
1224 riff_hdr r;
1225 wave_hdr w;
1226 data_chunk d;
1227
1228 BOOL b;
1229
1230 DWORD bytes_recorded_in_wav = 0;
1231 DWORD is_read = 0;
1232
1233
1234 file = CreateFile(
1235 f,
1236 GENERIC_READ,
1237 0, 0,
1238 OPEN_EXISTING,
1239 FILE_ATTRIBUTE_NORMAL,
1240 0
1241 );
1242
1243
1244
1245 if ( !file )
1246 {
1247 MessageBox(
1248 main_win,
1249 TEXT("Cannot open file. CreateFile() error."),
1250 TEXT("ERROR"),
1251 MB_OK|MB_ICONERROR
1252 );
1253
1254 return FALSE;
1255 }
1256
1257
1258 b = ReadFile( file, ( LPVOID ) &r, sizeof ( r ), &is_read, 0 );
1259
1260 if ( !b )
1261 {
1262 MessageBox(
1263 main_win,
1264 TEXT("Cannot read RIFF header."),
1265 TEXT("ERROR"),
1266 MB_OK|MB_ICONERROR
1267 );
1268
1269 CloseHandle( file );
1270 return FALSE;
1271 }
1272
1273
1274 b = ReadFile( file, ( LPVOID ) &w, sizeof ( w ), &is_read, 0 );
1275
1276
1277 if ( !b )
1278 {
1279 MessageBox(
1280 main_win,
1281 TEXT("Cannot read WAVE header."),
1282 TEXT("ERROR"),
1283 MB_OK|MB_ICONERROR
1284 );
1285
1286 CloseHandle( file );
1287 return FALSE;
1288 }
1289
1290
1291
1292 b = ReadFile( file, ( LPVOID ) &d, sizeof ( d ), &is_read, 0 );
1293
1294 if ( !b )
1295 {
1296 MessageBox(
1297 main_win,
1298 TEXT("Cannot read WAVE subchunk."),
1299 TEXT("ERROR"),
1300 MB_OK|MB_ICONERROR
1301 );
1302
1303 CloseHandle( file );
1304 return FALSE;
1305 }
1306
1307 bytes_recorded_in_wav = r.chunksize - 36;
1308
1309
1310 if ( bytes_recorded_in_wav == 0 )
1311 {
1312 MessageBox(
1313 main_win,
1314 TEXT("Cannot read file. No audio data."),
1315 TEXT("ERROR"),
1316 MB_OK|MB_ICONERROR
1317 );
1318
1319 CloseHandle( file );
1320 return FALSE;
1321 }
1322
1323
1324 snd::audio_format openfmt
1325 ( w.SampleRate, w.BitsPerSample, w.NumChannels );
1326
1327
1328
1329 AUD_BUF->clear();
1330
1331
1332 AUD_BUF->alloc_bytes( bytes_recorded_in_wav );
1333
1334
1335 b = ReadFile(
1336 file,
1337 ( LPVOID ) AUD_BUF->audio_buffer(),
1338 bytes_recorded_in_wav,
1339 &is_read,
1340 0
1341 );
1342
1343
1344 AUD_BUF->set_b_received( bytes_recorded_in_wav );
1345
1346
1347 if (( !b ) || ( is_read != bytes_recorded_in_wav ))
1348 {
1349 MessageBox(
1350 main_win,
1351 TEXT("Cannot read file. Error reading audio data."),
1352 TEXT("ERROR"),
1353 MB_OK|MB_ICONERROR
1354 );
1355
1356 CloseHandle( file );
1357
1358 AUD_BUF->reset();
1359 return FALSE;
1360 }
1361
1362 CloseHandle( file );
1363
1364 enable_but( BUTPLAY_ID );
1365 enable_but( BUTSTOP_ID );
1366 enable_but( BUTSTART_ID );
1367 enable_but( BUTEND_ID );
1368 enable_but( BUTREC_ID );
1369
1370
1371 samples_max = AUD_BUF->samples_received();
1372
1373 isnew = FALSE;
1374
1375 return TRUE;
1376
1377 }
1378
1379
1380 BOOL
1381 write_wav( TCHAR * f )
1382 {
1383
1384 HANDLE file;
1385
1386
1387 DWORD written;
1388 BOOL is_writ;
1389 int i;
1390 riff_hdr r;
1391 wave_hdr w;
1392 data_chunk d;
1393
1394
1395
1396 file = CreateFile(
1397 f,
1398 GENERIC_WRITE,
1399 0, 0,
1400 CREATE_NEW,
1401 FILE_ATTRIBUTE_NORMAL,
1402 0
1403 );
1404
1405
1406
1407 if ( !file )
1408 {
1409 i = MessageBox(
1410 main_win,
1411 TEXT("File already exist. Overwrite it?"),
1412 TEXT("Warning"),
1413 MB_YESNO|MB_ICONQUESTION
1414 );
1415
1416 if ( i == IDYES )
1417 {
1418
1419 file = CreateFile(
1420 f,
1421 GENERIC_WRITE,
1422 0, 0,
1423 CREATE_ALWAYS,
1424 FILE_ATTRIBUTE_NORMAL,
1425 0
1426 );
1427
1428 if ( !file )
1429 {
1430 MessageBox(
1431 main_win,
1432 TEXT("File Error, CreateFile() failed."),
1433 TEXT("ERROR"),
1434 MB_OK|MB_ICONERROR
1435 );
1436
1437
1438 return FALSE;
1439
1440 }
1441
1442
1443 } else
1444 return FALSE;
1445 }
1446
1447
1448
1449
1450 r.magic = 0x46464952;
1451
1452
1453 r.format = 0x45564157;
1454 r.chunksize = 36 + AUD_BUF->bytes_recorded();
1455
1456
1457 w.Subchunkid = 0x20746d66;
1458
1459 w.Subchunk1Size = 16;
1460 w.AudioFormat = 1;
1461 w.NumChannels = AUD_BUF->audinfo().channels();
1462 w.SampleRate = AUD_BUF->audinfo().sample_rate();
1463 w.ByteRate = AUD_BUF->audinfo().byte_rate();
1464 w.BlockAlign = AUD_BUF->audinfo().block_align();
1465 w.BitsPerSample = AUD_BUF->audinfo().bits();
1466
1467
1468 d.subc = 0x61746164;
1469 d.subc_size = AUD_BUF->bytes_recorded();
1470
1471
1472
1473 //
1474 // Writing headers
1475 //
1476
1477
1478 is_writ = WriteFile( file, ( LPCVOID ) &r, sizeof ( r ), &written, 0 );
1479
1480 if ( !is_writ )
1481 {
1482 MessageBox(
1483 main_win,
1484 TEXT("File Error, WriteFile() failed."),
1485 TEXT("ERROR"),
1486 MB_OK|MB_ICONERROR
1487 );
1488
1489 CloseHandle( file );
1490
1491 return FALSE;
1492
1493 }
1494
1495
1496 is_writ = WriteFile( file, ( LPCVOID ) &w, sizeof ( w ), &written, 0 );
1497
1498 if ( !is_writ )
1499 {
1500 MessageBox(
1501 main_win,
1502 TEXT("File Error, WriteFile() failed."),
1503 TEXT("ERROR"),
1504 MB_OK|MB_ICONERROR
1505 );
1506
1507 CloseHandle( file );
1508
1509 return FALSE;
1510
1511 }
1512
1513
1514 is_writ = WriteFile( file, ( LPCVOID ) &d, sizeof ( d ), &written, 0 );
1515
1516
1517 if ( !is_writ )
1518 {
1519 MessageBox(
1520 main_win,
1521 TEXT("File Error, WriteFile() failed."),
1522 TEXT("ERROR"),
1523 MB_OK|MB_ICONERROR
1524 );
1525
1526 CloseHandle( file );
1527
1528 return FALSE;
1529
1530 }
1531
1532
1533
1534 is_writ = WriteFile(
1535 file,
1536 ( LPCVOID ) AUD_BUF->audio_buffer(),
1537 AUD_BUF->bytes_recorded(),
1538 &written,
1539 0
1540 );
1541
1542 if ( !is_writ )
1543 {
1544 MessageBox(
1545 main_win,
1546 TEXT("File Error, WriteFile() failed."),
1547 TEXT("ERROR"),
1548 MB_OK|MB_ICONERROR
1549 );
1550
1551 CloseHandle( file );
1552
1553 return FALSE;
1554
1555 }
1556
1557
1558 CloseHandle( file );
1559
1560 return TRUE;
1561 }