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
_tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)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
MyRegisterClass(HINSTANCE hInstance)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
InitInstance(HINSTANCE hInstance,int nCmdShow)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
MyRegisterClass_wave(HINSTANCE hInstance)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
InitInstance_wave(HWND f,HINSTANCE hInstance,int nCmdShow)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
WndProc_wave(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)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
WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)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
l_play_finished(void)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
l_audio_arrival(unsigned int samples_arrival)902 void l_audio_arrival(unsigned int samples_arrival)
903 {
904 slider_pos += (DWORD)((slider_max * samples_arrival) / samples_max);
905 }
906
l_buffer_resized(unsigned int new_size)907 void l_buffer_resized(unsigned int new_size)
908 {
909 }
910
enable_but(DWORD id)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
disable_but(DWORD id)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
open_wav(TCHAR * f)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
write_wav(TCHAR * f)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