[SNDREC32:FORMATTING]
[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 * Robert Naumann (gonzoMD)
7 */
8
9 #include "stdafx.h"
10
11 #include <commctrl.h>
12 #include <commdlg.h>
13
14 #include "sndrec32.h"
15 #include "shellapi.h"
16
17 #ifndef _UNICODE
18 #define gprintf _snprintf
19 #else
20 #define gprintf _snwprintf
21 #endif
22
23 HINSTANCE hInst;
24 TCHAR szTitle[MAX_LOADSTRING];
25 TCHAR szWindowClass[MAX_LOADSTRING];
26
27 ATOM MyRegisterClass(HINSTANCE hInstance);
28 ATOM MyRegisterClass_wave(HINSTANCE hInstance);
29 BOOL InitInstance(HINSTANCE, int);
30 BOOL InitInstance_wave(HWND, HINSTANCE, int);
31 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
32 LRESULT CALLBACK WndProc_wave(HWND, UINT, WPARAM, LPARAM);
33
34 BOOL win_first, wout_first;
35
36 HWND main_win;
37 HWND wave_win;
38 HWND slider;
39 HWND buttons[5];
40 HBITMAP butbmps[5];
41 HBITMAP butbmps_dis[5];
42 WNDPROC buttons_std_proc;
43
44 BOOL butdisabled[5];
45 BOOL stopped_flag;
46 BOOL isnew;
47 BOOL display_dur;
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 BOOL s_recording;
73
74 NONCLIENTMETRICS s_info;
75
76 RECT text_rect;
77 RECT text2_rect;
78 RECT cli;
79
80 INT_PTR
81 CALLBACK
82 AboutDlgProc(HWND hWnd,
83 UINT msg,
84 WPARAM wp,
85 LPARAM lp)
86 {
87 switch (msg)
88 {
89 case WM_COMMAND:
90 switch (LOWORD(wp))
91 {
92 case IDOK:
93 EndDialog(hWnd, 0);
94 return TRUE;
95 }
96 break;
97 case WM_CLOSE:
98 EndDialog(hWnd, 0);
99 return TRUE;
100 }
101 return FALSE;
102 }
103
104 int
105 APIENTRY
106 _tWinMain(HINSTANCE hInstance,
107 HINSTANCE hPrevInstance,
108 LPTSTR lpCmdLine,
109 int nCmdShow)
110 {
111 UNREFERENCED_PARAMETER(hPrevInstance);
112 UNREFERENCED_PARAMETER(lpCmdLine);
113
114 MSG msg;
115 HACCEL hAccelTable;
116
117 s_info.cbSize = sizeof( NONCLIENTMETRICS );
118
119 InitCommonControls();
120
121 win_first = wout_first = FALSE;
122
123 text_rect.left = REFRESHA_X;
124 text_rect.top = REFRESHA_Y;
125 text_rect.right = REFRESHA_CX;
126 text_rect.bottom = REFRESHA_CY;
127
128 text2_rect.left = REFRESHB_X;
129 text2_rect.top = REFRESHB_Y;
130 text2_rect.right = REFRESHB_CX;
131 text2_rect.bottom = REFRESHB_CY;
132
133 /* Retrieving defaul system font, and others system informations */
134 SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
135 sizeof(NONCLIENTMETRICS),
136 &s_info,
137 0);
138
139 /* Set font size */
140 s_info.lfMenuFont.lfHeight = 14;
141
142 /* Inits buttons bitmaps */
143
144 butbmps[0] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_START));
145 butbmps[1] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_END));
146 butbmps[2] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_PLAY));
147 butbmps[3] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_STOP));
148 butbmps[4] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_REC));
149
150 butbmps_dis[0] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_START_DIS));
151 butbmps_dis[1] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_END_DIS));
152 butbmps_dis[2] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_PLAY_DIS));
153 butbmps_dis[3] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_STOP_DIS));
154 butbmps_dis[4] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2_REC_DIS));
155
156 /* Inits audio devices and buffers */
157
158 snd::audio_membuffer AUD_buffer(snd::A44100_16BIT_STEREO);
159 snd::audio_waveout AUD_waveout(snd::A44100_16BIT_STEREO, AUD_buffer);
160 snd::audio_wavein AUD_wavein(snd::A44100_16BIT_STEREO, AUD_buffer);
161
162 AUD_buffer.play_finished = l_play_finished;
163 AUD_buffer.audio_arrival = l_audio_arrival;
164 AUD_buffer.buffer_resized = l_buffer_resized;
165
166 AUD_buffer.alloc_seconds(INITIAL_BUFREC_SECONDS);
167
168 AUD_IN = &AUD_wavein;
169 AUD_OUT = &AUD_waveout;
170 AUD_BUF = &AUD_buffer;
171
172 /* Inits slider default parameters */
173
174 slider_pos = 0;
175 slider_min = 0;
176 slider_max = SLIDER_W;
177
178 stopped_flag = FALSE;
179 path_set = FALSE;
180 isnew = TRUE;
181 display_dur = TRUE;
182
183 samples_max = AUD_buffer.total_samples();
184
185 s_recording = false;
186
187 /* Inits strings */
188 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
189 LoadString(hInstance, IDC_REACTOS_SNDREC32, szWindowClass, MAX_LOADSTRING);
190 LoadString(hInstance, IDS_STRPOS, str_pos, MAX_LOADSTRING);
191 LoadString(hInstance, IDS_STRDUR, str_dur, MAX_LOADSTRING);
192 LoadString(hInstance, IDS_STRBUF, str_buf, MAX_LOADSTRING);
193 LoadString(hInstance, IDS_STRFMT, str_fmt, MAX_LOADSTRING);
194 LoadString(hInstance, IDS_STRCHAN, str_chan, MAX_LOADSTRING);
195 LoadString(hInstance, IDS_STRMONO, str_mono, 10);
196 LoadString(hInstance, IDS_STRSTEREO, str_stereo, 10);
197
198 /* Registers sndrec32 window class */
199 MyRegisterClass(hInstance);
200 MyRegisterClass_wave(hInstance);
201
202 if (!InitInstance(hInstance, nCmdShow))
203 {
204 MessageBox(0, TEXT("CreateWindow() Error!"), TEXT("ERROR"), MB_ICONERROR);
205 return FALSE;
206 }
207
208 /* Loads key accelerators */
209 hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_REACTOS_SNDREC32));
210
211 /* Starts main loop */
212 while (GetMessage(&msg, NULL, 0, 0))
213 {
214 if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
215 {
216 TranslateMessage(&msg);
217 DispatchMessage(&msg);
218 }
219 }
220
221 if (wout_first)
222 {
223 AUD_waveout.close();
224 }
225
226 if (win_first)
227 {
228 AUD_wavein.close();
229 }
230
231 AUD_buffer.clear();
232
233 return (int)msg.wParam;
234 }
235
236 ATOM
237 MyRegisterClass(HINSTANCE hInstance)
238 {
239 WNDCLASSEX wcex;
240
241 wcex.cbSize = sizeof(WNDCLASSEX);
242
243 wcex.style = CS_HREDRAW | CS_VREDRAW;
244 wcex.lpfnWndProc = WndProc;
245 wcex.cbClsExtra = 0;
246 wcex.cbWndExtra = 0;
247 wcex.hInstance = hInstance;
248 wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SNDREC32));
249 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
250 wcex.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
251 wcex.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
252 wcex.lpszClassName = szWindowClass;
253 wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SNDREC32));
254
255 return RegisterClassEx(&wcex);
256 }
257
258 BOOL
259 InitInstance(HINSTANCE hInstance, int nCmdShow)
260 {
261 HWND hWnd;
262
263 hInst = hInstance;
264
265 hWnd = CreateWindow(szWindowClass,
266 szTitle,
267 WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
268 CW_USEDEFAULT,
269 CW_USEDEFAULT,
270 MAINWINDOW_W,
271 MAINWINDOW_H,
272 NULL,
273 NULL,
274 hInstance,
275 NULL);
276 if (!hWnd)
277 {
278 return FALSE;
279 }
280
281 ShowWindow(hWnd, nCmdShow);
282 UpdateWindow(hWnd);
283
284 main_win = hWnd;
285
286 return TRUE;
287 }
288
289 ATOM
290 MyRegisterClass_wave(HINSTANCE hInstance)
291 {
292 WNDCLASSEX wcex;
293
294 wcex.cbSize = sizeof(WNDCLASSEX);
295
296 wcex.style = CS_HREDRAW | CS_VREDRAW;
297 wcex.lpfnWndProc = WndProc_wave;
298 wcex.cbClsExtra = 0;
299 wcex.cbWndExtra = 0;
300 wcex.hInstance = hInstance;
301 wcex.hIcon = 0;
302 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
303 wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
304 wcex.lpszMenuName = 0;
305 wcex.lpszClassName = TEXT("sndrec32_wave");
306 wcex.hIconSm = 0;
307
308 return RegisterClassEx(&wcex);
309 }
310
311 BOOL
312 InitInstance_wave(HWND f,
313 HINSTANCE hInstance,
314 int nCmdShow)
315 {
316 HWND hWnd;
317
318 hInst = hInstance;
319
320 hWnd = CreateWindow(TEXT("sndrec32_wave"),
321 TEXT(""),
322 WS_DLGFRAME | WS_VISIBLE | WS_CHILD,
323 WAVEBAR_X,
324 WAVEBAR_Y,
325 WAVEBAR_CX,
326 WAVEBAR_CY,
327 f,
328 (HMENU)8,
329 hInstance,
330 0);
331
332 if (!hWnd )
333 {
334 return FALSE;
335 }
336
337 ShowWindow(hWnd, nCmdShow);
338 UpdateWindow(hWnd);
339
340 wave_win = hWnd;
341
342 return TRUE;
343 }
344
345 LRESULT
346 CALLBACK
347 WndProc_wave(HWND hWnd,
348 UINT message,
349 WPARAM wParam,
350 LPARAM lParam)
351 {
352 PAINTSTRUCT ps;
353 HDC hdc;
354 HPEN pen;
355
356 unsigned int max_h = (cli.bottom / 2);
357 unsigned int samples;
358 unsigned int x, line_h;
359
360 switch (message)
361 {
362 case WM_CREATE:
363 GetClientRect(hWnd, &cli);
364 break;
365 case WM_PAINT:
366 /* Initialize hdc objects */
367 hdc = BeginPaint(hWnd, &ps);
368 pen = (HPEN)CreatePen(PS_SOLID, 1, WAVEBAR_COLOR);
369 SelectObject(hdc, (HBRUSH)pen);
370 if (AUD_OUT->current_status() == snd::WAVEOUT_PLAYING)
371 {
372 samples = AUD_OUT->tot_samples_buf();
373 for (unsigned int i = 0; i < WAVEBAR_CX; ++i)
374 {
375 x = (i * samples) / WAVEBAR_CX;
376 line_h = (AUD_OUT->nsample(x) * max_h) / AUD_OUT->samplevalue_max();
377 if (line_h)
378 {
379 MoveToEx(hdc, i, max_h, 0);
380 LineTo(hdc, i, max_h - (line_h * 2));
381 LineTo(hdc, i, max_h + (line_h * 2));
382 }
383 else
384 {
385 SetPixel(hdc, i, max_h, WAVEBAR_COLOR);
386 }
387 }
388 }
389 else if (AUD_IN->current_status() == snd::WAVEIN_RECORDING)
390 {
391 samples = AUD_IN->tot_samples_buf();
392 for (unsigned int i = 0; i < WAVEBAR_CX; ++i)
393 {
394 x = (i * samples) / WAVEBAR_CX;
395 line_h = (AUD_IN->nsample(x) * max_h) / AUD_IN->samplevalue_max();
396 if (line_h)
397 {
398 MoveToEx(hdc, i, max_h, 0);
399 LineTo(hdc, i, max_h - (line_h * 2));
400 LineTo(hdc, i, max_h + (line_h * 2));
401 }
402 else
403 {
404 SetPixel( hdc, i, max_h, WAVEBAR_COLOR );
405 }
406 }
407 }
408 else
409 {
410 /* In standby mode draw a simple line */
411 MoveToEx(hdc, 0, cli.bottom / 2, 0);
412 LineTo(hdc, WAVEBAR_CX, cli.bottom / 2);
413 }
414
415 DeleteObject( pen );
416 EndPaint( hWnd, &ps );
417 break;
418
419 case WM_USER:
420 break;
421 default:
422 return DefWindowProc(hWnd, message, wParam, lParam);
423 }
424
425 return 0;
426 }
427
428 LRESULT
429 CALLBACK
430 WndProc(HWND hWnd,
431 UINT message,
432 WPARAM wParam,
433 LPARAM lParam)
434 {
435 int wmId;
436 TCHAR str_tmp[MAX_LOADSTRING];
437 PAINTSTRUCT ps;
438 HDC hdc;
439 HFONT font;
440 long long slid_samp = 0;
441
442 /* Checking for global pointers to buffer and io audio devices */
443 if ((!AUD_IN) || (!AUD_OUT) || (!AUD_BUF))
444 {
445 MessageBox(0, TEXT("Buffer Error"), 0, 0);
446 return 1;
447 }
448
449 switch (message)
450 {
451 case WM_CREATE:
452 /* Creating the wave bar */
453 if (!InitInstance_wave(hWnd, hInst, SW_SHOWNORMAL))
454 {
455 MessageBox(0, TEXT("CreateWindow() Error!"), TEXT("ERROR"), MB_ICONERROR);
456 return FALSE;
457 }
458
459 /* Creating ALL the buttons */
460 for (int i = 0; i < 5; ++i)
461 {
462 buttons[i] = CreateWindow(TEXT("button"),
463 TEXT(""),
464 WS_CHILD | WS_VISIBLE | BS_BITMAP,
465 BUTTONS_CX + (i * (BUTTONS_W + ((i == 0) ? 0 : BUTTONS_SPACE))),
466 BUTTONS_CY,
467 BUTTONS_W,
468 BUTTONS_H,
469 hWnd,
470 (HMENU)i,
471 hInst,
472 0);
473 if (!buttons[i])
474 {
475 MessageBox(0, 0, TEXT("CreateWindow() Error!"), 0);
476 return FALSE;
477 }
478
479 /* Realize the button bmp image */
480 SendMessage(buttons[i], BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)butbmps[i]);
481 UpdateWindow(buttons[i]);
482 disable_but(i);
483 }
484
485 /* Creating the SLIDER window */
486 slider = CreateWindow(TRACKBAR_CLASS,
487 TEXT(""),
488 WS_CHILD | WS_VISIBLE | TBS_NOTICKS | TBS_HORZ | TBS_ENABLESELRANGE,
489 SLIDER_CX,
490 SLIDER_CY,
491 SLIDER_W,
492 SLIDER_H,
493 hWnd,
494 (HMENU)SLIDER_ID,
495 hInst,
496 0);
497 if (!slider)
498 {
499 MessageBox(0, 0, TEXT( "CreateWindow() Error!" ), 0);
500 return FALSE;
501 }
502
503 /* Sets slider limits */
504 SendMessage(slider,
505 TBM_SETRANGE,
506 (WPARAM)TRUE,
507 (LPARAM)MAKELONG(slider_min, slider_max));
508
509 UpdateWindow(slider);
510 enable_but(BUTREC_ID);
511 EnableWindow(slider, FALSE);
512 break;
513
514 /* Implements slider logic */
515 case WM_HSCROLL:
516 {
517 switch (LOWORD(wParam))
518 {
519 case SB_ENDSCROLL:
520 break;
521 case SB_PAGERIGHT:
522 case SB_PAGELEFT:
523 case TB_THUMBTRACK:
524 /* If the user touch the slider bar, set the
525 audio start position properly */
526 slider_pos = SendMessage(slider, TBM_GETPOS, 0, 0);
527 slid_samp = (__int64)slider_pos * (__int64)samples_max;
528 AUD_BUF->set_position(AUD_BUF->audinfo().bytes_in_samples((unsigned int)(slid_samp / (__int64)slider_max)));
529 InvalidateRect(hWnd, &text_rect, TRUE);
530 break;
531 }
532 break;
533 }
534
535 case WM_COMMAND:
536 wmId = LOWORD(wParam);
537 if ((wmId >= 0) && (wmId < 5) && (butdisabled[wmId] == TRUE))
538 break;
539
540 switch (wmId)
541 {
542 case ID_FILE_NEW:
543 if (!isnew)
544 {
545 if (AUD_IN->current_status() == snd::WAVEIN_RECORDING)
546 AUD_IN->stop_recording();
547
548 if ((AUD_OUT->current_status() == snd::WAVEOUT_PLAYING) ||
549 (AUD_OUT->current_status() == snd::WAVEOUT_PAUSED))
550 AUD_OUT->stop();
551
552 AUD_BUF->reset();
553
554 enable_but(BUTREC_ID);
555 disable_but(BUTSTART_ID);
556 disable_but(BUTEND_ID);
557 disable_but(BUTSTOP_ID);
558 disable_but(BUTPLAY_ID);
559
560 samples_max = AUD_BUF->total_samples();
561 slider_pos = 0;
562
563 SendMessage(slider, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) slider_pos);
564
565 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVEAS, MF_GRAYED);
566 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVE, MF_GRAYED);
567
568 isnew = TRUE;
569 display_dur = TRUE;
570
571 ZeroMemory(file_path, MAX_PATH * sizeof(TCHAR));
572
573 EnableWindow(slider, FALSE);
574
575 InvalidateRect(hWnd, &text_rect, TRUE);
576 InvalidateRect(hWnd, &text2_rect, TRUE);
577 }
578 break;
579
580 case ID_FILE_OPEN:
581 ZeroMemory(&ofn, sizeof(ofn));
582
583 ofn.lStructSize = sizeof(ofn);
584 ofn.hwndOwner = hWnd;
585 ofn.lpstrFilter = TEXT("Audio Files (*.wav)\0*.wav\0All Files (*.*)\0*.*\0");
586 ofn.lpstrFile = file_path;
587 ofn.nMaxFile = MAX_PATH;
588 ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
589 ofn.lpstrDefExt = TEXT("wav");
590
591 if (GetOpenFileName(&ofn))
592 {
593 open_wav(file_path);
594 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVE, MF_ENABLED);
595 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVEAS, MF_ENABLED);
596
597 EnableWindow(slider, TRUE);
598 }
599
600 InvalidateRect(hWnd, &text_rect, TRUE);
601 InvalidateRect(hWnd, &text2_rect, TRUE);
602 break;
603
604 case ID_ABOUT:
605 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, AboutDlgProc);
606 return TRUE;
607 break;
608
609 case ID_FILE_SAVEAS:
610 ZeroMemory(&ofn, sizeof(ofn));
611
612 ofn.lStructSize = sizeof(ofn);
613 ofn.hwndOwner = hWnd ;
614 ofn.Flags = OFN_OVERWRITEPROMPT;
615 ofn.lpstrFilter = TEXT("Audio Files (*.wav)\0*.wav\0All Files (*.*)\0*.*\0");
616 ofn.lpstrFile = file_path;
617 ofn.nMaxFile = MAX_PATH;
618
619 ofn.lpstrDefExt = TEXT("wav");
620
621 if (GetSaveFileName (&ofn))
622 {
623 write_wav(file_path);
624 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVE, MF_ENABLED);
625 }
626 break;
627
628
629 case ID_EDIT_AUDIOPROPS:
630 ShellExecute(NULL, NULL, _T("rundll32.exe"), _T("shell32.dll,Control_RunDLL mmsys.cpl,ShowAudioPropertySheet"), NULL, SW_SHOWNORMAL);
631 break;
632
633 case ID_FILE_EXIT:
634 DestroyWindow(hWnd);
635 break;
636
637 /* Sndrec32 buttons routines */
638 case BUTSTART_ID:
639 AUD_BUF->set_position_start();
640 slider_pos = 0;
641 SendMessage(slider, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)slider_pos);
642 break;
643
644 case BUTEND_ID:
645 DestroyWindow(hWnd);
646 break;
647
648 case BUTPLAY_ID:
649 if (wout_first == false)
650 {
651 AUD_OUT->open();
652 wout_first = true;
653 }
654
655 AUD_OUT->play();
656
657 disable_but(BUTSTART_ID);
658 disable_but(BUTEND_ID);
659 disable_but(BUTREC_ID);
660 disable_but(BUTPLAY_ID);
661
662 SetTimer(hWnd, 1, 250, 0);
663 SetTimer(hWnd, WAVEBAR_TIMERID, WAVEBAR_TIMERTIME, 0);
664
665 break;
666
667 case BUTSTOP_ID:
668 if (s_recording)
669 {
670 s_recording = FALSE;
671
672 AUD_IN->stop_recording();
673
674 /* Resetting slider position */
675 slider_pos = 0;
676 SendMessage(slider, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)slider_pos);
677
678 samples_max = AUD_BUF->samples_received();
679
680 EnableMenuItem((HMENU)IDR_MENU1, ID_FILE_SAVEAS, MF_ENABLED);
681
682 enable_but(BUTSTART_ID);
683 enable_but(BUTEND_ID);
684 enable_but(BUTREC_ID);
685 enable_but(BUTPLAY_ID);
686
687 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVEAS, MF_ENABLED);
688 EnableWindow(slider, TRUE);
689
690 display_dur = FALSE;
691
692 AUD_BUF->truncate();
693
694 InvalidateRect(hWnd, &text_rect, TRUE);
695 InvalidateRect(wave_win, 0, TRUE);
696
697 }
698 else
699 {
700 AUD_OUT->pause();
701
702 enable_but(BUTSTART_ID);
703 enable_but(BUTEND_ID);
704 enable_but(BUTREC_ID);
705 enable_but(BUTPLAY_ID);
706
707 }
708
709 KillTimer(hWnd, 1);
710 KillTimer(hWnd, WAVEBAR_TIMERID);
711
712 InvalidateRect(hWnd, &text_rect, TRUE);
713
714 break;
715
716 case BUTREC_ID:
717 if (win_first == false)
718 {
719 AUD_IN->open();
720 win_first = true;
721 }
722
723 s_recording = TRUE;
724
725 samples_max = AUD_BUF->total_samples();
726
727 AUD_IN->start_recording();
728
729 enable_but(BUTSTOP_ID);
730
731 disable_but(BUTSTART_ID);
732 disable_but(BUTEND_ID);
733 disable_but(BUTREC_ID);
734 disable_but(BUTPLAY_ID);
735
736 isnew = FALSE;
737
738 EnableWindow(slider, FALSE);
739
740 SetTimer(hWnd, 1, 150, 0);
741 SetTimer(hWnd, WAVEBAR_TIMERID, WAVEBAR_TIMERTIME, 0);
742
743 break;
744
745 default:
746 return DefWindowProc(hWnd, message, wParam, lParam);
747 }
748 break;
749
750 case WM_TIMER:
751 switch (wParam)
752 {
753 case 1:
754 if (stopped_flag)
755 {
756 KillTimer(hWnd, 1);
757 KillTimer(hWnd, WAVEBAR_TIMERID);
758 slider_pos = 0;
759 enable_but(BUTPLAY_ID);
760 stopped_flag = FALSE;
761 }
762
763 SendMessage(slider, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)slider_pos);
764 InvalidateRect(hWnd, &text_rect, TRUE);
765 break;
766
767 case WAVEBAR_TIMERID:
768 InvalidateRect(wave_win, 0, TRUE);
769 SendMessage(wave_win, WM_USER, 0, 0);
770 break;
771 }
772 break;
773
774 case WM_PAINT:
775 hdc = BeginPaint(hWnd, &ps);
776 font = CreateFontIndirect(&s_info.lfMenuFont);
777 SelectObject(hdc, font);
778 SetBkMode(hdc, TRANSPARENT);
779
780 if (AUD_IN->current_status() == snd::WAVEIN_RECORDING)
781 {
782 gprintf(str_tmp,
783 MAX_LOADSTRING,
784 str_pos,
785 (float)((float)AUD_BUF->bytes_recorded() / (float)AUD_BUF->audinfo().byte_rate()));
786
787 }
788 else if (AUD_OUT->current_status() == snd::WAVEOUT_PLAYING)
789 {
790 gprintf(str_tmp,
791 MAX_LOADSTRING,
792 str_pos,
793 (float)((float)AUD_BUF->bytes_played() / (float)AUD_BUF->audinfo().byte_rate()));
794 }
795 else
796 {
797 gprintf(str_tmp,
798 MAX_LOADSTRING,
799 str_pos,
800 (float)((((float)slider_pos * (float)samples_max) / (float)slider_max) / (float)AUD_BUF->audinfo().sample_rate()));
801 }
802
803 ExtTextOut(hdc,
804 STRPOS_X,
805 STRPOS_Y,
806 ETO_OPAQUE,
807 0,
808 str_tmp,
809 _tcslen(str_tmp),
810 0);
811
812 if (display_dur)
813 {
814 gprintf(str_tmp,
815 MAX_LOADSTRING,
816 str_dur,
817 AUD_BUF->fseconds_total());
818 }
819 else
820 {
821 gprintf(str_tmp,
822 MAX_LOADSTRING,
823 str_dur,
824 AUD_BUF->fseconds_recorded());
825 }
826
827 ExtTextOut(hdc,
828 STRDUR_X,
829 STRDUR_Y,
830 ETO_OPAQUE,
831 0,
832 str_tmp,
833 _tcslen(str_tmp),
834 0);
835
836 gprintf(str_tmp,
837 MAX_LOADSTRING,
838 str_buf,
839 (float)((float)AUD_BUF->mem_size() / 1024.0f));
840
841 ExtTextOut(hdc,
842 STRBUF_X,
843 STRBUF_Y,
844 ETO_OPAQUE,
845 0,
846 str_tmp,
847 _tcslen(str_tmp),
848 0);
849
850 gprintf(str_tmp,
851 MAX_LOADSTRING,
852 str_fmt,
853 (float)((float)AUD_BUF->audinfo().sample_rate() / 1000.0f),
854 AUD_BUF->audinfo().bits(),
855 AUD_BUF->audinfo().channels() == 2 ? str_mono : str_stereo);
856
857 ExtTextOut(hdc,
858 STRFMT_X,
859 STRFMT_Y,
860 ETO_OPAQUE,
861 0,
862 str_tmp,
863 _tcslen(str_tmp),
864 0);
865
866 gprintf(str_tmp,
867 MAX_LOADSTRING,
868 str_chan,
869 AUD_BUF->audinfo().channels() == 2 ? str_stereo : str_mono);
870
871 ExtTextOut(hdc,
872 STRCHAN_X,
873 STRCHAN_Y,
874 ETO_OPAQUE,
875 0,
876 str_tmp,
877 _tcslen(str_tmp),
878 0);
879
880 DeleteObject(font);
881 EndPaint(hWnd, &ps);
882 break;
883
884 case WM_DESTROY:
885 PostQuitMessage(0);
886 break;
887 default:
888 return DefWindowProc(hWnd, message, wParam, lParam);
889 }
890
891 return 0;
892 }
893
894 void l_play_finished(void)
895 {
896 stopped_flag = true;
897
898 enable_but(BUTSTART_ID);
899 enable_but(BUTEND_ID);
900 enable_but(BUTREC_ID);
901 enable_but(BUTPLAY_ID);
902
903 InvalidateRect(wave_win, 0, TRUE);
904 }
905
906 void l_audio_arrival(unsigned int samples_arrival)
907 {
908 slider_pos += (DWORD)((slider_max * samples_arrival) / samples_max);
909 }
910
911 void l_buffer_resized(unsigned int new_size)
912 {
913 }
914
915 VOID enable_but(DWORD id)
916 {
917 butdisabled[id] = FALSE;
918 SendMessage(buttons[id], BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)butbmps[id]);
919 }
920
921 VOID disable_but(DWORD id)
922 {
923 butdisabled[id] = TRUE;
924 SendMessage(buttons[id], BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)butbmps_dis[id]);
925 }
926
927 BOOL open_wav(TCHAR *f)
928 {
929 HANDLE file;
930
931 riff_hdr r;
932 wave_hdr w;
933 data_chunk d;
934
935 BOOL b;
936
937 DWORD bytes_recorded_in_wav = 0;
938 DWORD is_read = 0;
939
940 file = CreateFile(f,
941 GENERIC_READ,
942 0,
943 0,
944 OPEN_EXISTING,
945 FILE_ATTRIBUTE_NORMAL,
946 0);
947 if (!file)
948 {
949 MessageBox(main_win,
950 TEXT("Cannot open file. CreateFile() error."),
951 TEXT("ERROR"),
952 MB_OK | MB_ICONERROR);
953
954 return FALSE;
955 }
956
957 b = ReadFile(file, (LPVOID)&r, sizeof(r), &is_read, 0);
958 if (!b)
959 {
960 MessageBox(main_win,
961 TEXT("Cannot read RIFF header."),
962 TEXT("ERROR"),
963 MB_OK | MB_ICONERROR);
964
965 CloseHandle(file);
966 return FALSE;
967 }
968
969 b = ReadFile(file, (LPVOID)&w, sizeof(w), &is_read, 0);
970 if (!b)
971 {
972 MessageBox(main_win,
973 TEXT("Cannot read WAVE header."),
974 TEXT("ERROR"),
975 MB_OK | MB_ICONERROR);
976
977 CloseHandle(file);
978 return FALSE;
979 }
980
981 b = ReadFile(file, (LPVOID)&d, sizeof(d), &is_read, 0);
982 if (!b)
983 {
984 MessageBox(main_win,
985 TEXT("Cannot read WAVE subchunk."),
986 TEXT("ERROR"),
987 MB_OK | MB_ICONERROR);
988
989 CloseHandle(file);
990 return FALSE;
991 }
992
993 bytes_recorded_in_wav = r.chunksize - 36;
994 if (bytes_recorded_in_wav == 0)
995 {
996 MessageBox(main_win,
997 TEXT("Cannot read file. No audio data."),
998 TEXT("ERROR"),
999 MB_OK | MB_ICONERROR);
1000
1001 CloseHandle(file);
1002 return FALSE;
1003 }
1004
1005 snd::audio_format openfmt(w.SampleRate, w.BitsPerSample, w.NumChannels);
1006
1007 AUD_BUF->clear();
1008 AUD_BUF->alloc_bytes(bytes_recorded_in_wav);
1009
1010 b = ReadFile(file,
1011 (LPVOID)AUD_BUF->audio_buffer(),
1012 bytes_recorded_in_wav,
1013 &is_read,
1014 0);
1015
1016 AUD_BUF->set_b_received(bytes_recorded_in_wav);
1017
1018 if ((!b) || (is_read != bytes_recorded_in_wav))
1019 {
1020 MessageBox(main_win,
1021 TEXT("Cannot read file. Error reading audio data."),
1022 TEXT("ERROR"),
1023 MB_OK | MB_ICONERROR);
1024
1025 CloseHandle(file);
1026
1027 AUD_BUF->reset();
1028 return FALSE;
1029 }
1030
1031 CloseHandle(file);
1032
1033 enable_but(BUTPLAY_ID);
1034 enable_but(BUTSTOP_ID);
1035 enable_but(BUTSTART_ID);
1036 enable_but(BUTEND_ID);
1037 enable_but(BUTREC_ID);
1038
1039 samples_max = AUD_BUF->samples_received();
1040
1041 isnew = FALSE;
1042
1043 return TRUE;
1044 }
1045
1046 BOOL
1047 write_wav(TCHAR *f)
1048 {
1049 HANDLE file;
1050 DWORD written;
1051 BOOL is_writ;
1052 int i;
1053 riff_hdr r;
1054 wave_hdr w;
1055 data_chunk d;
1056
1057 file = CreateFile(f, GENERIC_WRITE, 0, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
1058 if (!file)
1059 {
1060 i = MessageBox(main_win,
1061 TEXT("File already exist. Overwrite it?"),
1062 TEXT("Warning"),
1063 MB_YESNO | MB_ICONQUESTION);
1064
1065 if (i == IDYES)
1066 {
1067 file = CreateFile(f, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
1068 if (!file)
1069 {
1070 MessageBox(main_win,
1071 TEXT("File Error, CreateFile() failed."),
1072 TEXT("ERROR"),
1073 MB_OK | MB_ICONERROR);
1074
1075 return FALSE;
1076 }
1077
1078 } else
1079 return FALSE;
1080 }
1081
1082 r.magic = 0x46464952;
1083 r.format = 0x45564157;
1084 r.chunksize = 36 + AUD_BUF->bytes_recorded();
1085
1086 w.Subchunkid = 0x20746d66;
1087 w.Subchunk1Size = 16;
1088 w.AudioFormat = 1;
1089 w.NumChannels = AUD_BUF->audinfo().channels();
1090 w.SampleRate = AUD_BUF->audinfo().sample_rate();
1091 w.ByteRate = AUD_BUF->audinfo().byte_rate();
1092 w.BlockAlign = AUD_BUF->audinfo().block_align();
1093 w.BitsPerSample = AUD_BUF->audinfo().bits();
1094
1095 d.subc = 0x61746164;
1096 d.subc_size = AUD_BUF->bytes_recorded();
1097
1098 /* Writing headers */
1099 is_writ = WriteFile(file, (LPCVOID)&r, sizeof(r), &written, 0);
1100 if (!is_writ)
1101 {
1102 MessageBox(main_win,
1103 TEXT("File Error, WriteFile() failed."),
1104 TEXT("ERROR"),
1105 MB_OK | MB_ICONERROR);
1106
1107 CloseHandle(file);
1108 return FALSE;
1109 }
1110
1111 is_writ = WriteFile(file, (LPCVOID)&w, sizeof(w), &written, 0);
1112 if (!is_writ)
1113 {
1114 MessageBox(main_win,
1115 TEXT("File Error, WriteFile() failed."),
1116 TEXT("ERROR"),
1117 MB_OK | MB_ICONERROR);
1118
1119 CloseHandle(file);
1120 return FALSE;
1121 }
1122
1123 is_writ = WriteFile(file, (LPCVOID)&d, sizeof(d), &written, 0);
1124 if (!is_writ)
1125 {
1126 MessageBox(main_win,
1127 TEXT("File Error, WriteFile() failed."),
1128 TEXT("ERROR"),
1129 MB_OK | MB_ICONERROR);
1130
1131 CloseHandle(file);
1132 return FALSE;
1133 }
1134
1135 is_writ = WriteFile(file,
1136 (LPCVOID)AUD_BUF->audio_buffer(),
1137 AUD_BUF->bytes_recorded(),
1138 &written,
1139 0);
1140 if (!is_writ)
1141 {
1142 MessageBox(main_win,
1143 TEXT("File Error, WriteFile() failed."),
1144 TEXT("ERROR"),
1145 MB_OK | MB_ICONERROR);
1146
1147 CloseHandle(file);
1148 return FALSE;
1149 }
1150
1151 CloseHandle(file);
1152 return TRUE;
1153 }