www.pudn.com > DXPlayer.rar > dxplayer.cpp
#include#include #include #include #include #include "dxplayer.h" #include "Commctrl.h" #include "resource.h" //#define _DEBUG // //Globe varible // HWND g_hwndApp=0; HWND g_hTrackbar=0; HINSTANCE g_hInstance=0; TCHAR g_szFileName[MAX_PATH]={0}; //!not do like: LPTSTR g_szFileName; UINT_PTR g_TimerID=0; BOOL g_bCanSeek=FALSE; TCHAR szClassName[]=TEXT("DirectShow Window\n"); TCHAR szApplicationName[]=TEXT("DirectShow Player\n"); IGraphBuilder *pGB; IMediaEventEx *pME; IMediaControl *pMC; IMediaSeeking *pMS; IMediaPosition *pMP; //IMediaEventSink *PMESink; IBaseFilter *pBFilter; IBasicVideo *pBV; IBasicAudio *pBA; //control volum for IVideoWindow *pVW; // //the main window message loop // LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam) { static OAFilterState OAState; static BOOL bStartOfDrag=TRUE; short int Action; HRESULT hr; RECT rect; switch(msg) { case WM_CREATE: break; case WM_DESTROY: PostQuitMessage(0); break; case WM_KEYDOWN: switch(wParam) { case VK_ESCAPE: ToggleFullScreen(); break; case VK_SPACE: break; } break; case WM_GRAPHNOTIFY: HandleGraphEvent(); break; case WM_COMMAND: switch(wParam) { case ID_MENU_OPEN: if(g_psCurrent!=Init) OnClose(); OnOpen(); break; case ID_MENU_FULLSCREEN: ToggleFullScreen(); break; case ID_MENU_CLOSE: OnClose(); break; case ID_MENU_RUN: if(g_psCurrent!=Running&&pMC) //if(g_psCurrent==Pause) { JIF(pMC->Run()); if(SUCCEEDED(hr)) g_psCurrent=Running; } break; case ID_MENU_PAUSE: if(pMC) if(g_psCurrent!=Pause) { JIF(pMC->Pause()); if(SUCCEEDED(hr)) g_psCurrent=Pause; } break; case ID_MENU_STOP: LONGLONG pos=0; if(pMC) { if(pMS) pMS->SetPositions(&pos,AM_SEEKING_AbsolutePositioning, NULL,AM_SEEKING_NoPositioning); JIF(pMC->Stop()); if(SUCCEEDED(hr)) g_psCurrent=Stopped; } break; } break; case WM_PAINT: //keep the trackbar all at the buttom of window GetClientRect(g_hwndApp,&rect); SetWindowPos(g_hTrackbar,NULL, rect.left,rect.bottom-TRACKBAR_HEIGHT-BUTTOM_BLANK_HEIGHT, rect.right-rect.left,TRACKBAR_HEIGHT,SWP_NOOWNERZORDER); break; case WM_TIMER: if(wParam==ID_TIMER_SEEK) { //ASSERT(g_bCanSeek==TRUE); // not compiled in VC/debug mode ? if(!g_bCanSeek) break; REFERENCE_TIME timeNow; if (SUCCEEDED(pMS->GetCurrentPosition(&timeNow))) { long sliderTick = (long)((timeNow * TRACK_LEN)/g_lDuration); SendMessage( g_hTrackbar, TBM_SETPOS, TRUE, sliderTick ); } } break; case WM_HSCROLL: Action=LOWORD(wParam); if(Action==TB_ENDTRACK||Action==TB_THUMBTRACK) { DWORD dwPosition=SendMessage(g_hTrackbar,TBM_GETPOS,0,0); //Pause video/audio whiling drag the trackbar if(bStartOfDrag) { if(pMC) pMC->GetState(10,&OAState); bStartOfDrag=FALSE; pMC->Pause(); } //Update the position continuously REFERENCE_TIME newTime = (g_lDuration/TRACK_LEN) * dwPosition; pMS->SetPositions(&newTime, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning); if(Action==TB_ENDTRACK) { if(OAState==State_Stopped) pMC->Stop(); else if(OAState==State_Running) pMC->Run(); bStartOfDrag=TRUE; } } break; case WM_SIZING: /* LPRECT lpRect; //short int nWidth=LOWORD(lParam); //short int nHeight=HIWORD(lParam); UNIT fwSide=wParam; lpRect=(LPRECT)lParam; break; if(nWidth<=g_xMinPlayWnd ||nHeight<=g_yMinPlayWnd) //SetWindowPos(g_hwndApp,NULL,0,0,g_xMinPlayWnd,g_yMinPlayWnd,SWP_NOMOVE); return 0L; */ break; } return DefWindowProc(hwnd,msg,wParam,lParam); } // //Create the main window // int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPSTR lpCmdLine,int nShowCmd) { MSG msg; WNDCLASS wc; HRESULT hr=CoInitialize(NULL); if(FAILED(hr)) ErrorExit("Failed to initialize COM"); if(lpCmdLine[0]!='\0') { //g_szFileName=lpCmdLine; _tcsncpy(g_szFileName,lpCmdLine,sizeof(lpCmdLine)/sizeof(lpCmdLine[0])); } wc.style=CS_VREDRAW|CS_HREDRAW; wc.cbClsExtra=0; wc.cbWndExtra=0; wc.lpfnWndProc=MainWndProc; wc.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH); wc.hCursor=LoadCursor(NULL,IDC_ARROW); wc.hIcon=NULL; g_hInstance=wc.hInstance=hInstance; wc.lpszClassName=szClassName; //#define MAKEINTRESOURCE(i) (LPTSTR) ((DWORD) ((WORD) (i))) //Convert the 16 bit unsigned int to 32 bit unsigned int wc.lpszMenuName=MAKEINTRESOURCE(IDR_MAINMENU); if(!RegisterClass(&wc)) { CoUninitialize(); ErrorExit("Couldn't Register window class! The application must quit!\n"); } g_hwndApp=CreateWindow(szClassName,szApplicationName, WS_OVERLAPPEDWINDOW | WS_CAPTION | WS_CLIPCHILDREN, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, 0,0,g_hInstance,0); if(g_hwndApp) { g_hTrackbar= CreateWindowEx( 0, TRACKBAR_CLASS, "Trackbar Control", WS_CHILD | WS_VISIBLE | TBS_ENABLESELRANGE | TBS_AUTOTICKS | TBS_NOTICKS | TBS_HORZ|TBS_FIXEDLENGTH|TBS_NOTICKS, 0, 0, CW_USEDEFAULT,CW_USEDEFAULT , g_hwndApp, //(HMENU)IDC_TRACK_VOLUME, (HMENU)ID_TRACKBAR, g_hInstance, NULL); EnableWindow(g_hTrackbar,FALSE); SendMessage(g_hTrackbar, TBM_SETRANGE, TRUE, MAKELONG(0, 100)); ShowWindow(g_hwndApp,nShowCmd); UpdateWindow(g_hwndApp); while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return ((int)msg.wParam); } return 0L; } void Msg(LPCSTR szFormat,...) { TCHAR szBuffer[1024]; const size_t NUMCHARS=sizeof(szBuffer)/sizeof(szBuffer[0]); const LASTCHAR=NUMCHARS-1; //format the input string; va_list args; va_start(args,szFormat); _vsnprintf(szBuffer,NUMCHARS-1,szFormat,args); va_end(args); szBuffer[LASTCHAR]=TEXT('\0'); MessageBox(NULL,szBuffer,TEXT("DirectShow Player"),MB_OK); } HRESULT Play(LPCSTR szFileName) { HRESULT hr; WCHAR wFile[MAX_PATH]; //Only Unicode Supported if(!szFileName) return E_POINTER; UpdateWindow(g_hwndApp); //wcsncpy(wFile, T2W(szFileName), sizeof(wFile)/sizeof(wFile[0])); MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,szFileName,-1,wFile,sizeof(wFile)/sizeof(wFile[0])-1); wFile[MAX_PATH-1] = 0; LIF(CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,IID_IGraphBuilder,(void **)&pGB)); JIF(pGB->RenderFile(wFile,NULL)); if(SUCCEEDED(hr)) { LIF(pGB->QueryInterface(IID_IMediaControl,(void **)&pMC)); //PGB->QueryInterface(IID_IMediaEventSink,(void **)&pMESink); LIF(pGB->QueryInterface(IID_IMediaEventEx,(void **)&pME)); LIF(pGB->QueryInterface(IID_IMediaSeeking,(void **)&pMS)); LIF(pGB->QueryInterface(IID_IMediaPosition,(void **)&pMP)); //if Audio-only file, the pVW is null? LIF(pGB->QueryInterface(IID_IVideoWindow,(void **)&pVW)); LIF(pGB->QueryInterface(IID_IBasicVideo,(void **)&pBV)); LIF(pGB->QueryInterface(IID_IBasicAudio,(void **)&pBA)); LIF(pME->SetNotifyWindow((OAHWND)g_hwndApp,WM_GRAPHNOTIFY,0)); CheckMediaType(szFileName); if(g_MediaType == AUDIO_MEDIA) { InitAudioWindow(); } else { JIF(pVW->put_Owner((OAHWND)g_hwndApp)); JIF(pVW->put_WindowStyle(WS_CHILD|WS_CLIPSIBLINGS|WS_CLIPCHILDREN)); InitVidoWindow(1,1); } InitTrackbar(); LIF(pMC->Run()); g_bCanSeek=CheckMediaSeekable(); if(g_bCanSeek) { StopTimer(); g_TimerID=SetTimer(g_hwndApp,ID_TIMER_SEEK,TIMER_FREQ,(TIMERPROC)NULL); if(!g_TimerID) { //failed to SetTimer, then disable the slider(trackbar) InitTrackbar(); } } g_psCurrent=Running; } UpdateWindow(g_hwndApp); SetFocus(g_hwndApp); return hr; } HRESULT InitVidoWindow(int nMultipier,int nDivider) { //default mode: 100%, at the center of client rectangle LONG lHeight,lWidth; HRESULT hr; RECT rect; JIF(pBV->GetVideoSize(&lWidth,&lHeight)); lWidth=lWidth*nMultipier/nDivider; lHeight=lHeight*nMultipier/nDivider; g_xMinPlayWnd=lWidth; g_yMinPlayWnd=lHeight; /* int nTitleHeight = GetSystemMetrics(SM_CYCAPTION); int nBorderWidth = GetSystemMetrics(SM_CXBORDER); int nBorderHeight = GetSystemMetrics(SM_CYBORDER); */ //changes the size, position, and Z order of a child, //pop-up, or top-level window SetWindowPos(g_hwndApp,NULL,0,0, 2*lWidth,2*lHeight, SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_SHOWWINDOW ); GetClientRect(g_hwndApp,&rect); JIF(pVW->SetWindowPosition((rect.right-rect.left)/4, (rect.bottom-rect.top)/4,lWidth,lHeight)); return hr; } HRESULT InitAudioWindow() { //可以有选择性的播放动画(或文字) g_xMinPlayWnd=AUDIO_DEFAULT_WIDTH; g_yMinPlayWnd=AUDIO_DEFAULT_HEIGHT; SetWindowPos(g_hwndApp,NULL,0,0, AUDIO_DEFAULT_WIDTH,AUDIO_DEFAULT_HEIGHT, SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_SHOWWINDOW); return S_OK; } HRESULT InitDefPlayWindow() { g_xMinPlayWnd=PLAYERWND_DEFAULT_WIDTH; g_yMinPlayWnd=PLAYERWND_DEFAULT_HEIGHT; SetWindowPos(g_hwndApp,NULL,0,0, PLAYERWND_DEFAULT_WIDTH,PLAYERWND_DEFAULT_HEIGHT, SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_SHOWWINDOW); InitTrackbar(); return S_OK; } HRESULT ToggleFullScreen() { HRESULT hr; LONG lMode; static HWND hDrain=0; //Audio-only file not support FullScreen Mode! if((g_MediaType==AUDIO_MEDIA)||(!pVW)) return S_OK; //Get current mode LIF(pVW->get_FullScreenMode(&lMode)); if(lMode=OAFALSE) { //Save current message drain JIF(pVW->get_MessageDrain((OAHWND *) &hDrain)); // Set message drain to application main window JIF(pVW->put_MessageDrain((OAHWND) g_hwndApp)); // Switch to full-screen mode lMode = OATRUE; LIF(pVW->put_FullScreenMode(lMode)); g_bFullScreen = TRUE; } else { // Switch back to windowed mode lMode = OAFALSE; JIF(pVW->put_FullScreenMode(lMode)); // Undo change of message drain LIF(pVW->put_MessageDrain((OAHWND) hDrain)); // Reset video window JIF(pVW->SetWindowForeground(-1)); // Reclaim keyboard focus for player application UpdateWindow(g_hwndApp); SetForegroundWindow(g_hwndApp); SetFocus(g_hwndApp); g_bFullScreen = FALSE; } return hr; } /* HRESULT CheckMediaType(AM_MEDIA_TYPE *pmt) { if(pmt==NULL) return E_POINTER; } */ HRESULT HandleGraphEvent() { HRESULT hr; long eCode,eParam1,eParam2; if(!pME||!pMS) return S_OK; //because the message loop are asynchronize, //use loop to retrieve events from events queue. while(SUCCEEDED(hr=pME->GetEvent(&eCode,&eParam1,&eParam2,0))) { switch(eCode) { case WM_DISPLAYCHANGE: break; case EC_COMPLETE: LONGLONG pos=0; #ifdef _DEBUG _TEST("is over"); #endif //the media type must support rand-seeking //hr=pMS->SetPositions(&pos,AM_SEEKING_AbsolutePositioning, // &pos,AM_SEEKING_AbsolutePositioning); hr=pMS->SetPositions(&pos,AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning); pMC->StopWhenReady(); UpdateWindow(g_hwndApp); if(FAILED(hr)) { //Some Custom filter may not implement seeking interface //In this case,just stop and restart for the same effect. if(FAILED(pMC->Stop())){break;} if(FAILED(pMC->Run())){break;} } break; } pME->FreeEventParams(eCode,eParam1,eParam2); } return hr; } void CleanUpInterface() { HRESULT hr; if(pVW) { JIF(pVW->put_Visible(OAFALSE)); JIF(pVW->put_Owner(OAHWND(NULL))); } //Disable envents callback if(pME) hr=pME->SetNotifyWindow(OAHWND(NULL),0,0); //StopTimer(); SafeRelease(pMC); SafeRelease(pME); SafeRelease(pMS); SafeRelease(pMP); SafeRelease(pBV); SafeRelease(pBA); SafeRelease(pVW); SafeRelease(pBFilter); SafeRelease(pGB); } /***************************Begin Trackbar***************************************/ //implementing a seek bar, must include "Commctrl.h" void InitTrackbar() { LONG InitPos=0; //if use CSliderCtrl SliderCtrl(MFC),must include //Initialize the trackbar range(0-100),but disable //the control until the user open a media file //g_hTrackbar=GetDlgItem(g_hwndApp,ID_TRACKBAR) //sendmessage to g_hTrackbar , not to g_hwndApp? SendMessage(g_hTrackbar,TBM_SETRANGE,TRUE,MAKELONG(0,TRACK_LEN)); SendMessage(g_hTrackbar,TBM_SETPOS,TRUE,InitPos); EnableWindow(g_hTrackbar,FALSE); } BOOL CheckMediaSeekable(void) { //Determine if the source media is seekable BOOL bCanSeek=FALSE; HRESULT hr; if(!pMS) return bCanSeek; DWORD dwCaps=AM_SEEKING_CanSeekAbsolute|AM_SEEKING_CanGetDuration; bCanSeek=(S_OK==pMS->CheckCapabilities(&dwCaps)); if(bCanSeek) { hr=pMS->GetDuration(&g_lDuration); if(SUCCEEDED(hr)) EnableWindow(g_hTrackbar,TRUE); } return bCanSeek; } void StopTimer() { if(g_TimerID!=0) { KillTimer(g_hwndApp,g_TimerID); g_TimerID=0; } } /************************End Trackbar***************************/ BOOL GetMediaFileName(LPTSTR szFileName) { static OPENFILENAME ofn={0}; static BOOL bSetInitialDir = FALSE; // Reset filename *szFileName = 0; // Fill in standard structure fields ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = g_hwndApp; ofn.lpstrFilter = FILE_FILTER_TEXT; ofn.lpstrCustomFilter = NULL; ofn.nFilterIndex = 1; ofn.lpstrFile = szFileName; ofn.nMaxFile = MAX_PATH; ofn.lpstrTitle = TEXT("Open Media File...\0"); ofn.lpstrFileTitle = NULL; ofn.lpstrDefExt = TEXT("*\0"); ofn.Flags = OFN_FILEMUSTEXIST | OFN_READONLY | OFN_PATHMUSTEXIST; // Remember the path of the first selected file if (bSetInitialDir == FALSE) { ofn.lpstrInitialDir = DEFAULT_MEDIA_PATH; bSetInitialDir = TRUE; } else ofn.lpstrInitialDir = NULL; // Create the standard file open dialog and return its result return GetOpenFileName((LPOPENFILENAME)&ofn); } void OnOpen() { HRESULT hr; TCHAR szFileName[MAX_PATH]={0}; //before open the file dialog, may init the default play window InitDefPlayWindow(); ShowWindow(g_hwndApp,SW_SHOWNORMAL); SetForegroundWindow(g_hwndApp); //open the file dialog if(!GetMediaFileName(szFileName)) { DWORD dwDlgErr=CommDlgExtendedError(); // Don't show output if user cancelled the selection (no dlg error) if (dwDlgErr) { Msg(TEXT("GetClipFileName Failed! Error=0x%x\r\n"), GetLastError()); } return; } // This sample does not offer support for Windows Media playback. // The PlayWndASF and Jukebox samples demonstrate how to add a // Windows Media certificate handler to your app, along with giving // example code to load and connect the ASF Reader source filter. // To prevent problems with using the older (default) ASF reader here, // simply disable loading of ASF,WMA,WMV files. /* if (IsWindowsMediaFile(szFilename)) { Msg(TEXT("Windows Media files (ASF,WMV,WMA) are not supported by this application.\n\n") TEXT("To play Windows Media files, use the PlayWndASF or Jukebox samples.\0")); return; } lstrcpy(g_szFileName, szFilename); } */ lstrcpy(g_szFileName,szFileName); // Reset status variables if(g_psCurrent!=Init) g_psCurrent = Stopped; //g_lVolume = VOLUME_FULL; // Start playing the media file hr = Play(g_szFileName); if(FAILED(hr)){ return; OnClose(); } return; } //再次打开(OnOPen,与再次关闭OnClose()都会出错,查证!) void OnClose() { HRESULT hr; if(pMC) JIF(pMC->Stop()); CleanUpInterface(); StopTimer(); InitTrackbar(); g_psCurrent=Stopped; g_bFullScreen=FALSE; g_szFileName[0]=TEXT('\0'); RECT rect; GetClientRect(g_hwndApp,&rect); InvalidateRect(g_hwndApp,&rect,TRUE); //update the Title g_psCurrent=Init; InitDefPlayWindow(); UpdateWindow(g_hwndApp); } HRESULT CheckMediaType(LPCSTR szFileName) { int pos=0; //TCHAR szMatch[MAX_PATH+1]={0}; TCHAR szEXEName[MAX_PATH+1]={0}; size_t nums=0; if(!szFileName) return E_POINTER; //!!may not support UNICODE character. nums=strlen(szFileName)-1; for(int i=nums;i>=0;i--) { if (szFileName[i]=='.') break; szEXEName[pos++]=szFileName[i]; } szEXEName[pos]=TEXT('\0'); //check the media type by the EXE name //use strcmp() may cause error while UNICODE char if( !strcmp(szEXEName,TEXT("3pm"))||!strcmp(szEXEName,TEXT("amw"))||!strcmp(szEXEName,TEXT("apm")) ||!strcmp(szEXEName,TEXT("2pm"))||!strcmp(szEXEName,TEXT("ua"))||!strcmp(szEXEName,TEXT("fia")) ||!strcmp(szEXEName,TEXT("ffia"))||!strcmp(szEXEName,TEXT("vaw"))||!strcmp(szEXEName,TEXT("dim")) ||!strcmp(szEXEName,TEXT("idim"))||!strcmp(szEXEName,TEXT("imr"))||!strcmp(szEXEName,TEXT("dns"))) { g_MediaType=AUDIO_MEDIA; return S_OK; } if(!strcmp(szEXEName,TEXT("gpj"))||!strcmp(szEXEName,TEXT("fig")) ||!strcmp(szEXEName,TEXT("pmb"))||!strcmp(szEXEName,TEXT("agt"))) { g_MediaType=STATIC_PICTURE; return S_OK; } //others return Video mode g_MediaType=VIDEO_MEDIA; return S_OK; /* * else if( * !strcmp(szEXENAME,"iva")||!strcmp(szEXENAME,"tq")||!strcmp(szEXENAME,"vom") * ||!strcmp(szEXENAME,"gpm")||!strcmp(szEXENAME,"gepm")||!strcmp(szEXENAME,"v1m") * ||!strcmp(szEXENAME,"gpj")||!strcmp(szEXENAME,"pmb")||!strcmp(szEXENAME,"fig") * ) * { * g_MediaType=VIDEO_MEDIA; * return S_OK; * } */ }