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