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 HMENU hMainMenu
= NULL
;
16 TCHAR szAppTitle
[256] = _T("");
17 TCHAR szPrevFile
[MAX_PATH
] = _T("\0");
19 BOOL bIsOpened
= FALSE
;
20 BOOL bIsPaused
= FALSE
;
25 static const TBBUTTON Buttons
[] =
26 { /* iBitmap, idCommand, fsState, fsStyle, bReserved[2], dwData, iString */
27 {TBICON_PLAY
, IDC_PLAY
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0},
28 {TBICON_STOP
, IDC_STOP
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0},
29 {TBICON_EJECT
, IDC_EJECT
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0},
30 {15, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0}, 0, 0},
31 {TBICON_BACKWARD
, IDC_BACKWARD
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0},
32 {TBICON_SEEKBACK
, IDC_SEEKBACK
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0},
33 {TBICON_SEEKFORW
, IDC_SEEKFORW
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0},
34 {TBICON_FORWARD
, IDC_FORWARD
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0}
37 void EnableMenuItems(void)
39 MCI_GENERIC_PARMS mciGeneric
;
42 EnableMenuItem(hMainMenu
, IDM_CLOSE_FILE
, MF_BYCOMMAND
| MF_ENABLED
);
44 dwError
= mciSendCommand(wDeviceId
, MCI_CONFIGURE
, MCI_TEST
, (DWORD_PTR
)&mciGeneric
);
47 EnableMenuItem(hMainMenu
, IDM_DEVPROPS
, MF_BYCOMMAND
| MF_ENABLED
);
51 void DisableMenuItems(void)
53 EnableMenuItem(hMainMenu
, IDM_CLOSE_FILE
, MF_BYCOMMAND
| MF_GRAYED
);
54 EnableMenuItem(hMainMenu
, IDM_DEVPROPS
, MF_BYCOMMAND
| MF_GRAYED
);
58 SetImageList(HWND hwnd
)
60 HIMAGELIST hImageList
;
62 hImageList
= ImageList_Create(16, 16, ILC_MASK
| ILC_COLOR24
, 1, 1);
66 MessageBox(hwnd
, _T("ImageList it is not created!"), NULL
, MB_OK
);
70 ImageList_AddMasked(hImageList
,
71 LoadImage(hInstance
, MAKEINTRESOURCE(IDB_PLAYICON
), IMAGE_BITMAP
, 16, 16, LR_DEFAULTCOLOR
),
74 ImageList_AddMasked(hImageList
,
75 LoadImage(hInstance
, MAKEINTRESOURCE(IDB_STOPICON
), IMAGE_BITMAP
, 16, 16, LR_DEFAULTCOLOR
),
78 ImageList_AddMasked(hImageList
,
79 LoadImage(hInstance
, MAKEINTRESOURCE(IDB_EJECTICON
), IMAGE_BITMAP
, 16, 16, LR_DEFAULTCOLOR
),
82 ImageList_AddMasked(hImageList
,
83 LoadImage(hInstance
, MAKEINTRESOURCE(IDB_BACKWARDICON
), IMAGE_BITMAP
, 16, 16, LR_DEFAULTCOLOR
),
86 ImageList_AddMasked(hImageList
,
87 LoadImage(hInstance
, MAKEINTRESOURCE(IDB_SEEKBACKICON
), IMAGE_BITMAP
, 16, 16, LR_DEFAULTCOLOR
),
90 ImageList_AddMasked(hImageList
,
91 LoadImage(hInstance
, MAKEINTRESOURCE(IDB_SEEKFORWICON
), IMAGE_BITMAP
, 16, 16, LR_DEFAULTCOLOR
),
94 ImageList_AddMasked(hImageList
,
95 LoadImage(hInstance
, MAKEINTRESOURCE(IDB_FORWARDICON
), IMAGE_BITMAP
, 16, 16, LR_DEFAULTCOLOR
),
98 ImageList_Destroy((HIMAGELIST
)SendMessage(hToolBar
,
101 (LPARAM
)hImageList
));
105 ShowMCIError(HWND hwnd
, DWORD dwError
)
107 TCHAR szErrorMessage
[256];
108 TCHAR szTempMessage
[300];
110 if (mciGetErrorString(dwError
, szErrorMessage
, sizeof(szErrorMessage
) / sizeof(TCHAR
)) == FALSE
)
112 LoadString(hInstance
, IDS_DEFAULTMCIERRMSG
, szErrorMessage
, sizeof(szErrorMessage
) / sizeof(TCHAR
));
115 _stprintf(szTempMessage
, _T("MMSYS%u: %s"), dwError
, szErrorMessage
);
116 MessageBox(hwnd
, szTempMessage
, szAppTitle
, MB_OK
| MB_ICONEXCLAMATION
);
120 InitControls(HWND hwnd
)
122 INT NumButtons
= sizeof(Buttons
) / sizeof(Buttons
[0]);
124 InitCommonControls();
126 /* Create trackbar */
127 hTrackBar
= CreateWindowEx(0,
130 TBS_ENABLESELRANGE
| WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_CLIPSIBLINGS
,
141 MessageBox(hwnd
, _T("TrackBar it is not created!"), NULL
, MB_OK
);
146 hToolBar
= CreateWindowEx(0,
149 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
| WS_CLIPSIBLINGS
|
150 TBSTYLE_FLAT
| CCS_BOTTOM
| TBSTYLE_TOOLTIPS
,
161 MessageBox(hwnd
, _T("ToolBar it is not created!"), NULL
, MB_OK
);
166 SendMessage(hToolBar
, TB_ADDBUTTONS
, NumButtons
, (LPARAM
)Buttons
);
170 IsSupportedFileExtension(LPTSTR lpFileName
, LPTSTR lpDeviceName
, LPDWORD dwSize
)
176 pathend
= _tcsrchr(lpFileName
, '.');
185 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE
, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\MCI Extensions"), 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
187 if (RegQueryValueEx(hKey
, pathend
, NULL
, &dwType
, (LPBYTE
)lpDeviceName
, dwSize
) == ERROR_SUCCESS
)
190 if (dwType
!= REG_SZ
)
207 MCI_GENERIC_PARMS mciGeneric
;
212 dwError
= mciSendCommand(wDeviceId
, MCI_CLOSE
, MCI_WAIT
, (DWORD_PTR
)&mciGeneric
);
213 if (dwError
) return dwError
;
223 OpenMciDevice(HWND hwnd
, LPTSTR lpType
, LPTSTR lpFileName
)
225 MCI_STATUS_PARMS mciStatus
;
226 MCI_OPEN_PARMS mciOpen
;
227 TCHAR szNewTitle
[MAX_PATH
];
235 mciOpen
.lpstrDeviceType
= lpType
;
236 mciOpen
.lpstrElementName
= lpFileName
;
237 mciOpen
.dwCallback
= 0;
238 mciOpen
.wDeviceID
= 0;
239 mciOpen
.lpstrAlias
= NULL
;
241 dwError
= mciSendCommand(0, MCI_OPEN
, MCI_OPEN_TYPE
| MCI_OPEN_ELEMENT
| MCI_WAIT
, (DWORD_PTR
)&mciOpen
);
247 mciStatus
.dwItem
= MCI_STATUS_LENGTH
;
249 dwError
= mciSendCommand(mciOpen
.wDeviceID
, MCI_STATUS
, MCI_STATUS_ITEM
| MCI_WAIT
, (DWORD_PTR
)&mciStatus
);
255 SendMessage(hTrackBar
, TBM_SETRANGEMIN
, (WPARAM
) TRUE
, (LPARAM
) 1);
256 SendMessage(hTrackBar
, TBM_SETRANGEMAX
, (WPARAM
) TRUE
, (LPARAM
) mciStatus
.dwReturn
);
257 SendMessage(hTrackBar
, TBM_SETPAGESIZE
, 0, 10);
258 SendMessage(hTrackBar
, TBM_SETLINESIZE
, 0, 1);
259 SendMessage(hTrackBar
, TBM_SETPOS
, (WPARAM
) TRUE
, (LPARAM
) 1);
261 if (mciStatus
.dwReturn
< 10000)
263 SendMessage(hTrackBar
, TBM_SETTICFREQ
, (WPARAM
) 100, (LPARAM
) 0);
265 else if (mciStatus
.dwReturn
< 100000)
267 SendMessage(hTrackBar
, TBM_SETTICFREQ
, (WPARAM
) 1000, (LPARAM
) 0);
269 else if (mciStatus
.dwReturn
< 1000000)
271 SendMessage(hTrackBar
, TBM_SETTICFREQ
, (WPARAM
) 10000, (LPARAM
) 0);
275 SendMessage(hTrackBar
, TBM_SETTICFREQ
, (WPARAM
) 100000, (LPARAM
) 0);
278 _stprintf(szNewTitle
, _T("%s - %s"), szAppTitle
, lpFileName
);
279 SetWindowText(hwnd
, szNewTitle
);
281 MaxFilePos
= mciStatus
.dwReturn
;
282 wDeviceId
= mciOpen
.wDeviceID
;
284 _tcscpy(szPrevFile
, lpFileName
);
292 StopPlayback(HWND hwnd
)
296 SendMessage(hTrackBar
, TBM_SETPOS
, (WPARAM
) TRUE
, (LPARAM
) 1);
297 KillTimer(hwnd
, IDT_PLAYTIMER
);
303 SeekPlayback(HWND hwnd
, DWORD dwNewPos
)
305 MCI_SEEK_PARMS mciSeek
;
306 MCI_PLAY_PARMS mciPlay
;
311 mciSeek
.dwTo
= (DWORD_PTR
)dwNewPos
;
312 dwError
= mciSendCommand(wDeviceId
, MCI_SEEK
, MCI_WAIT
| MCI_TO
, (DWORD_PTR
)&mciSeek
);
315 ShowMCIError(hwnd
, dwError
);
318 mciPlay
.dwCallback
= (DWORD_PTR
)hwnd
;
319 dwError
= mciSendCommand(wDeviceId
, MCI_PLAY
, MCI_NOTIFY
, (DWORD_PTR
)&mciPlay
);
322 ShowMCIError(hwnd
, dwError
);
328 SeekBackPlayback(HWND hwnd
)
330 MCI_STATUS_PARMS mciStatus
;
333 if (!bIsOpened
) return;
335 mciStatus
.dwItem
= MCI_STATUS_POSITION
;
336 mciSendCommand(wDeviceId
, MCI_STATUS
, MCI_STATUS_ITEM
, (DWORD_PTR
)&mciStatus
);
338 dwNewPos
= mciStatus
.dwReturn
- 1;
340 if((UINT
)dwNewPos
<= 1)
346 SeekPlayback(hwnd
, dwNewPos
);
351 SeekForwPlayback(HWND hwnd
)
353 MCI_STATUS_PARMS mciStatus
;
356 if (!bIsOpened
) return;
358 mciStatus
.dwItem
= MCI_STATUS_POSITION
;
359 mciSendCommand(wDeviceId
, MCI_STATUS
, MCI_STATUS_ITEM
, (DWORD_PTR
)&mciStatus
);
361 dwNewPos
= mciStatus
.dwReturn
+ 1;
363 if((UINT
)dwNewPos
>= MaxFilePos
)
369 SeekPlayback(hwnd
, dwNewPos
);
374 PausePlayback(HWND hwnd
)
376 MCI_GENERIC_PARMS mciGeneric
;
381 dwError
= mciSendCommand(wDeviceId
, MCI_PAUSE
, MCI_WAIT
, (DWORD_PTR
)&mciGeneric
);
384 ShowMCIError(hwnd
, dwError
);
391 ResumePlayback(HWND hwnd
)
393 MCI_GENERIC_PARMS mciGeneric
;
398 dwError
= mciSendCommand(wDeviceId
, MCI_RESUME
, MCI_WAIT
, (DWORD_PTR
)&mciGeneric
);
401 ShowMCIError(hwnd
, dwError
);
408 ShowDeviceProperties(HWND hwnd
)
410 MCI_GENERIC_PARMS mciGeneric
;
413 dwError
= mciSendCommand(wDeviceId
, MCI_CONFIGURE
, MCI_WAIT
, (DWORD_PTR
)&mciGeneric
);
416 ShowMCIError(hwnd
, dwError
);
421 PlayTimerProc(HWND hwnd
, UINT uMsg
, UINT_PTR idEvent
, DWORD dwTime
)
423 MCI_STATUS_PARMS mciStatus
;
426 if (!bIsOpened
) KillTimer(hwnd
, IDT_PLAYTIMER
);
428 mciStatus
.dwItem
= MCI_STATUS_POSITION
;
429 mciSendCommand(wDeviceId
, MCI_STATUS
, MCI_STATUS_ITEM
, (DWORD_PTR
)&mciStatus
);
430 dwPos
= mciStatus
.dwReturn
;
432 if((UINT
)dwPos
>= MaxFilePos
)
438 SendMessage(hTrackBar
, TBM_SETPOS
, (WPARAM
) TRUE
, (LPARAM
) dwPos
);
443 PlayFile(HWND hwnd
, LPTSTR lpFileName
)
445 MCI_PLAY_PARMS mciPlay
;
446 TCHAR szLocalFileName
[MAX_PATH
];
447 TCHAR szDeviceName
[MAX_PATH
];
451 if (lpFileName
== NULL
)
453 if (szPrevFile
[0] == _T('\0'))
456 _tcscpy(szLocalFileName
, szPrevFile
);
460 _tcscpy(szLocalFileName
, lpFileName
);
463 if (GetFileAttributes(szLocalFileName
) == INVALID_FILE_ATTRIBUTES
)
468 dwSize
= sizeof(szDeviceName
) - 2;
469 _tcsnset(szDeviceName
, _T('\0'), dwSize
/ sizeof(TCHAR
));
471 if (!IsSupportedFileExtension(szLocalFileName
, szDeviceName
, &dwSize
))
473 TCHAR szErrorMessage
[256];
475 LoadString(hInstance
, IDS_UNKNOWNFILEEXT
, szErrorMessage
, sizeof(szErrorMessage
) / sizeof(TCHAR
));
476 MessageBox(hwnd
, szErrorMessage
, szAppTitle
, MB_OK
| MB_ICONEXCLAMATION
);
480 mciError
= OpenMciDevice(hwnd
, szDeviceName
, szLocalFileName
);
483 ShowMCIError(hwnd
, mciError
);
487 SetTimer(hwnd
, IDT_PLAYTIMER
, 100, (TIMERPROC
) PlayTimerProc
);
489 mciSendCommand(wDeviceId
, MCI_SEEK
, MCI_WAIT
| MCI_SEEK_TO_START
, 0);
491 mciPlay
.dwCallback
= (DWORD_PTR
)hwnd
;
493 mciPlay
.dwTo
= MaxFilePos
;
495 mciError
= mciSendCommand(wDeviceId
, MCI_PLAY
, MCI_NOTIFY
| MCI_FROM
/*| MCI_TO*/, (DWORD_PTR
)&mciPlay
);
498 ShowMCIError(hwnd
, mciError
);
503 OpenFileDialog(HWND hwnd
)
505 OPENFILENAME OpenFileName
;
506 TCHAR szFile
[MAX_PATH
+ 1] = _T("\0");
507 TCHAR szFilter
[MAX_PATH
], szCurrentDir
[MAX_PATH
];
509 ZeroMemory(&OpenFileName
, sizeof(OpenFileName
));
511 LoadString(hInstance
, IDS_ALL_TYPES_FILTER
, szFilter
, sizeof(szFilter
) / sizeof(TCHAR
));
513 if (!GetCurrentDirectory(sizeof(szCurrentDir
) / sizeof(TCHAR
), szCurrentDir
))
515 _tcscpy(szCurrentDir
, _T("c:\\"));
518 OpenFileName
.lStructSize
= sizeof(OpenFileName
);
519 OpenFileName
.hwndOwner
= hwnd
;
520 OpenFileName
.hInstance
= hInstance
;
521 OpenFileName
.lpstrFilter
= szFilter
;
522 OpenFileName
.lpstrFile
= szFile
;
523 OpenFileName
.nMaxFile
= sizeof(szFile
) / sizeof((szFile
)[0]);
524 OpenFileName
.lpstrInitialDir
= szCurrentDir
;
525 OpenFileName
.Flags
= OFN_FILEMUSTEXIST
| OFN_PATHMUSTEXIST
| OFN_HIDEREADONLY
| OFN_SHAREAWARE
;
526 OpenFileName
.lpstrDefExt
= _T("\0");
528 if (GetOpenFileName(&OpenFileName
))
530 PlayFile(hwnd
, OpenFileName
.lpstrFile
);
535 MainWndProc(HWND hwnd
, UINT Message
, WPARAM wParam
, LPARAM lParam
)
541 hMainMenu
= GetMenu(hwnd
);
547 TCHAR droppedfile
[MAX_PATH
];
549 drophandle
= (HDROP
)wParam
;
550 DragQueryFile(drophandle
, 0, droppedfile
, sizeof(droppedfile
) / sizeof(TCHAR
));
551 DragFinish(drophandle
);
552 PlayFile(hwnd
, droppedfile
);
558 LPNMHDR pnmhdr
= (LPNMHDR
)lParam
;
560 switch (pnmhdr
->code
)
562 case TTN_GETDISPINFO
:
564 LPTOOLTIPTEXT lpttt
= (LPTOOLTIPTEXT
)lParam
;
565 UINT idButton
= (UINT
)lpttt
->hdr
.idFrom
;
570 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_PLAY
);
573 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_STOP
);
576 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_EJECT
);
579 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_BACKWARD
);
582 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_SEEKBACK
);
585 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_SEEKFORW
);
588 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_FORWARD
);
599 LPRECT pRect
= (LPRECT
)lParam
;
601 if (pRect
->right
- pRect
->left
< MAIN_WINDOW_MIN_WIDTH
)
602 pRect
->right
= pRect
->left
+ MAIN_WINDOW_MIN_WIDTH
;
604 if (pRect
->bottom
- pRect
->top
!= MAIN_WINDOW_HEIGHT
)
605 pRect
->bottom
= pRect
->top
+ MAIN_WINDOW_HEIGHT
;
615 if (hToolBar
&& hTrackBar
)
617 SendMessage(hToolBar
, TB_AUTOSIZE
, 0, 0);
618 SendMessage(hToolBar
, TB_GETITEMRECT
, 1, (LPARAM
)&Rect
);
620 Size
= GetSystemMetrics(SM_CYMENU
) + Rect
.bottom
;
621 MoveWindow(hTrackBar
, 0, 0, LOWORD(lParam
), HIWORD(lParam
) - Size
, TRUE
);
628 if (hTrackBar
== (HWND
) lParam
)
632 DWORD dwNewPos
= (DWORD
) SendMessage(hTrackBar
, TBM_GETPOS
, 0, 0);
633 SeekPlayback(hwnd
, dwNewPos
);
637 SendMessage(hTrackBar
, TBM_SETPOS
, TRUE
, 0);
644 switch (LOWORD(wParam
))
650 ResumePlayback(hwnd
);
656 if (szPrevFile
[0] == _T('\0'))
657 OpenFileDialog(hwnd
);
659 PlayFile(hwnd
, NULL
);
674 SeekBackPlayback(hwnd
);
678 SeekForwPlayback(hwnd
);
685 OpenFileDialog(hwnd
);
690 _tcscpy(szPrevFile
, _T("\0"));
694 ShowDeviceProperties(hwnd
);
698 ShellExecute(hwnd
, NULL
, _T("SNDVOL32.EXE"), NULL
, NULL
, SW_SHOWNORMAL
);
703 HICON mplayIcon
= LoadIcon(hInstance
, MAKEINTRESOURCE(IDI_MAIN
));
704 ShellAbout(hwnd
, szAppTitle
, 0, mplayIcon
);
705 DeleteObject(mplayIcon
);
709 PostMessage(hwnd
, WM_CLOSE
, 0, 0);
720 return DefWindowProc(hwnd
, Message
, wParam
, lParam
);
724 _tWinMain(HINSTANCE hInst
, HINSTANCE hPrevInst
, LPTSTR lpCmdLine
, INT nCmdShow
)
726 WNDCLASSEX WndClass
= {0};
727 TCHAR szClassName
[] = _T("ROSMPLAY32");
734 LoadString(hInstance
, IDS_APPTITLE
, szAppTitle
, sizeof(szAppTitle
) / sizeof(TCHAR
));
736 WndClass
.cbSize
= sizeof(WNDCLASSEX
);
737 WndClass
.lpszClassName
= szClassName
;
738 WndClass
.lpfnWndProc
= MainWndProc
;
739 WndClass
.hInstance
= hInstance
;
740 WndClass
.style
= CS_HREDRAW
| CS_VREDRAW
;
741 WndClass
.hIcon
= LoadIcon(hInstance
, MAKEINTRESOURCE(IDI_MAIN
));
742 WndClass
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
743 WndClass
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
744 WndClass
.lpszMenuName
= MAKEINTRESOURCE(IDR_MAINMENU
);
746 RegisterClassEx(&WndClass
);
748 hwnd
= CreateWindow(szClassName
,
750 WS_SYSMENU
| WS_MINIMIZEBOX
| WS_THICKFRAME
| WS_OVERLAPPED
| WS_CAPTION
| WS_CLIPCHILDREN
,
760 DragAcceptFiles(hwnd
, TRUE
);
764 dwError
= SearchPath(NULL
, _T("SNDVOL32.EXE"), NULL
, 0, NULL
, NULL
);
767 EnableMenuItem(hMainMenu
, IDM_VOLUMECTL
, MF_BYCOMMAND
| MF_GRAYED
);
771 ShowWindow(hwnd
, SW_SHOW
);
774 PlayFile(hwnd
, lpCmdLine
);
777 while (GetMessage(&msg
, NULL
, 0, 0))
779 TranslateMessage(&msg
);
780 DispatchMessage(&msg
);