autodefine "off" $include "animation.inc" ' Includes call to 'windowssdk.inc' and 'animation.lib' $include "shlwapi.inc" DECLARE CDECL EXTERN sprintf(POINTER p,POINTER p,...),INT ' direct2d variables POINTER render1 = 0 POINTER render2 = 0 POINTER blackbrush1, blackbrush2, blackbrush3 POINTER greenbrush1 POINTER whitebrush1, whitebrush2 POINTER textformat1, textformat2 ' media foundation INT TIMER_1 = 1 POINTER mfData = 0 INT paused = FALSE UINT64 duration ' video file duration in 100-nanosecond units ' other INT overlayHeight = 40 INT progHeight = 3 INT showOverlay = 1 ISTRING name[260] ' ini file FILE ini INT fError,ret ISTRING startPath[260] ' GIF stuff POINTER render = 0 POINTER gifHandle = 0 INT stretchGif = FALSE INT gifWidth = 0 INT gifHeight = 0 ISTRING ext[8] ' window WINDOW w1,w2,w3 ' Check for ini file - if missing, write an ini file with default startup path and use that path for initial viewing fError=OPENFILE(ini,GETSTARTPATH+"MP4 Player.ini","R") IF fError<>0 CLOSEFILE ini OPENFILE(ini,GETSTARTPATH+"MP4 Player.ini","W") WRITE ini,GETSTARTPATH CLOSEFILE ini startPath=GETSTARTPATH ELSE OPENFILE(ini,GETSTARTPATH+"MP4 Player.ini","R") READ ini,startPath CLOSEFILE ini ENDIF SetCurrentDirectoryA(startPath) ret=PathIsDirectoryA(startPath) IF ret=0 MESSAGEBOX w1,"Your last accessed directory is not available:\nUsing "+UCASE$(GETSTARTPATH),"Path error",@MB_OK|@MB_ICONINFORMATION SetCurrentDirectoryA(GETSTARTPATH) ENDIF OPENWINDOW w1,0,0,1024,824,@MINBOX|@MAXBOX|@SIZE|@NOAUTODRAW,0,"MP4/MP3/GIF Player",&w1_Handler BEGINMENU w1 MENUTITLE "&File" MENUITEM "&Open video...",0,1 SEPARATOR MENUITEM "E&xit",0,2 MENUTITLE "&View" MENUITEM "&Show/hide progress",0,3 MENUTITLE "&Playback" MENUITEM "Pause/&Resume",0,4 ENDMENU OPENWINDOW w2,0,0,1024,724,@NOCAPTION|@NOAUTODRAW,w1,"",&w2_Handler OPENWINDOW w3,0,0,1024,824,@NOCAPTION|@NOAUTODRAW,w1,"",&w3_Handler OnInit() SHOWWINDOW w3,@SWHIDE WAITUNTIL IsWindowClosed(w1) CoUninitialize() 'Save last-used directory to ini file IF startPath="" THEN startPath=GETSTARTPATH OPENFILE(ini,GETSTARTPATH+"MP4 Player.ini","W") WRITE ini,startPath CLOSEFILE ini END ' ------------------------------------------------------------------------------------------------------------------- ' WINDOW PROCEDURES ' ------------------------------------------------------------------------------------------------------------------- SUB w1_Handler(),INT SELECT @MESSAGE CASE @IDCREATE CENTERWINDOW w1 CASE @IDCLOSEWINDOW OnClose() CLOSEWINDOW w1 CASE @IDPAINT OnPaint1() CASE @IDSIZE OnSize1() CASE @IDLBUTTONDN OnMouseClick() CASE @IDKEYUP OnKeyboard() CASE @IDMENUPICK SELECT @MENUNUM CASE 1 ' open video OpenVideo() CASE 2 ' quit CLOSEWINDOW w1 CASE 3 ' show/hide progress INT value = showOverlay IF value THEN showOverlay = 0 ELSE showOverlay = 1 OnSize1() CASE 4 ' pause/resume paused = NOT(paused) IF paused THEN MFVideoPause(mfData) ELSE MFVideoPlay(mfData) ENDIF ENDSELECT CASE @IDTIMER SELECT @WPARAM CASE TIMER_1 InvalidateRect(w1.hWnd,NULL,NULL) ENDSELECT ENDSELECT RETURN 0 ENDSUB SUB w2_Handler(),INT SELECT @MESSAGE CASE @IDPAINT OnPaint2() CASE @IDSIZE OnSize2() CASE @IDCLOSEWINDOW CLOSEWINDOW w2 CASE @IDKEYUP OnKeyboard() ENDSELECT RETURN 0 ENDSUB SUB w3_Handler(),INT SELECT @MESSAGE CASE @IDCREATE CENTERWINDOW w3 CASE @IDCLOSEWINDOW OnClose3() CLOSEWINDOW w3 CASE @IDPAINT OnPaint3() CASE @IDSIZE OnSize3() CASE @IDKEYUP OnKeyboard() CASE @IDTIMER SELECT @WPARAM CASE TIMER_1 gifOnTimer(w3.hWnd,gifHandle,TIMER_1) ENDSELECT CASE @IDLBUTTONDN stretchGif=NOT(stretchGif) InvalidateRect(w3.hWnd,NULL,NULL) ENDSELECT RETURN 0 ENDSUB ' ------------------------------------------------------------------------------------------------------------------- ' EVENTS ' ------------------------------------------------------------------------------------------------------------------- SUB OnInit() CoInitialize(0) ' init direct2d library HRESULT hr = D2DInit() IF hr > 0 THEN _MessageBox(0, "The initialisation has failed with code:"+STR$(hr),"Direct2D",0) _SendMessage(w1.hWnd,WM_CLOSE,0,0) RETURN ENDIF ' create the direct2d render target WINRECT rc GetClientRect(w1.hWnd,rc) render1 = D2DRenderTargetCreate(w1.hWnd,rc.right,rc.bottom) GetClientRect(w2.hWnd,rc) render2 = D2DRenderTargetCreate(w2.hWnd,rc.right,rc.bottom) GetClientRect(w3.hWnd,rc) render = D2DRenderTargetCreate(w3.hWnd,rc.right,rc.bottom) ' create a solid brush blackbrush1 = D2DSolidBrushCreate(render1, 0, 0, 0, 255) blackbrush2 = D2DSolidBrushCreate(render2, 0, 0, 0, 255) blackbrush3 = D2DSolidBrushCreate(render, 0, 0, 0, 255) greenbrush1 = D2DSolidBrushCreate(render1, 0, 150, 0, 255) whitebrush1 = D2DSolidBrushCreate(render1, 255, 255, 255, 255) whitebrush2 = D2DSolidBrushCreate(render2, 255, 255, 255, 255) ' create fonts textformat1 = D2DTextFormatCreate(render1, L"SegoeUI", 15.0, DWRITE_FONT_WEIGHT_REGULAR, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, DWRITE_TEXT_ALIGNMENT_LEADING, DWRITE_PARAGRAPH_ALIGNMENT_CENTER) textformat2 = D2DTextFormatCreate(render2, L"SegoeUI", 20.0, DWRITE_FONT_WEIGHT_REGULAR, DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, DWRITE_TEXT_ALIGNMENT_CENTER, DWRITE_PARAGRAPH_ALIGNMENT_CENTER) ENDSUB SUB OnClose() ' delete the fonts D2DTextFormatRelease(textformat1) D2DTextFormatRelease(textformat2) ' delete brush D2DSolidBrushRelease(blackbrush1) D2DSolidBrushRelease(blackbrush2) D2DSolidBrushRelease(blackbrush3) D2DSolidBrushRelease(greenbrush1) D2DSolidBrushRelease(whitebrush1) D2DSolidBrushRelease(whitebrush2) ' destroy direct2d render target D2DRenderTargetDestroy(render1) D2DRenderTargetDestroy(render2) D2DRenderTargetDestroy(render) ' clean media files MFVideoShutdown(mfData) gifDetach(w3.hWnd,gifHandle) ' finish direct2d library D2DFinish() ENDSUB SUB OnClose3() gifDetach(w3.hWnd,gifHandle) ' destroy direct2d render target D2DRenderTargetDestroy(render) ' finish direct2d library D2DFinish() SHOWWINDOW w2,@SWSHOW ENDSUB ' ------------------------------------------------------------------------------------------------------------------- ' KEYBOARD & MOUSE EVENTS ' ------------------------------------------------------------------------------------------------------------------- SUB OnMouseClick() IF mfData THEN WINRECT rc GetClientRect(w1.hWnd, rc) POINT p GetCursorPos(&p) ScreenToClient(w1.hWnd, &p) UINT64 width = rc.right UINT64 mx = p.x UINT64 pos = (mx/FLT(width)) * duration MFVideoSetPosition(mfData, pos) ENDIF ENDSUB SUB OnKeyboard() SELECT @WPARAM CASE 32 ' Spacebar paused = NOT(paused) IF paused THEN MFVideoPause(mfData) ELSE MFVideoPlay(mfData) ENDIF CASE 79 ' O letter OpenVideo() CASE 17 ' Control key INT value = showOverlay IF value THEN showOverlay = 0 ELSE showOverlay = 1 OnSize1() ENDSELECT ENDSUB ' ------------------------------------------------------------------------------------------------------------------- ' MEDIA FOUNDATION ROUTINES ' ------------------------------------------------------------------------------------------------------------------- SUB FormatTime(UINT64 _time,INT offset),STRING ISTRING time[32] = "" UINT64 t = _time / 10000000 ' duration in seconds INT h = FLOOR(t/3600) INT m = (t/60)%60 INT s = t%60 + offset sprintf(time,"%02d:%02d:%02d",h,m,s) RETURN time ENDSUB 'You can check the extension in OpenVideo(), if you open a mp3 file just hide w2. SUB OpenVideo() ISTRING fileName[MAX_PATH] ext="" fileName=FILEREQUEST("Select Video/Audio file",w1,1,"MP4 Video (*.mp4)|*.mp4|MP3 Audio (*.mp3)|*.mp3|Animated GIF (*.gif)|*.gif||","mp4",0,startPath) ret=GetCurrentDirectoryA(259,startPath) ext=RIGHT$(fileName,3) IF LEN(fileName) THEN STOPTIMER w1,TIMER_1 IF mfData THEN MFVideoPause(mfData) MFVideoShutdown(mfData) ENDIF mfData = 0 gifHandle = 0 IF UCASE$(ext)="GIF" THEN SHOWWINDOW w2,@SWHIDE SHOWWINDOW w3,@SWSHOW gifHandle=gifAttach(w3.hWnd,TIMER_1,S2W(fileName),render) GifGetSize(gifHandle,gifWidth,gifHeight) OnSize1() OnSize3() InvalidateRect(w1.hWnd, NULL, true) InvalidateRect(w3.hWnd, NULL, true) ELSE IF UCASE$(ext)="MP3" SHOWWINDOW w2,@SWHIDE ENDIF IF UCASE$(ext)="MP4" SHOWWINDOW w2,@SWSHOW ENDIF SHOWWINDOW w3,@SWHIDE mfData = MFVideoInit(w2.hWnd) duration = MFVideoLoadFromFile(mfData,S2W(fileName)) MFVideoPlay(mfData) MFVideoLoop(mfData, TRUE) OnSize1() OnSize2() InvalidateRect(w1.hWnd, NULL, true) InvalidateRect(w2.hWnd, NULL, true) ENDIF STARTTIMER w1,20,TIMER_1 POINTER p = PathFindFileName(&fileName) name = *p ENDIF ENDSUB ' ------------------------------------------------------------------------------------------------------------------- ' SIZE ROUTINES ' ------------------------------------------------------------------------------------------------------------------- SUB OnSize1() WINRECT rc GetClientRect(w1.hWnd,rc) D2DRenderTargetResize(render1,rc.right,rc.bottom) ' update render target area INT height=0 IF showOverlay THEN height=overlayHeight IF IsWindowVisible(w2.hWnd) THEN SETSIZE w2,0,0,rc.right,rc.bottom-height IF IsWindowVisible(w3.hWnd) THEN SETSIZE w3,0,0,rc.right,rc.bottom-height ENDSUB SUB OnSize2() WINRECT rc GetClientRect(w2.hWnd,rc) D2DRenderTargetResize(render2,rc.right,rc.bottom) ' update render target area ENDSUB SUB OnSize3() WINRECT rc GetClientRect(w3.hWnd,rc) D2DRenderTargetResize(render,rc.right,rc.bottom) ' update render target area ENDSUB ' ------------------------------------------------------------------------------------------------------------------- ' PAINT ROUTINES ' ------------------------------------------------------------------------------------------------------------------- SUB OnPaint1() INT width,height UINT64 pos,progressWidth WSTRING timeElapsed INT remWidth=60 WSTRING timeRemaining IF render1 THEN D2DRenderBegin(render1) D2DRenderGetSize(render1,width,height) IF gifHandle = 0 AND mfData = 0 THEN D2DFillSolidColor(render1,0,0,0,255) ELSE IF gifHandle > 0 ' draw the overlay background D2DRenderRectangle(render1,blackbrush1,0,height-overlayHeight,width,height) ' draw GIF name D2DRenderText(render1,whitebrush1,L" "+S2W(name),10,height-overlayHeight,width-10-remWidth-20,height,textformat1) ENDIF IF mfData > 0 ' draw the overlay background D2DRenderRectangle(render1,blackbrush1,0,height-overlayHeight,width,height) ' calculate progressWidth pos=MFVideoGetPosition(mfData) progressWidth=(pos/FLT(duration))*width D2DRenderRectangle(render1,greenbrush1,0,height-progHeight-1,progressWidth,height-1) ' draw elapsed time timeElapsed = S2W(FormatTime(pos, 1)) D2DRenderText(render1,whitebrush1,timeElapsed+L" "+S2W(name),10,height-overlayHeight,width-10-remWidth-20,height,textformat1) ' draw remaining time timeRemaining = S2W("-"+FormatTime(duration-pos,1)) D2DRenderText(render1,whitebrush1,timeRemaining,width-10-remWidth,height-overlayHeight,width-10,height,textformat1) ENDIF ENDIF ' if anything doesn't work this is a good spot to check what's going on HRESULT hr = D2DRenderEnd(render1) ' in case of error 'hr' will have the error code '_MessageBox(0,STR$(hr),"Render error",0) ENDIF ENDSUB SUB OnPaint2() INT width,height IF mfData THEN MFVideoRefresh(mfData) ELSE IF render2 THEN D2DRenderBegin(render2) D2DRenderGetSize(render2,width,height) D2DFillSolidColor(render2,0,0,0,255) ' render text WSTRING text=L"-- Play MP4, MP3 and Animated GIFs --"+WCHR$(10)+WCHR$(10)+L"Press 'O' to open a video/audio/GIF file" _ +WCHR$(10)+WCHR$(10)+L"Press 'SPACEBAR' to pause/resume play"+WCHR$(10)+L"Press 'CONTROL' to show/hide progress" D2DRenderText(render2, whitebrush2, text, 0, 0, width, height, textformat2) ' if anything doesn't work this is a good spot to check what's going on HRESULT hr=D2DRenderEnd(render2) ' in case of error 'hr' will have the error code '_MessageBox(0,STR$(hr),"Render error",0) ENDIF ENDIF ENDSUB SUB OnPaint3() IF render THEN INT width = 0 INT height = 0 D2DRenderBegin(render) D2DFillSolidColor(render,0,0,0,255) IF stretchGif THEN ' the gif will fill the client area RenderGif(gifHandle) ELSE ' the gif will follow the mouse D2DRenderGetSize(render, width, height) POINT p GetCursorPos(&p) ScreenToClient(w3.hWnd,&p) RenderGif(gifHandle,p.x-gifWidth/2.0,p.y-gifHeight/2.0,p.x+gifWidth/2.0,p.y+gifHeight/2.0) ENDIF ' if anything doesn't work this is a good spot to check what's going on HRESULT hr = D2DRenderEnd(render) ' in case of error 'hr' will have the error code '_MessageBox(0,STR$(hr),"render error",0) ENDIF ENDSUB