2 * PROJECT: ReactOS Multimedia Player
3 * FILE: base\applications\mplay32\mplay32.c
4 * PROGRAMMERS: Dmitry Chapyshev (dmitry@reactos.org)
9 #define MAIN_WINDOW_HEIGHT 125
10 #define MAIN_WINDOW_MIN_WIDTH 250
12 HINSTANCE hInstance
= NULL
;
13 HWND hTrackBar
= NULL
;
15 TCHAR szAppTitle
[256] = _T("");
16 TCHAR szPrevFile
[MAX_PATH
] = _T("\0");
18 BOOL bIsOpened
= FALSE
;
19 BOOL bIsPaused
= FALSE
;
22 /* Known types table */
23 static const TYPEBYEXT ExtTypes
[] =
25 { _T(".wav"), WAVE_FILE
},
26 { _T(".wave"), WAVE_FILE
},
27 { _T(".mid"), MIDI_FILE
},
28 { _T(".midi"), MIDI_FILE
},
29 { _T(".cda"), AUDIOCD_FILE
},
30 { _T(".avi"), AVI_FILE
},
35 static const TBBUTTON Buttons
[] =
36 { /* iBitmap, idCommand, fsState, fsStyle, bReserved[2], dwData, iString */
37 {TBICON_PLAY
, IDC_PLAY
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0},
38 {TBICON_STOP
, IDC_STOP
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0},
39 {TBICON_EJECT
, IDC_EJECT
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0},
40 {15, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0}, 0, 0},
41 {TBICON_BACKWARD
, IDC_BACKWARD
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0},
42 {TBICON_SEEKBACK
, IDC_SEEKBACK
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0},
43 {TBICON_SEEKFORW
, IDC_SEEKFORW
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0},
44 {TBICON_FORWARD
, IDC_FORWARD
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0}
48 SetImageList(HWND hwnd
)
50 HIMAGELIST hImageList
;
52 hImageList
= ImageList_Create(16, 16, ILC_MASK
| ILC_COLOR24
, 1, 1);
56 MessageBox(hwnd
, _T("ImageList it is not created!"), NULL
, MB_OK
);
60 ImageList_AddMasked(hImageList
,
61 LoadImage(hInstance
, MAKEINTRESOURCE(IDB_PLAYICON
), IMAGE_BITMAP
, 16, 16, LR_DEFAULTCOLOR
),
64 ImageList_AddMasked(hImageList
,
65 LoadImage(hInstance
, MAKEINTRESOURCE(IDB_STOPICON
), IMAGE_BITMAP
, 16, 16, LR_DEFAULTCOLOR
),
68 ImageList_AddMasked(hImageList
,
69 LoadImage(hInstance
, MAKEINTRESOURCE(IDB_EJECTICON
), IMAGE_BITMAP
, 16, 16, LR_DEFAULTCOLOR
),
72 ImageList_AddMasked(hImageList
,
73 LoadImage(hInstance
, MAKEINTRESOURCE(IDB_BACKWARDICON
), IMAGE_BITMAP
, 16, 16, LR_DEFAULTCOLOR
),
76 ImageList_AddMasked(hImageList
,
77 LoadImage(hInstance
, MAKEINTRESOURCE(IDB_SEEKBACKICON
), IMAGE_BITMAP
, 16, 16, LR_DEFAULTCOLOR
),
80 ImageList_AddMasked(hImageList
,
81 LoadImage(hInstance
, MAKEINTRESOURCE(IDB_SEEKFORWICON
), IMAGE_BITMAP
, 16, 16, LR_DEFAULTCOLOR
),
84 ImageList_AddMasked(hImageList
,
85 LoadImage(hInstance
, MAKEINTRESOURCE(IDB_FORWARDICON
), IMAGE_BITMAP
, 16, 16, LR_DEFAULTCOLOR
),
88 ImageList_Destroy((HIMAGELIST
)SendMessage(hToolBar
,
95 InitControls(HWND hwnd
)
97 INT NumButtons
= sizeof(Buttons
) / sizeof(Buttons
[0]);
101 /* Create trackbar */
102 hTrackBar
= CreateWindowEx(0,
105 TBS_ENABLESELRANGE
| WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_CLIPSIBLINGS
,
116 MessageBox(hwnd
, _T("TrackBar it is not created!"), NULL
, MB_OK
);
121 hToolBar
= CreateWindowEx(0,
124 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_CLIPSIBLINGS
|
125 TBSTYLE_FLAT
| CCS_BOTTOM
| TBSTYLE_TOOLTIPS
,
136 MessageBox(hwnd
, _T("ToolBar it is not created!"), NULL
, MB_OK
);
141 SendMessage(hToolBar
, TB_ADDBUTTONS
, NumButtons
, (LPARAM
)Buttons
);
145 IsSupportedFileExtension(LPTSTR lpFileName
)
147 TCHAR szExt
[MAX_PATH
];
148 INT DotPos
= 0, i
, j
;
150 for (i
= _tcslen(lpFileName
); i
>= 0; --i
)
152 if (lpFileName
[i
] == '.')
154 DotPos
= _tcslen(lpFileName
) - i
;
159 if (!DotPos
) return UNSUPPORTED_FILE
;
161 szExt
[DotPos
+ 1] = _T('\0');
162 for (i
= _tcslen(lpFileName
), j
= DotPos
; j
>= 0; --i
, --j
)
164 szExt
[j
] = lpFileName
[i
];
169 if (ExtTypes
[i
].uType
== UNSUPPORTED_FILE
)
171 return UNSUPPORTED_FILE
;
174 if (_tcscmp(ExtTypes
[i
].szExt
, szExt
) == 0)
176 return ExtTypes
[i
].uType
;
180 return UNSUPPORTED_FILE
;
186 MCI_GENERIC_PARMS mciGeneric
;
191 dwError
= mciSendCommand(wDeviceId
, MCI_CLOSE
, MCI_WAIT
, (DWORD_PTR
)&mciGeneric
);
192 if (dwError
) return dwError
;
200 OpenMciDevice(HWND hwnd
, LPTSTR lpType
, LPTSTR lpFileName
)
202 MCI_STATUS_PARMS mciStatus
;
203 MCI_OPEN_PARMS mciOpen
;
204 TCHAR szNewTitle
[MAX_PATH
];
212 mciOpen
.lpstrDeviceType
= lpType
;
213 mciOpen
.lpstrElementName
= lpFileName
;
214 mciOpen
.dwCallback
= 0;
215 mciOpen
.wDeviceID
= 0;
216 mciOpen
.lpstrAlias
= NULL
;
218 dwError
= mciSendCommand(0, MCI_OPEN
, MCI_OPEN_TYPE
| MCI_OPEN_ELEMENT
| MCI_WAIT
, (DWORD_PTR
)&mciOpen
);
221 MessageBox(0, _T("Can't open device! (1)"), NULL
, MB_OK
);
225 mciStatus
.dwItem
= MCI_STATUS_LENGTH
;
227 dwError
= mciSendCommand(mciOpen
.wDeviceID
, MCI_STATUS
, MCI_STATUS_ITEM
| MCI_WAIT
, (DWORD_PTR
)&mciStatus
);
230 MessageBox(0, _T("Can't open device! (2)"), NULL
, MB_OK
);
234 SendMessage(hTrackBar
, TBM_SETRANGE
, (WPARAM
) TRUE
, (LPARAM
) MAKELONG(1, mciStatus
.dwReturn
));
235 SendMessage(hTrackBar
, TBM_SETPAGESIZE
, 0, 10);
236 SendMessage(hTrackBar
, TBM_SETLINESIZE
, 0, 1);
237 SendMessage(hTrackBar
, TBM_SETPOS
, (WPARAM
) TRUE
, (LPARAM
) 1);
239 if (mciStatus
.dwReturn
< 10000)
241 SendMessage(hTrackBar
, TBM_SETTICFREQ
, (WPARAM
) 100, (LPARAM
) 0);
243 else if (mciStatus
.dwReturn
< 100000)
245 SendMessage(hTrackBar
, TBM_SETTICFREQ
, (WPARAM
) 1000, (LPARAM
) 0);
247 else if (mciStatus
.dwReturn
< 1000000)
249 SendMessage(hTrackBar
, TBM_SETTICFREQ
, (WPARAM
) 10000, (LPARAM
) 0);
253 SendMessage(hTrackBar
, TBM_SETTICFREQ
, (WPARAM
) 100000, (LPARAM
) 0);
256 _stprintf(szNewTitle
, _T("%s - %s"), szAppTitle
, lpFileName
);
257 SetWindowText(hwnd
, szNewTitle
);
259 MaxFilePos
= mciStatus
.dwReturn
;
260 wDeviceId
= mciOpen
.wDeviceID
;
262 _tcscpy(szPrevFile
, lpFileName
);
267 StopPlayback(HWND hwnd
)
271 SendMessage(hTrackBar
, TBM_SETPOS
, (WPARAM
) TRUE
, (LPARAM
) 1);
272 KillTimer(hwnd
, IDT_PLAYTIMER
);
278 SeekPlayback(HWND hwnd
, DWORD dwNewPos
)
280 MCI_SEEK_PARMS mciSeek
;
281 MCI_PLAY_PARMS mciPlay
;
286 mciSeek
.dwTo
= (DWORD_PTR
)dwNewPos
;
287 dwError
= mciSendCommand(wDeviceId
, MCI_SEEK
, MCI_WAIT
| MCI_TO
, (DWORD_PTR
)&mciSeek
);
290 MessageBox(hwnd
, _T("SeekPlayback: Can't seek!"), NULL
, MB_OK
);
293 mciPlay
.dwCallback
= (DWORD_PTR
)hwnd
;
294 dwError
= mciSendCommand(wDeviceId
, MCI_PLAY
, MCI_NOTIFY
, (DWORD_PTR
)&mciPlay
);
297 MessageBox(hwnd
, _T("SeekPlayback: Can't play!"), NULL
, MB_OK
);
303 SeekBackPlayback(HWND hwnd
)
305 MCI_STATUS_PARMS mciStatus
;
308 if (!bIsOpened
) return;
310 mciStatus
.dwItem
= MCI_STATUS_POSITION
;
311 mciSendCommand(wDeviceId
, MCI_STATUS
, MCI_STATUS_ITEM
, (DWORD_PTR
)&mciStatus
);
313 dwNewPos
= mciStatus
.dwReturn
- 1;
315 if((UINT
)dwNewPos
<= 1)
321 SeekPlayback(hwnd
, dwNewPos
);
326 SeekForwPlayback(HWND hwnd
)
328 MCI_STATUS_PARMS mciStatus
;
331 if (!bIsOpened
) return;
333 mciStatus
.dwItem
= MCI_STATUS_POSITION
;
334 mciSendCommand(wDeviceId
, MCI_STATUS
, MCI_STATUS_ITEM
, (DWORD_PTR
)&mciStatus
);
336 dwNewPos
= mciStatus
.dwReturn
+ 1;
338 if((UINT
)dwNewPos
>= MaxFilePos
)
344 SeekPlayback(hwnd
, dwNewPos
);
349 PausePlayback(HWND hwnd
)
351 MCI_GENERIC_PARMS mciGeneric
;
356 dwError
= mciSendCommand(wDeviceId
, MCI_PAUSE
, MCI_WAIT
, (DWORD_PTR
)&mciGeneric
);
359 MessageBox(hwnd
, _T("Can't pause!"), NULL
, MB_OK
);
366 ResumePlayback(HWND hwnd
)
368 MCI_GENERIC_PARMS mciGeneric
;
373 dwError
= mciSendCommand(wDeviceId
, MCI_RESUME
, MCI_WAIT
, (DWORD_PTR
)&mciGeneric
);
376 MessageBox(hwnd
, _T("Can't resume!"), NULL
, MB_OK
);
383 PlayTimerProc(HWND hwnd
, UINT uMsg
, UINT_PTR idEvent
, DWORD dwTime
)
385 MCI_STATUS_PARMS mciStatus
;
388 if (!bIsOpened
) KillTimer(hwnd
, IDT_PLAYTIMER
);
390 mciStatus
.dwItem
= MCI_STATUS_POSITION
;
391 mciSendCommand(wDeviceId
, MCI_STATUS
, MCI_STATUS_ITEM
, (DWORD_PTR
)&mciStatus
);
392 dwPos
= mciStatus
.dwReturn
;
394 if((UINT
)dwPos
>= MaxFilePos
)
400 SendMessage(hTrackBar
, TBM_SETPOS
, (WPARAM
) TRUE
, (LPARAM
) dwPos
);
405 PlayFile(HWND hwnd
, LPTSTR lpFileName
)
407 MCI_PLAY_PARMS mciPlay
;
408 TCHAR szLocalFileName
[MAX_PATH
];
412 if (lpFileName
== NULL
)
414 if (szPrevFile
[0] == _T('\0'))
417 _tcscpy(szLocalFileName
, szPrevFile
);
421 _tcscpy(szLocalFileName
, lpFileName
);
424 if (GetFileAttributes(szLocalFileName
) == INVALID_FILE_ATTRIBUTES
)
429 FileType
= IsSupportedFileExtension(szLocalFileName
);
433 case UNSUPPORTED_FILE
:
434 MessageBox(hwnd
, _T("Unsupported format!"), NULL
, MB_OK
);
437 OpenMciDevice(hwnd
, _T("waveaudio"), szLocalFileName
);
440 OpenMciDevice(hwnd
, _T("sequencer"), szLocalFileName
);
443 OpenMciDevice(hwnd
, _T("cdaudio"), szLocalFileName
);
446 OpenMciDevice(hwnd
, _T("avivideo"), szLocalFileName
);
450 SetTimer(hwnd
, IDT_PLAYTIMER
, 100, (TIMERPROC
) PlayTimerProc
);
452 dwError
= mciSendCommand(wDeviceId
, MCI_SEEK
, MCI_WAIT
| MCI_SEEK_TO_START
, 0);
454 mciPlay
.dwCallback
= (DWORD_PTR
)hwnd
;
456 mciPlay
.dwTo
= MaxFilePos
;
458 dwError
= mciSendCommand(wDeviceId
, MCI_PLAY
, MCI_NOTIFY
| MCI_FROM
| MCI_TO
, (DWORD_PTR
)&mciPlay
);
461 MessageBox(hwnd
, _T("Can't play!"), NULL
, MB_OK
);
466 OpenFileDialog(HWND hwnd
)
468 OPENFILENAME OpenFileName
;
469 TCHAR szFile
[MAX_PATH
+ 1] = _T("\0");
470 TCHAR szFilter
[MAX_PATH
], szCurrentDir
[MAX_PATH
];
472 ZeroMemory(&OpenFileName
, sizeof(OpenFileName
));
474 LoadString(hInstance
, IDS_ALL_TYPES_FILTER
, szFilter
, sizeof(szFilter
) / sizeof(TCHAR
));
476 if (!GetCurrentDirectory(sizeof(szCurrentDir
) / sizeof(TCHAR
), szCurrentDir
))
478 _tcscpy(szCurrentDir
, _T("c:\\"));
481 OpenFileName
.lStructSize
= sizeof(OpenFileName
);
482 OpenFileName
.hwndOwner
= hwnd
;
483 OpenFileName
.hInstance
= hInstance
;
484 OpenFileName
.lpstrFilter
= szFilter
;
485 OpenFileName
.lpstrFile
= szFile
;
486 OpenFileName
.nMaxFile
= sizeof(szFile
) / sizeof((szFile
)[0]);
487 OpenFileName
.lpstrInitialDir
= szCurrentDir
;
488 OpenFileName
.Flags
= OFN_FILEMUSTEXIST
| OFN_PATHMUSTEXIST
| OFN_HIDEREADONLY
| OFN_SHAREAWARE
;
489 OpenFileName
.lpstrDefExt
= _T("\0");
491 if (GetOpenFileName(&OpenFileName
))
493 PlayFile(hwnd
, OpenFileName
.lpstrFile
);
498 MainWndProc(HWND hwnd
, UINT Message
, WPARAM wParam
, LPARAM lParam
)
508 LPNMHDR pnmhdr
= (LPNMHDR
)lParam
;
510 switch (pnmhdr
->code
)
512 case TTN_GETDISPINFO
:
514 LPTOOLTIPTEXT lpttt
= (LPTOOLTIPTEXT
)lParam
;
515 UINT idButton
= (UINT
)lpttt
->hdr
.idFrom
;
520 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_PLAY
);
523 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_STOP
);
526 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_EJECT
);
529 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_BACKWARD
);
532 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_SEEKBACK
);
535 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_SEEKFORW
);
538 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_FORWARD
);
549 LPRECT pRect
= (LPRECT
)lParam
;
551 if (pRect
->right
- pRect
->left
< MAIN_WINDOW_MIN_WIDTH
)
552 pRect
->right
= pRect
->left
+ MAIN_WINDOW_MIN_WIDTH
;
554 if (pRect
->bottom
- pRect
->top
!= MAIN_WINDOW_HEIGHT
)
555 pRect
->bottom
= pRect
->top
+ MAIN_WINDOW_HEIGHT
;
565 if (hToolBar
&& hTrackBar
)
567 SendMessage(hToolBar
, TB_AUTOSIZE
, 0, 0);
568 SendMessage(hToolBar
, TB_GETITEMRECT
, 1, (LPARAM
)&Rect
);
570 Size
= GetSystemMetrics(SM_CYMENU
) + Rect
.bottom
;
571 MoveWindow(hTrackBar
, 0, 0, LOWORD(lParam
), HIWORD(lParam
) - Size
, TRUE
);
578 if (hTrackBar
== (HWND
) lParam
)
582 DWORD dwNewPos
= (DWORD
) SendMessage(hTrackBar
, TBM_GETPOS
, 0, 0);
583 SeekPlayback(hwnd
, dwNewPos
);
587 SendMessage(hTrackBar
, TBM_SETPOS
, TRUE
, 0);
594 switch (LOWORD(wParam
))
600 ResumePlayback(hwnd
);
606 if (szPrevFile
[0] == _T('\0'))
607 OpenFileDialog(hwnd
);
609 PlayFile(hwnd
, NULL
);
624 SeekBackPlayback(hwnd
);
628 SeekForwPlayback(hwnd
);
635 OpenFileDialog(hwnd
);
640 _tcscpy(szPrevFile
, _T("\0"));
645 HICON mplayIcon
= LoadIcon(hInstance
, MAKEINTRESOURCE(IDI_MAIN
));
646 ShellAbout(hwnd
, szAppTitle
, 0, mplayIcon
);
647 DeleteObject(mplayIcon
);
651 PostMessage(hwnd
, WM_CLOSE
, 0, 0);
662 return DefWindowProc(hwnd
, Message
, wParam
, lParam
);
666 _tWinMain(HINSTANCE hInst
, HINSTANCE hPrevInst
, LPTSTR lpCmdLine
, INT nCmdShow
)
668 WNDCLASSEX WndClass
= {0};
669 TCHAR szClassName
[] = _T("ROSMPLAY32");
675 LoadString(hInstance
, IDS_APPTITLE
, szAppTitle
, sizeof(szAppTitle
) / sizeof(TCHAR
));
677 WndClass
.cbSize
= sizeof(WNDCLASSEX
);
678 WndClass
.lpszClassName
= szClassName
;
679 WndClass
.lpfnWndProc
= MainWndProc
;
680 WndClass
.hInstance
= hInstance
;
681 WndClass
.style
= CS_HREDRAW
| CS_VREDRAW
;
682 WndClass
.hIcon
= LoadIcon(hInstance
, MAKEINTRESOURCE(IDI_MAIN
));
683 WndClass
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
684 WndClass
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
685 WndClass
.lpszMenuName
= MAKEINTRESOURCE(IDR_MAINMENU
);
687 RegisterClassEx(&WndClass
);
689 hwnd
= CreateWindow(szClassName
,
691 WS_SYSMENU
| WS_MINIMIZEBOX
| WS_THICKFRAME
| WS_OVERLAPPED
| WS_CAPTION
| WS_CLIPCHILDREN
,
702 ShowWindow(hwnd
, SW_SHOW
);
705 PlayFile(hwnd
, lpCmdLine
);
708 while (GetMessage(&msg
, NULL
, 0, 0))
710 TranslateMessage(&msg
);
711 DispatchMessage(&msg
);