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