8408de873bb526ffd64cb1318f09d33958a6ec16
[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
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;
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
728 if (( wmId >= 0 ) && ( wmId < 5 ) && ( butdisabled[wmId] == TRUE ))
729 break;
730
731 switch ( wmId )
732 {
733
734 case ID_NEW:
735
736 if ( !isnew )
737 {
738
739 if ( AUD_IN->current_status() == snd::WAVEIN_RECORDING )
740 AUD_IN->stop_recording();
741
742
743 if (( AUD_OUT->current_status() == snd::WAVEOUT_PLAYING ) ||
744 ( AUD_OUT->current_status() == snd::WAVEOUT_PAUSED ))
745 AUD_OUT->stop();
746
747
748 AUD_BUF->reset();
749
750 enable_but( BUTREC_ID );
751 disable_but( BUTSTART_ID );
752 disable_but( BUTEND_ID );
753 disable_but( BUTSTOP_ID );
754 disable_but( BUTPLAY_ID );
755
756
757 samples_max = AUD_BUF->total_samples();
758 slider_pos = 0;
759
760 SendMessage(slider, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) slider_pos);
761
762 EnableMenuItem( GetMenu( hWnd ), ID_FILE_SAVEAS, MF_GRAYED );
763 EnableMenuItem( GetMenu( hWnd ), ID_FILE_SAVE, MF_GRAYED );
764
765 isnew = TRUE;
766 display_dur = TRUE;
767
768 ZeroMemory( file_path, MAX_PATH * sizeof(TCHAR) );
769
770 EnableWindow( slider, FALSE );
771
772 InvalidateRect( hWnd, &text_rect, TRUE );
773 InvalidateRect( hWnd, &text2_rect, TRUE );
774
775 }
776
777
778
779 break;
780
781
782
783
784 case ID_FILE_OPEN:
785
786 ZeroMemory( &ofn, sizeof( ofn ));
787
788 ofn.lStructSize = sizeof( ofn );
789 ofn.hwndOwner = hWnd;
790 ofn.lpstrFilter = TEXT("Audio Files (*.wav)\0*.wav\0All Files (*.*)\0*.*\0");
791 ofn.lpstrFile = file_path;
792 ofn.nMaxFile = MAX_PATH;
793 ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
794 ofn.lpstrDefExt = TEXT("wav");
795
796 if( GetOpenFileName( &ofn ))
797 {
798 open_wav( file_path );
799 EnableMenuItem( GetMenu( hWnd ), ID_FILE_SAVE, MF_ENABLED );
800 EnableMenuItem( GetMenu( hWnd ), ID_FILE_SAVEAS, MF_ENABLED );
801
802 EnableWindow( slider, TRUE );
803
804 }
805
806 InvalidateRect( hWnd, &text_rect, TRUE );
807 InvalidateRect( hWnd, &text2_rect, TRUE );
808
809 break;
810
811
812
813
814 case ID__ABOUT:
815
816 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, AboutDlgProc);
817 return TRUE;
818 break;
819
820
821 case ID_FILE_SAVEAS:
822
823 ZeroMemory( &ofn, sizeof( ofn ));
824
825 ofn.lStructSize = sizeof( ofn );
826 ofn.hwndOwner = hWnd ;
827 ofn.Flags = OFN_OVERWRITEPROMPT;
828 ofn.lpstrFilter = TEXT("Audio Files (*.wav)\0*.wav\0All Files (*.*)\0*.*\0");
829 ofn.lpstrFile = file_path;
830 ofn.nMaxFile = MAX_PATH;
831
832 ofn.lpstrDefExt = TEXT("wav");
833
834 if ( GetSaveFileName ( &ofn ))
835 {
836 write_wav( file_path );
837
838 EnableMenuItem( GetMenu( hWnd ), ID_FILE_SAVE, MF_ENABLED );
839 }
840
841 break;
842
843 case ID_EXIT:
844 DestroyWindow( hWnd );
845 break;
846
847
848 //
849 // Sndrec32 buttons routines
850 //
851
852 case BUTSTART_ID:
853
854 AUD_BUF->set_position_start();
855
856 slider_pos = 0;
857
858 SendMessage( slider, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) slider_pos );
859
860 break;
861
862
863 case BUTEND_ID:
864 DestroyWindow( hWnd );
865 break;
866
867 case BUTPLAY_ID:
868
869 if ( wout_first == false )
870 {
871 AUD_OUT->open();
872 wout_first = true;
873 }
874
875
876 AUD_OUT->play();
877
878 disable_but( BUTSTART_ID );
879 disable_but( BUTEND_ID );
880 disable_but( BUTREC_ID );
881 disable_but( BUTPLAY_ID );
882
883
884 SetTimer( hWnd, 1, 250, 0 );
885 SetTimer( hWnd, WAVEBAR_TIMERID, WAVEBAR_TIMERTIME, 0 );
886
887 break;
888
889 case BUTSTOP_ID:
890 if ( s_recording )
891 {
892 s_recording = FALSE;
893
894 AUD_IN->stop_recording();
895
896
897
898 //
899 // Resetting slider position
900 //
901
902 slider_pos = 0;
903 SendMessage(slider, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) slider_pos);
904
905
906 samples_max = AUD_BUF->samples_received();
907
908 EnableMenuItem((HMENU)IDR_MENU1, ID_FILE_SAVEAS, MF_ENABLED );
909
910
911 enable_but( BUTSTART_ID );
912 enable_but( BUTEND_ID );
913 enable_but( BUTREC_ID );
914 enable_but( BUTPLAY_ID );
915
916 EnableMenuItem( GetMenu( hWnd ), ID_FILE_SAVEAS, MF_ENABLED );
917 EnableWindow( slider, TRUE );
918
919 display_dur = FALSE;
920
921 AUD_BUF->truncate();
922
923 InvalidateRect( hWnd, &text_rect, TRUE );
924 InvalidateRect( wave_win, 0, TRUE );
925
926
927 } else {
928
929 AUD_OUT->pause();
930
931 enable_but( BUTSTART_ID );
932 enable_but( BUTEND_ID );
933 enable_but( BUTREC_ID );
934 enable_but( BUTPLAY_ID );
935
936 }
937
938 KillTimer( hWnd, 1 );
939 KillTimer( hWnd, WAVEBAR_TIMERID );
940
941 InvalidateRect( hWnd, &text_rect, TRUE );
942
943 break;
944
945 case BUTREC_ID:
946
947 if ( win_first == false )
948 {
949 AUD_IN->open();
950 win_first = true;
951 }
952
953 s_recording = TRUE;
954
955 samples_max = AUD_BUF->total_samples();
956
957 AUD_IN->start_recording();
958
959 enable_but( BUTSTOP_ID );
960
961 disable_but( BUTSTART_ID );
962 disable_but( BUTEND_ID );
963 disable_but( BUTREC_ID );
964 disable_but( BUTPLAY_ID );
965
966 isnew = FALSE;
967
968 EnableWindow( slider, FALSE );
969
970 SetTimer( hWnd, 1, 150, 0 );
971
972 SetTimer( hWnd, WAVEBAR_TIMERID, WAVEBAR_TIMERTIME, 0 );
973
974 break;
975
976
977 default:
978 return DefWindowProc(hWnd, message, wParam, lParam);
979 }
980 break;
981
982
983 case WM_TIMER:
984
985 switch ( wParam )
986 {
987
988 case 1:
989 if ( stopped_flag )
990 {
991 KillTimer( hWnd, 1 );
992 KillTimer( hWnd, WAVEBAR_TIMERID );
993 slider_pos = 0;
994
995 enable_but( BUTPLAY_ID );
996
997 stopped_flag = FALSE;
998 }
999
1000
1001
1002 SendMessage(
1003 slider,
1004 TBM_SETPOS,
1005 ( WPARAM ) TRUE,
1006 ( LPARAM ) slider_pos
1007 );
1008
1009 InvalidateRect( hWnd, &text_rect, TRUE );
1010 break;
1011
1012
1013
1014 case WAVEBAR_TIMERID:
1015 InvalidateRect( wave_win, 0, TRUE );
1016 SendMessage( wave_win, WM_USER, 0, 0 );
1017 break;
1018
1019 }
1020
1021 break;
1022
1023
1024
1025 case WM_PAINT:
1026
1027
1028 hdc = BeginPaint(hWnd, &ps);
1029
1030
1031 font = CreateFontIndirect( &s_info.lfMenuFont );
1032
1033
1034 SelectObject( hdc, font );
1035
1036 SetBkMode( hdc, TRANSPARENT );
1037
1038
1039 if ( AUD_IN->current_status() == snd::WAVEIN_RECORDING )
1040 {
1041 gprintf(
1042 str_tmp,
1043 MAX_LOADSTRING,
1044 str_pos,
1045 ( float )(( float )AUD_BUF->bytes_recorded( ) / ( float )AUD_BUF->audinfo().byte_rate( ))
1046 );
1047
1048 } else if ( AUD_OUT->current_status() == snd::WAVEOUT_PLAYING ) {
1049
1050 gprintf(
1051 str_tmp,
1052 MAX_LOADSTRING,
1053 str_pos,
1054 ( float )(( float )AUD_BUF->bytes_played() / ( float )AUD_BUF->audinfo().byte_rate( ))
1055 );
1056
1057 } else {
1058
1059 gprintf(
1060 str_tmp,
1061 MAX_LOADSTRING,
1062 str_pos,
1063 ( float )(((( float )slider_pos * ( float )samples_max ) / ( float )slider_max ) / ( float )AUD_BUF->audinfo().sample_rate())
1064 );
1065 }
1066
1067
1068 ExtTextOut( hdc, STRPOS_X, STRPOS_Y, ETO_OPAQUE,
1069 0, str_tmp, _tcslen( str_tmp ), 0 );
1070
1071
1072 if ( display_dur )
1073 {
1074
1075 gprintf( str_tmp, MAX_LOADSTRING, str_dur,
1076 AUD_BUF->fseconds_total( ));
1077
1078 } else {
1079
1080
1081 gprintf( str_tmp, MAX_LOADSTRING, str_dur,
1082 AUD_BUF->fseconds_recorded( ));
1083 }
1084
1085
1086
1087 ExtTextOut( hdc, STRDUR_X, STRDUR_Y, ETO_OPAQUE,
1088 0, str_tmp, _tcslen( str_tmp ), 0 );
1089
1090
1091
1092 gprintf(
1093 str_tmp,
1094 MAX_LOADSTRING,
1095 str_buf,
1096 ( float )(( float )AUD_BUF->mem_size() / 1024.0f )
1097 );
1098
1099
1100 ExtTextOut( hdc, STRBUF_X, STRBUF_Y, ETO_OPAQUE,
1101 0, str_tmp, _tcslen( str_tmp ), 0 );
1102
1103
1104
1105 gprintf(
1106 str_tmp,
1107 MAX_LOADSTRING,
1108 str_fmt,
1109 ( float )(( float )AUD_BUF->audinfo().sample_rate() / 1000.0f ),
1110 AUD_BUF->audinfo().bits(),
1111 AUD_BUF->audinfo().channels() == 2 ? str_mono : str_stereo
1112 );
1113
1114
1115 ExtTextOut( hdc, STRFMT_X, STRFMT_Y, ETO_OPAQUE,
1116 0, str_tmp, _tcslen( str_tmp ), 0 );
1117
1118
1119
1120 gprintf(
1121 str_tmp,
1122 MAX_LOADSTRING,
1123 str_chan,
1124 AUD_BUF->audinfo().channels() == 2 ? str_stereo : str_mono
1125 );
1126
1127
1128 ExtTextOut( hdc, STRCHAN_X, STRCHAN_Y, ETO_OPAQUE,
1129 0, str_tmp, _tcslen( str_tmp ), 0 );
1130
1131
1132
1133 DeleteObject( font );
1134
1135 EndPaint(hWnd, &ps);
1136
1137
1138 break;
1139
1140
1141
1142
1143 case WM_DESTROY:
1144 PostQuitMessage(0);
1145 break;
1146 default:
1147 return DefWindowProc( hWnd, message, wParam, lParam );
1148 }
1149 return 0;
1150 }
1151
1152
1153
1154
1155
1156 void l_play_finished ( void )
1157 {
1158
1159 stopped_flag = true;
1160
1161
1162 enable_but( BUTSTART_ID );
1163 enable_but( BUTEND_ID );
1164 enable_but( BUTREC_ID );
1165 enable_but( BUTPLAY_ID );
1166
1167 InvalidateRect( wave_win, 0, TRUE );
1168
1169 }
1170
1171 void l_audio_arrival ( unsigned int samples_arrival )
1172 {
1173
1174
1175 slider_pos += ( DWORD ) (( slider_max * samples_arrival ) / samples_max );
1176
1177
1178 }
1179
1180 void l_buffer_resized ( unsigned int new_size )
1181 {
1182
1183
1184
1185
1186
1187 }
1188
1189 VOID enable_but( DWORD id )
1190 {
1191
1192 butdisabled[ id ] = FALSE;
1193
1194 SendMessage(buttons[ id ], BM_SETIMAGE, ( WPARAM )IMAGE_BITMAP, ( LPARAM )butbmps[ id ]);
1195
1196
1197 }
1198 VOID disable_but( DWORD id )
1199 {
1200
1201 butdisabled[ id ] = TRUE;
1202
1203 SendMessage(buttons[ id ], BM_SETIMAGE, ( WPARAM )IMAGE_BITMAP, ( LPARAM )butbmps_dis[ id ]);
1204
1205 }
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222 BOOL open_wav( TCHAR * f )
1223 {
1224
1225
1226 HANDLE file;
1227
1228 riff_hdr r;
1229 wave_hdr w;
1230 data_chunk d;
1231
1232 BOOL b;
1233
1234 DWORD bytes_recorded_in_wav = 0;
1235 DWORD is_read = 0;
1236
1237
1238 file = CreateFile(
1239 f,
1240 GENERIC_READ,
1241 0, 0,
1242 OPEN_EXISTING,
1243 FILE_ATTRIBUTE_NORMAL,
1244 0
1245 );
1246
1247
1248
1249 if ( !file )
1250 {
1251 MessageBox(
1252 main_win,
1253 TEXT("Cannot open file. CreateFile() error."),
1254 TEXT("ERROR"),
1255 MB_OK|MB_ICONERROR
1256 );
1257
1258 return FALSE;
1259 }
1260
1261
1262 b = ReadFile( file, ( LPVOID ) &r, sizeof ( r ), &is_read, 0 );
1263
1264 if ( !b )
1265 {
1266 MessageBox(
1267 main_win,
1268 TEXT("Cannot read RIFF header."),
1269 TEXT("ERROR"),
1270 MB_OK|MB_ICONERROR
1271 );
1272
1273 CloseHandle( file );
1274 return FALSE;
1275 }
1276
1277
1278 b = ReadFile( file, ( LPVOID ) &w, sizeof ( w ), &is_read, 0 );
1279
1280
1281 if ( !b )
1282 {
1283 MessageBox(
1284 main_win,
1285 TEXT("Cannot read WAVE header."),
1286 TEXT("ERROR"),
1287 MB_OK|MB_ICONERROR
1288 );
1289
1290 CloseHandle( file );
1291 return FALSE;
1292 }
1293
1294
1295
1296 b = ReadFile( file, ( LPVOID ) &d, sizeof ( d ), &is_read, 0 );
1297
1298 if ( !b )
1299 {
1300 MessageBox(
1301 main_win,
1302 TEXT("Cannot read WAVE subchunk."),
1303 TEXT("ERROR"),
1304 MB_OK|MB_ICONERROR
1305 );
1306
1307 CloseHandle( file );
1308 return FALSE;
1309 }
1310
1311 bytes_recorded_in_wav = r.chunksize - 36;
1312
1313
1314 if ( bytes_recorded_in_wav == 0 )
1315 {
1316 MessageBox(
1317 main_win,
1318 TEXT("Cannot read file. No audio data."),
1319 TEXT("ERROR"),
1320 MB_OK|MB_ICONERROR
1321 );
1322
1323 CloseHandle( file );
1324 return FALSE;
1325 }
1326
1327
1328 snd::audio_format openfmt
1329 ( w.SampleRate, w.BitsPerSample, w.NumChannels );
1330
1331
1332
1333 AUD_BUF->clear();
1334
1335
1336 AUD_BUF->alloc_bytes( bytes_recorded_in_wav );
1337
1338
1339 b = ReadFile(
1340 file,
1341 ( LPVOID ) AUD_BUF->audio_buffer(),
1342 bytes_recorded_in_wav,
1343 &is_read,
1344 0
1345 );
1346
1347
1348 AUD_BUF->set_b_received( bytes_recorded_in_wav );
1349
1350
1351 if (( !b ) || ( is_read != bytes_recorded_in_wav ))
1352 {
1353 MessageBox(
1354 main_win,
1355 TEXT("Cannot read file. Error reading audio data."),
1356 TEXT("ERROR"),
1357 MB_OK|MB_ICONERROR
1358 );
1359
1360 CloseHandle( file );
1361
1362 AUD_BUF->reset();
1363 return FALSE;
1364 }
1365
1366 CloseHandle( file );
1367
1368 enable_but( BUTPLAY_ID );
1369 enable_but( BUTSTOP_ID );
1370 enable_but( BUTSTART_ID );
1371 enable_but( BUTEND_ID );
1372 enable_but( BUTREC_ID );
1373
1374
1375 samples_max = AUD_BUF->samples_received();
1376
1377 isnew = FALSE;
1378
1379 return TRUE;
1380
1381 }
1382
1383
1384 BOOL
1385 write_wav( TCHAR * f )
1386 {
1387
1388 HANDLE file;
1389
1390
1391 DWORD written;
1392 BOOL is_writ;
1393 int i;
1394 riff_hdr r;
1395 wave_hdr w;
1396 data_chunk d;
1397
1398
1399
1400 file = CreateFile(
1401 f,
1402 GENERIC_WRITE,
1403 0, 0,
1404 CREATE_NEW,
1405 FILE_ATTRIBUTE_NORMAL,
1406 0
1407 );
1408
1409
1410
1411 if ( !file )
1412 {
1413 i = MessageBox(
1414 main_win,
1415 TEXT("File already exist. Overwrite it?"),
1416 TEXT("Warning"),
1417 MB_YESNO|MB_ICONQUESTION
1418 );
1419
1420 if ( i == IDYES )
1421 {
1422
1423 file = CreateFile(
1424 f,
1425 GENERIC_WRITE,
1426 0, 0,
1427 CREATE_ALWAYS,
1428 FILE_ATTRIBUTE_NORMAL,
1429 0
1430 );
1431
1432 if ( !file )
1433 {
1434 MessageBox(
1435 main_win,
1436 TEXT("File Error, CreateFile() failed."),
1437 TEXT("ERROR"),
1438 MB_OK|MB_ICONERROR
1439 );
1440
1441
1442 return FALSE;
1443
1444 }
1445
1446
1447 } else
1448 return FALSE;
1449 }
1450
1451
1452
1453
1454 r.magic = 0x46464952;
1455
1456
1457 r.format = 0x45564157;
1458 r.chunksize = 36 + AUD_BUF->bytes_recorded();
1459
1460
1461 w.Subchunkid = 0x20746d66;
1462
1463 w.Subchunk1Size = 16;
1464 w.AudioFormat = 1;
1465 w.NumChannels = AUD_BUF->audinfo().channels();
1466 w.SampleRate = AUD_BUF->audinfo().sample_rate();
1467 w.ByteRate = AUD_BUF->audinfo().byte_rate();
1468 w.BlockAlign = AUD_BUF->audinfo().block_align();
1469 w.BitsPerSample = AUD_BUF->audinfo().bits();
1470
1471
1472 d.subc = 0x61746164;
1473 d.subc_size = AUD_BUF->bytes_recorded();
1474
1475
1476
1477 //
1478 // Writing headers
1479 //
1480
1481
1482 is_writ = WriteFile( file, ( LPCVOID ) &r, sizeof ( r ), &written, 0 );
1483
1484 if ( !is_writ )
1485 {
1486 MessageBox(
1487 main_win,
1488 TEXT("File Error, WriteFile() failed."),
1489 TEXT("ERROR"),
1490 MB_OK|MB_ICONERROR
1491 );
1492
1493 CloseHandle( file );
1494
1495 return FALSE;
1496
1497 }
1498
1499
1500 is_writ = WriteFile( file, ( LPCVOID ) &w, sizeof ( w ), &written, 0 );
1501
1502 if ( !is_writ )
1503 {
1504 MessageBox(
1505 main_win,
1506 TEXT("File Error, WriteFile() failed."),
1507 TEXT("ERROR"),
1508 MB_OK|MB_ICONERROR
1509 );
1510
1511 CloseHandle( file );
1512
1513 return FALSE;
1514
1515 }
1516
1517
1518 is_writ = WriteFile( file, ( LPCVOID ) &d, sizeof ( d ), &written, 0 );
1519
1520
1521 if ( !is_writ )
1522 {
1523 MessageBox(
1524 main_win,
1525 TEXT("File Error, WriteFile() failed."),
1526 TEXT("ERROR"),
1527 MB_OK|MB_ICONERROR
1528 );
1529
1530 CloseHandle( file );
1531
1532 return FALSE;
1533
1534 }
1535
1536
1537
1538 is_writ = WriteFile(
1539 file,
1540 ( LPCVOID ) AUD_BUF->audio_buffer(),
1541 AUD_BUF->bytes_recorded(),
1542 &written,
1543 0
1544 );
1545
1546 if ( !is_writ )
1547 {
1548 MessageBox(
1549 main_win,
1550 TEXT("File Error, WriteFile() failed."),
1551 TEXT("ERROR"),
1552 MB_OK|MB_ICONERROR
1553 );
1554
1555 CloseHandle( file );
1556
1557 return FALSE;
1558
1559 }
1560
1561
1562 CloseHandle( file );
1563
1564 return TRUE;
1565 }