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