[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 * 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 HPEN oldpen;
356
357 unsigned int max_h = (cli.bottom / 2);
358 unsigned int samples;
359 unsigned int x, line_h;
360
361 switch (message)
362 {
363 case WM_CREATE:
364 GetClientRect(hWnd, &cli);
365 break;
366 case WM_PAINT:
367 /* Initialize hdc objects */
368 hdc = BeginPaint(hWnd, &ps);
369 pen = (HPEN)CreatePen(PS_SOLID, 1, WAVEBAR_COLOR);
370 oldpen = (HPEN) SelectObject(hdc, (HBRUSH)pen);
371 if (AUD_OUT->current_status() == snd::WAVEOUT_PLAYING)
372 {
373 samples = AUD_OUT->tot_samples_buf();
374 for (unsigned int i = 0; i < WAVEBAR_CX; ++i)
375 {
376 x = (i * samples) / WAVEBAR_CX;
377 line_h = (AUD_OUT->nsample(x) * max_h) / AUD_OUT->samplevalue_max();
378 if (line_h)
379 {
380 MoveToEx(hdc, i, max_h, 0);
381 LineTo(hdc, i, max_h - (line_h * 2));
382 LineTo(hdc, i, max_h + (line_h * 2));
383 }
384 else
385 {
386 SetPixel(hdc, i, max_h, WAVEBAR_COLOR);
387 }
388 }
389 }
390 else if (AUD_IN->current_status() == snd::WAVEIN_RECORDING)
391 {
392 samples = AUD_IN->tot_samples_buf();
393 for (unsigned int i = 0; i < WAVEBAR_CX; ++i)
394 {
395 x = (i * samples) / WAVEBAR_CX;
396 line_h = (AUD_IN->nsample(x) * max_h) / AUD_IN->samplevalue_max();
397 if (line_h)
398 {
399 MoveToEx(hdc, i, max_h, 0);
400 LineTo(hdc, i, max_h - (line_h * 2));
401 LineTo(hdc, i, max_h + (line_h * 2));
402 }
403 else
404 {
405 SetPixel( hdc, i, max_h, WAVEBAR_COLOR );
406 }
407 }
408 }
409 else
410 {
411 /* In standby mode draw a simple line */
412 MoveToEx(hdc, 0, cli.bottom / 2, 0);
413 LineTo(hdc, WAVEBAR_CX, cli.bottom / 2);
414 }
415
416 SelectObject(hdc, oldpen);
417 DeleteObject( pen );
418 EndPaint( hWnd, &ps );
419 break;
420
421 case WM_USER:
422 break;
423 default:
424 return DefWindowProc(hWnd, message, wParam, lParam);
425 }
426
427 return 0;
428 }
429
430 LRESULT
431 CALLBACK
432 WndProc(HWND hWnd,
433 UINT message,
434 WPARAM wParam,
435 LPARAM lParam)
436 {
437 int wmId;
438 TCHAR str_tmp[MAX_LOADSTRING];
439 PAINTSTRUCT ps;
440 HDC hdc;
441 HFONT font;
442 HFONT oldfont;
443 long long slid_samp = 0;
444
445 /* Checking for global pointers to buffer and io audio devices */
446 if ((!AUD_IN) || (!AUD_OUT) || (!AUD_BUF))
447 {
448 MessageBox(0, TEXT("Buffer Error"), 0, 0);
449 return 1;
450 }
451
452 switch (message)
453 {
454 case WM_CREATE:
455 /* Creating the wave bar */
456 if (!InitInstance_wave(hWnd, hInst, SW_SHOWNORMAL))
457 {
458 MessageBox(0, TEXT("CreateWindow() Error!"), TEXT("ERROR"), MB_ICONERROR);
459 return FALSE;
460 }
461
462 /* Creating ALL the buttons */
463 for (int i = 0; i < 5; ++i)
464 {
465 buttons[i] = CreateWindow(TEXT("button"),
466 TEXT(""),
467 WS_CHILD | WS_VISIBLE | BS_BITMAP,
468 BUTTONS_CX + (i * (BUTTONS_W + ((i == 0) ? 0 : BUTTONS_SPACE))),
469 BUTTONS_CY,
470 BUTTONS_W,
471 BUTTONS_H,
472 hWnd,
473 (HMENU)i,
474 hInst,
475 0);
476 if (!buttons[i])
477 {
478 MessageBox(0, 0, TEXT("CreateWindow() Error!"), 0);
479 return FALSE;
480 }
481
482 /* Realize the button bmp image */
483 SendMessage(buttons[i], BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)butbmps[i]);
484 UpdateWindow(buttons[i]);
485 disable_but(i);
486 }
487
488 /* Creating the SLIDER window */
489 slider = CreateWindow(TRACKBAR_CLASS,
490 TEXT(""),
491 WS_CHILD | WS_VISIBLE | TBS_NOTICKS | TBS_HORZ | TBS_ENABLESELRANGE,
492 SLIDER_CX,
493 SLIDER_CY,
494 SLIDER_W,
495 SLIDER_H,
496 hWnd,
497 (HMENU)SLIDER_ID,
498 hInst,
499 0);
500 if (!slider)
501 {
502 MessageBox(0, 0, TEXT( "CreateWindow() Error!" ), 0);
503 return FALSE;
504 }
505
506 /* Sets slider limits */
507 SendMessage(slider,
508 TBM_SETRANGE,
509 (WPARAM)TRUE,
510 (LPARAM)MAKELONG(slider_min, slider_max));
511
512 UpdateWindow(slider);
513 enable_but(BUTREC_ID);
514 EnableWindow(slider, FALSE);
515 break;
516
517 /* Implements slider logic */
518 case WM_HSCROLL:
519 {
520 switch (LOWORD(wParam))
521 {
522 case SB_ENDSCROLL:
523 break;
524 case SB_PAGERIGHT:
525 case SB_PAGELEFT:
526 case TB_THUMBTRACK:
527 /* If the user touch the slider bar, set the
528 audio start position properly */
529 slider_pos = SendMessage(slider, TBM_GETPOS, 0, 0);
530 slid_samp = (__int64)slider_pos * (__int64)samples_max;
531 AUD_BUF->set_position(AUD_BUF->audinfo().bytes_in_samples((unsigned int)(slid_samp / (__int64)slider_max)));
532 InvalidateRect(hWnd, &text_rect, TRUE);
533 break;
534 }
535 break;
536 }
537
538 case WM_COMMAND:
539 wmId = LOWORD(wParam);
540 if ((wmId >= 0) && (wmId < 5) && (butdisabled[wmId] == TRUE))
541 break;
542
543 switch (wmId)
544 {
545 case ID_FILE_NEW:
546 if (!isnew)
547 {
548 if (AUD_IN->current_status() == snd::WAVEIN_RECORDING)
549 AUD_IN->stop_recording();
550
551 if ((AUD_OUT->current_status() == snd::WAVEOUT_PLAYING) ||
552 (AUD_OUT->current_status() == snd::WAVEOUT_PAUSED))
553 AUD_OUT->stop();
554
555 AUD_BUF->reset();
556
557 enable_but(BUTREC_ID);
558 disable_but(BUTSTART_ID);
559 disable_but(BUTEND_ID);
560 disable_but(BUTSTOP_ID);
561 disable_but(BUTPLAY_ID);
562
563 samples_max = AUD_BUF->total_samples();
564 slider_pos = 0;
565
566 SendMessage(slider, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) slider_pos);
567
568 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVEAS, MF_GRAYED);
569 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVE, MF_GRAYED);
570
571 isnew = TRUE;
572 display_dur = TRUE;
573
574 ZeroMemory(file_path, MAX_PATH * sizeof(TCHAR));
575
576 EnableWindow(slider, FALSE);
577
578 InvalidateRect(hWnd, &text_rect, TRUE);
579 InvalidateRect(hWnd, &text2_rect, TRUE);
580 }
581 break;
582
583 case ID_FILE_OPEN:
584 ZeroMemory(&ofn, sizeof(ofn));
585
586 ofn.lStructSize = sizeof(ofn);
587 ofn.hwndOwner = hWnd;
588 ofn.lpstrFilter = TEXT("Audio Files (*.wav)\0*.wav\0All Files (*.*)\0*.*\0");
589 ofn.lpstrFile = file_path;
590 ofn.nMaxFile = MAX_PATH;
591 ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
592 ofn.lpstrDefExt = TEXT("wav");
593
594 if (GetOpenFileName(&ofn))
595 {
596 open_wav(file_path);
597 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVE, MF_ENABLED);
598 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVEAS, MF_ENABLED);
599
600 EnableWindow(slider, TRUE);
601 }
602
603 InvalidateRect(hWnd, &text_rect, TRUE);
604 InvalidateRect(hWnd, &text2_rect, TRUE);
605 break;
606
607 case ID_ABOUT:
608 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, AboutDlgProc);
609 return TRUE;
610 break;
611
612 case ID_FILE_SAVEAS:
613 ZeroMemory(&ofn, sizeof(ofn));
614
615 ofn.lStructSize = sizeof(ofn);
616 ofn.hwndOwner = hWnd ;
617 ofn.Flags = OFN_OVERWRITEPROMPT;
618 ofn.lpstrFilter = TEXT("Audio Files (*.wav)\0*.wav\0All Files (*.*)\0*.*\0");
619 ofn.lpstrFile = file_path;
620 ofn.nMaxFile = MAX_PATH;
621
622 ofn.lpstrDefExt = TEXT("wav");
623
624 if (GetSaveFileName (&ofn))
625 {
626 write_wav(file_path);
627 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVE, MF_ENABLED);
628 }
629 break;
630
631
632 case ID_EDIT_AUDIOPROPS:
633 ShellExecute(NULL, NULL, _T("rundll32.exe"), _T("shell32.dll,Control_RunDLL mmsys.cpl,ShowAudioPropertySheet"), NULL, SW_SHOWNORMAL);
634 break;
635
636 case ID_FILE_EXIT:
637 DestroyWindow(hWnd);
638 break;
639
640 /* Sndrec32 buttons routines */
641 case BUTSTART_ID:
642 AUD_BUF->set_position_start();
643 slider_pos = 0;
644 SendMessage(slider, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)slider_pos);
645 break;
646
647 case BUTEND_ID:
648 DestroyWindow(hWnd);
649 break;
650
651 case BUTPLAY_ID:
652 if (wout_first == false)
653 {
654 AUD_OUT->open();
655 wout_first = true;
656 }
657
658 AUD_OUT->play();
659
660 disable_but(BUTSTART_ID);
661 disable_but(BUTEND_ID);
662 disable_but(BUTREC_ID);
663 disable_but(BUTPLAY_ID);
664
665 SetTimer(hWnd, 1, 250, 0);
666 SetTimer(hWnd, WAVEBAR_TIMERID, WAVEBAR_TIMERTIME, 0);
667
668 break;
669
670 case BUTSTOP_ID:
671 if (s_recording)
672 {
673 s_recording = FALSE;
674
675 AUD_IN->stop_recording();
676
677 /* Resetting slider position */
678 slider_pos = 0;
679 SendMessage(slider, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)slider_pos);
680
681 samples_max = AUD_BUF->samples_received();
682
683 EnableMenuItem((HMENU)IDR_MENU1, ID_FILE_SAVEAS, MF_ENABLED);
684
685 enable_but(BUTSTART_ID);
686 enable_but(BUTEND_ID);
687 enable_but(BUTREC_ID);
688 enable_but(BUTPLAY_ID);
689
690 EnableMenuItem(GetMenu(hWnd), ID_FILE_SAVEAS, MF_ENABLED);
691 EnableWindow(slider, TRUE);
692
693 display_dur = FALSE;
694
695 AUD_BUF->truncate();
696
697 InvalidateRect(hWnd, &text_rect, TRUE);
698 InvalidateRect(wave_win, 0, TRUE);
699
700 }
701 else
702 {
703 AUD_OUT->pause();
704
705 enable_but(BUTSTART_ID);
706 enable_but(BUTEND_ID);
707 enable_but(BUTREC_ID);
708 enable_but(BUTPLAY_ID);
709
710 }
711
712 KillTimer(hWnd, 1);
713 KillTimer(hWnd, WAVEBAR_TIMERID);
714
715 InvalidateRect(hWnd, &text_rect, TRUE);
716
717 break;
718
719 case BUTREC_ID:
720 if (win_first == false)
721 {
722 AUD_IN->open();
723 win_first = true;
724 }
725
726 s_recording = TRUE;
727
728 samples_max = AUD_BUF->total_samples();
729
730 AUD_IN->start_recording();
731
732 enable_but(BUTSTOP_ID);
733
734 disable_but(BUTSTART_ID);
735 disable_but(BUTEND_ID);
736 disable_but(BUTREC_ID);
737 disable_but(BUTPLAY_ID);
738
739 isnew = FALSE;
740
741 EnableWindow(slider, FALSE);
742
743 SetTimer(hWnd, 1, 150, 0);
744 SetTimer(hWnd, WAVEBAR_TIMERID, WAVEBAR_TIMERTIME, 0);
745
746 break;
747
748 default:
749 return DefWindowProc(hWnd, message, wParam, lParam);
750 }
751 break;
752
753 case WM_TIMER:
754 switch (wParam)
755 {
756 case 1:
757 if (stopped_flag)
758 {
759 KillTimer(hWnd, 1);
760 KillTimer(hWnd, WAVEBAR_TIMERID);
761 slider_pos = 0;
762 enable_but(BUTPLAY_ID);
763 stopped_flag = FALSE;
764 }
765
766 SendMessage(slider, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)slider_pos);
767 InvalidateRect(hWnd, &text_rect, TRUE);
768 break;
769
770 case WAVEBAR_TIMERID:
771 InvalidateRect(wave_win, 0, TRUE);
772 SendMessage(wave_win, WM_USER, 0, 0);
773 break;
774 }
775 break;
776
777 case WM_PAINT:
778 hdc = BeginPaint(hWnd, &ps);
779 font = CreateFontIndirect(&s_info.lfMenuFont);
780 oldfont = (HFONT) SelectObject(hdc, font);
781 SetBkMode(hdc, TRANSPARENT);
782
783 if (AUD_IN->current_status() == snd::WAVEIN_RECORDING)
784 {
785 gprintf(str_tmp,
786 MAX_LOADSTRING,
787 str_pos,
788 (float)((float)AUD_BUF->bytes_recorded() / (float)AUD_BUF->audinfo().byte_rate()));
789
790 }
791 else if (AUD_OUT->current_status() == snd::WAVEOUT_PLAYING)
792 {
793 gprintf(str_tmp,
794 MAX_LOADSTRING,
795 str_pos,
796 (float)((float)AUD_BUF->bytes_played() / (float)AUD_BUF->audinfo().byte_rate()));
797 }
798 else
799 {
800 gprintf(str_tmp,
801 MAX_LOADSTRING,
802 str_pos,
803 (float)((((float)slider_pos * (float)samples_max) / (float)slider_max) / (float)AUD_BUF->audinfo().sample_rate()));
804 }
805
806 ExtTextOut(hdc,
807 STRPOS_X,
808 STRPOS_Y,
809 ETO_OPAQUE,
810 0,
811 str_tmp,
812 _tcslen(str_tmp),
813 0);
814
815 if (display_dur)
816 {
817 gprintf(str_tmp,
818 MAX_LOADSTRING,
819 str_dur,
820 AUD_BUF->fseconds_total());
821 }
822 else
823 {
824 gprintf(str_tmp,
825 MAX_LOADSTRING,
826 str_dur,
827 AUD_BUF->fseconds_recorded());
828 }
829
830 ExtTextOut(hdc,
831 STRDUR_X,
832 STRDUR_Y,
833 ETO_OPAQUE,
834 0,
835 str_tmp,
836 _tcslen(str_tmp),
837 0);
838
839 gprintf(str_tmp,
840 MAX_LOADSTRING,
841 str_buf,
842 (float)((float)AUD_BUF->mem_size() / 1024.0f));
843
844 ExtTextOut(hdc,
845 STRBUF_X,
846 STRBUF_Y,
847 ETO_OPAQUE,
848 0,
849 str_tmp,
850 _tcslen(str_tmp),
851 0);
852
853 gprintf(str_tmp,
854 MAX_LOADSTRING,
855 str_fmt,
856 (float)((float)AUD_BUF->audinfo().sample_rate() / 1000.0f),
857 AUD_BUF->audinfo().bits(),
858 AUD_BUF->audinfo().channels() == 2 ? str_mono : str_stereo);
859
860 ExtTextOut(hdc,
861 STRFMT_X,
862 STRFMT_Y,
863 ETO_OPAQUE,
864 0,
865 str_tmp,
866 _tcslen(str_tmp),
867 0);
868
869 gprintf(str_tmp,
870 MAX_LOADSTRING,
871 str_chan,
872 AUD_BUF->audinfo().channels() == 2 ? str_stereo : str_mono);
873
874 ExtTextOut(hdc,
875 STRCHAN_X,
876 STRCHAN_Y,
877 ETO_OPAQUE,
878 0,
879 str_tmp,
880 _tcslen(str_tmp),
881 0);
882
883 SelectObject(hdc, oldfont);
884 DeleteObject(font);
885 EndPaint(hWnd, &ps);
886 break;
887
888 case WM_DESTROY:
889 PostQuitMessage(0);
890 break;
891 default:
892 return DefWindowProc(hWnd, message, wParam, lParam);
893 }
894
895 return 0;
896 }
897
898 void l_play_finished(void)
899 {
900 stopped_flag = true;
901
902 enable_but(BUTSTART_ID);
903 enable_but(BUTEND_ID);
904 enable_but(BUTREC_ID);
905 enable_but(BUTPLAY_ID);
906
907 InvalidateRect(wave_win, 0, TRUE);
908 }
909
910 void l_audio_arrival(unsigned int samples_arrival)
911 {
912 slider_pos += (DWORD)((slider_max * samples_arrival) / samples_max);
913 }
914
915 void l_buffer_resized(unsigned int new_size)
916 {
917 }
918
919 VOID enable_but(DWORD id)
920 {
921 butdisabled[id] = FALSE;
922 SendMessage(buttons[id], BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)butbmps[id]);
923 }
924
925 VOID disable_but(DWORD id)
926 {
927 butdisabled[id] = TRUE;
928 SendMessage(buttons[id], BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)butbmps_dis[id]);
929 }
930
931 BOOL open_wav(TCHAR *f)
932 {
933 HANDLE file;
934
935 riff_hdr r;
936 wave_hdr w;
937 data_chunk d;
938
939 BOOL b;
940
941 DWORD bytes_recorded_in_wav = 0;
942 DWORD is_read = 0;
943
944 file = CreateFile(f,
945 GENERIC_READ,
946 0,
947 0,
948 OPEN_EXISTING,
949 FILE_ATTRIBUTE_NORMAL,
950 0);
951 if (!file)
952 {
953 MessageBox(main_win,
954 TEXT("Cannot open file. CreateFile() error."),
955 TEXT("ERROR"),
956 MB_OK | MB_ICONERROR);
957
958 return FALSE;
959 }
960
961 b = ReadFile(file, (LPVOID)&r, sizeof(r), &is_read, 0);
962 if (!b)
963 {
964 MessageBox(main_win,
965 TEXT("Cannot read RIFF header."),
966 TEXT("ERROR"),
967 MB_OK | MB_ICONERROR);
968
969 CloseHandle(file);
970 return FALSE;
971 }
972
973 b = ReadFile(file, (LPVOID)&w, sizeof(w), &is_read, 0);
974 if (!b)
975 {
976 MessageBox(main_win,
977 TEXT("Cannot read WAVE header."),
978 TEXT("ERROR"),
979 MB_OK | MB_ICONERROR);
980
981 CloseHandle(file);
982 return FALSE;
983 }
984
985 b = ReadFile(file, (LPVOID)&d, sizeof(d), &is_read, 0);
986 if (!b)
987 {
988 MessageBox(main_win,
989 TEXT("Cannot read WAVE subchunk."),
990 TEXT("ERROR"),
991 MB_OK | MB_ICONERROR);
992
993 CloseHandle(file);
994 return FALSE;
995 }
996
997 bytes_recorded_in_wav = r.chunksize - 36;
998 if (bytes_recorded_in_wav == 0)
999 {
1000 MessageBox(main_win,
1001 TEXT("Cannot read file. No audio data."),
1002 TEXT("ERROR"),
1003 MB_OK | MB_ICONERROR);
1004
1005 CloseHandle(file);
1006 return FALSE;
1007 }
1008
1009 snd::audio_format openfmt(w.SampleRate, w.BitsPerSample, w.NumChannels);
1010
1011 AUD_BUF->clear();
1012 AUD_BUF->alloc_bytes(bytes_recorded_in_wav);
1013
1014 b = ReadFile(file,
1015 (LPVOID)AUD_BUF->audio_buffer(),
1016 bytes_recorded_in_wav,
1017 &is_read,
1018 0);
1019
1020 AUD_BUF->set_b_received(bytes_recorded_in_wav);
1021
1022 if ((!b) || (is_read != bytes_recorded_in_wav))
1023 {
1024 MessageBox(main_win,
1025 TEXT("Cannot read file. Error reading audio data."),
1026 TEXT("ERROR"),
1027 MB_OK | MB_ICONERROR);
1028
1029 CloseHandle(file);
1030
1031 AUD_BUF->reset();
1032 return FALSE;
1033 }
1034
1035 CloseHandle(file);
1036
1037 enable_but(BUTPLAY_ID);
1038 enable_but(BUTSTOP_ID);
1039 enable_but(BUTSTART_ID);
1040 enable_but(BUTEND_ID);
1041 enable_but(BUTREC_ID);
1042
1043 samples_max = AUD_BUF->samples_received();
1044
1045 isnew = FALSE;
1046
1047 return TRUE;
1048 }
1049
1050 BOOL
1051 write_wav(TCHAR *f)
1052 {
1053 HANDLE file;
1054 DWORD written;
1055 BOOL is_writ;
1056 int i;
1057 riff_hdr r;
1058 wave_hdr w;
1059 data_chunk d;
1060
1061 file = CreateFile(f, GENERIC_WRITE, 0, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
1062 if (!file)
1063 {
1064 i = MessageBox(main_win,
1065 TEXT("File already exist. Overwrite it?"),
1066 TEXT("Warning"),
1067 MB_YESNO | MB_ICONQUESTION);
1068
1069 if (i == IDYES)
1070 {
1071 file = CreateFile(f, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
1072 if (!file)
1073 {
1074 MessageBox(main_win,
1075 TEXT("File Error, CreateFile() failed."),
1076 TEXT("ERROR"),
1077 MB_OK | MB_ICONERROR);
1078
1079 return FALSE;
1080 }
1081
1082 } else
1083 return FALSE;
1084 }
1085
1086 r.magic = 0x46464952;
1087 r.format = 0x45564157;
1088 r.chunksize = 36 + AUD_BUF->bytes_recorded();
1089
1090 w.Subchunkid = 0x20746d66;
1091 w.Subchunk1Size = 16;
1092 w.AudioFormat = 1;
1093 w.NumChannels = AUD_BUF->audinfo().channels();
1094 w.SampleRate = AUD_BUF->audinfo().sample_rate();
1095 w.ByteRate = AUD_BUF->audinfo().byte_rate();
1096 w.BlockAlign = AUD_BUF->audinfo().block_align();
1097 w.BitsPerSample = AUD_BUF->audinfo().bits();
1098
1099 d.subc = 0x61746164;
1100 d.subc_size = AUD_BUF->bytes_recorded();
1101
1102 /* Writing headers */
1103 is_writ = WriteFile(file, (LPCVOID)&r, sizeof(r), &written, 0);
1104 if (!is_writ)
1105 {
1106 MessageBox(main_win,
1107 TEXT("File Error, WriteFile() failed."),
1108 TEXT("ERROR"),
1109 MB_OK | MB_ICONERROR);
1110
1111 CloseHandle(file);
1112 return FALSE;
1113 }
1114
1115 is_writ = WriteFile(file, (LPCVOID)&w, sizeof(w), &written, 0);
1116 if (!is_writ)
1117 {
1118 MessageBox(main_win,
1119 TEXT("File Error, WriteFile() failed."),
1120 TEXT("ERROR"),
1121 MB_OK | MB_ICONERROR);
1122
1123 CloseHandle(file);
1124 return FALSE;
1125 }
1126
1127 is_writ = WriteFile(file, (LPCVOID)&d, sizeof(d), &written, 0);
1128 if (!is_writ)
1129 {
1130 MessageBox(main_win,
1131 TEXT("File Error, WriteFile() failed."),
1132 TEXT("ERROR"),
1133 MB_OK | MB_ICONERROR);
1134
1135 CloseHandle(file);
1136 return FALSE;
1137 }
1138
1139 is_writ = WriteFile(file,
1140 (LPCVOID)AUD_BUF->audio_buffer(),
1141 AUD_BUF->bytes_recorded(),
1142 &written,
1143 0);
1144 if (!is_writ)
1145 {
1146 MessageBox(main_win,
1147 TEXT("File Error, WriteFile() failed."),
1148 TEXT("ERROR"),
1149 MB_OK | MB_ICONERROR);
1150
1151 CloseHandle(file);
1152 return FALSE;
1153 }
1154
1155 CloseHandle(file);
1156 return TRUE;
1157 }