diff --git a/MinimalistMediaPlayer.dproj b/MinimalistMediaPlayer.dproj index 78f974b..9c564ba 100644 --- a/MinimalistMediaPlayer.dproj +++ b/MinimalistMediaPlayer.dproj @@ -106,12 +106,12 @@ .\$(Platform)\$(Config)\ true 1033 - CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=2.0.3.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=2.0.2.0;Comments= + CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=2.0.3.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=2.0.3.0;Comments= .\$(Platform)\$(Config)\ .\$(Platform)\$(Config) - "B:\MoviesToGo\The Lady In The Van (2015).mkv" + "nofile" 2 3 diff --git a/MinimalistMediaPlayer.res b/MinimalistMediaPlayer.res index 05746a7..37a1064 100644 Binary files a/MinimalistMediaPlayer.res and b/MinimalistMediaPlayer.res differ diff --git a/appEvents.pas b/appEvents.pas index d03563d..fd67bc0 100644 --- a/appEvents.pas +++ b/appEvents.pas @@ -167,6 +167,8 @@ procedure TAppEvents.appEventsMessage(var msg: tagMSG; var handled: boolean); case msgIs(WM_USER_CENTRE_WINDOW) of TRUE: UI.centreWindow(UI.handle); end; case msgIs(WM_PROCESS_MESSAGES) of TRUE: application.processMessages; end; case msgIs(WIN_TWEAK_SIZE) of TRUE: UI.tweakWindow; end; + + case msgIs(WM_CENTRE_CURSOR) of TRUE: PB.centreCursor; end; end; constructor TAppEvents.create; diff --git a/consts.pas b/consts.pas index dea129b..7584802 100644 --- a/consts.pas +++ b/consts.pas @@ -53,6 +53,7 @@ interface WM_PLAY_CURRENT_ITEM = WM_USER + 2109; WM_SHOW_WINDOW = WM_USER + 2110; WM_PROCESS_MESSAGES = WM_USER + 2111; + WM_CENTRE_CURSOR = WM_USER + 2112; POT_PLAYER = 'C:\Program Files\DAUM\PotPlayer\PotPlayerMini64.exe'; LOSSLESS_CUT = 'C:\Program Files\LosslessCut-win-x64\LosslessCut.exe'; @@ -64,7 +65,7 @@ interface UI_DEFAULT_AUDIO_HEIGHT = 56; type - TMediaType = (mtUnk, mtAudio, mtVideo); + TMediaType = (mtUnk, mtAudio, mtVideo, mtImage); TMediaTypeRec = record mimeType: string; mediaType: TMediaType; @@ -73,7 +74,13 @@ TMediaTypeRec = record end; const - mediaTypes: array[0..82] of TMediaTypeRec = ( + mediaTypes: array[0..86] of TMediaTypeRec = ( + +// manually added image formats +(mimeType: 'image/jpeg'; mediaType: mtImage; typeName: 'JPEG image'; fileExts: '.jpg.jpeg'), +(mimeType: 'image/bmp'; mediaType: mtImage; typeName: 'BITMAP image'; fileExts: '.bmp'), +(mimeType: 'image/png'; mediaType: mtImage; typeName: 'PNG image'; fileExts: '.png'), +(mimeType: 'image/webp'; mediaType: mtImage; typeName: 'WEBP image'; fileExts: '.webp'), // DVD/Blu-ray audio formats (mimeType: 'audio/ac3'; mediaType: mtAudio; typeName: 'AC-3 Audio'; fileExts: '.ac3.a52'), diff --git a/mediaInfo.pas b/mediaInfo.pas index 6159d41..023684d 100644 --- a/mediaInfo.pas +++ b/mediaInfo.pas @@ -72,19 +72,22 @@ TMediaChapter = class(TObject) TMediaInfo = class(TObject) private FAudioBitRate: integer; + FAudioCount: integer; FFileSize: int64; FGeneralCount: integer; + FHasCoverArt: string; FHeight: integer; - FStereoMono: string; - FWidth: integer; - FOverallFrameRate: string; + FImageCount: integer; + FImageHeight: integer; + FImageWidth: integer; + FOtherCount: integer; FOverallBitRate: integer; + FOverallFrameRate: string; + FStereoMono: string; + FTextCount: integer; FVideoBitRate: integer; - FAudioCount: integer; FVideoCount: integer; - FTextCount: integer; - FImageCount: integer; - FOtherCount: integer; + FWidth: integer; FChapterCount: integer; FDuration: integer; @@ -95,16 +98,17 @@ TMediaInfo = class(TObject) FURL: string; function getAudioBitRate: string; + function getDuration: integer; function getFileSize: string; + function getHasCoverArt: boolean; + function getSelectedCount: integer; + function getStereoMono: string; + function getStreamCount: integer; function getOverallFrameRate: string; function getOverallBitRate: string; function getVideoBitRate: string; function getXY: string; - function getStereoMono: string; procedure setURL(const aValue: string); - function getStreamCount: integer; - function getSelectedCount: integer; - function getDuration: integer; protected constructor create; destructor destroy; override; @@ -117,7 +121,10 @@ TMediaInfo = class(TObject) property duration: integer read getDuration; property fileSize: string read getFileSize; property generalCount: integer read FGeneralCount; + property hasCoverArt: boolean read getHasCoverArt; property imageCount: integer read FImageCount; + property imageHeight: integer read FImageHeight; + property imageWidth: integer read FImageWidth; property mediaChapters: TObjectList read FMediaChapters; property mediaStreams: TObjectList read FMediaStreams; property otherCount: integer read FOtherCount; @@ -176,6 +183,11 @@ function TMediaInfo.getAudioBitRate: string; result := format('AR: %d Kb/s', [round(FAudioBitRate / 1000)]); end; +function TMediaInfo.getHasCoverArt: boolean; +begin + result := FHasCoverArt = 'Yes'; +end; + function TMediaInfo.getData(const aMemo: TMemo): boolean; begin case FNeedInfo of TRUE: initMediaInfo(FURL); end; @@ -368,7 +380,10 @@ function TMediaInfo.initMediaInfo(const aURL: string = ''): boolean; case tryStrToInt(mediaInfo_Get(handle, Stream_Video, 0, 'Height', Info_Text, Info_Name), FHeight) of FALSE: FHeight := 0; end; case tryStrToInt(mediaInfo_Get(handle, Stream_Video, 0, 'BitRate', Info_Text, Info_Name), FVideoBitRate) of FALSE: FVideoBitRate := 0; end; - FStereoMono := mediaInfo_Get(handle, Stream_Audio, 0, 'Title', Info_Text, Info_Name); + case tryStrToInt(mediaInfo_Get(handle, Stream_Image, 0, 'Width', Info_Text, Info_Name), FImageWidth) of FALSE: FImageWidth := 0; end; + case tryStrToInt(mediaInfo_Get(handle, Stream_Image, 0, 'Height', Info_Text, Info_Name), FImageHeight) of FALSE: FImageHeight := 0; end; + + FStereoMono := mediaInfo_Get(handle, Stream_Audio, 0, 'Title', Info_Text, Info_Name); case tryStrToInt(mediaInfo_Get(handle, Stream_General, 0, 'GeneralCount', Info_Text, Info_Name), FGeneralCount) of FALSE: FGeneralCount := 0; end; case tryStrToInt(mediaInfo_Get(handle, Stream_General, 0, 'VideoCount', Info_Text, Info_Name), FVideoCount) of FALSE: FVideoCount := 0; end; @@ -377,6 +392,8 @@ function TMediaInfo.initMediaInfo(const aURL: string = ''): boolean; case tryStrToInt(mediaInfo_Get(handle, Stream_General, 0, 'OtherCount', Info_Text, Info_Name), FOtherCount) of FALSE: FOtherCount := 0; end; case tryStrToInt(mediaInfo_Get(handle, Stream_General, 0, 'ImageCount', Info_Text, Info_Name), FImageCount) of FALSE: FImageCount := 0; end; + FHasCoverArt := mediaInfo_Get(handle, Stream_General, 0, 'Cover', Info_Text, Info_Name); + for var vStreamIx := 0 to streamCount - 1 do begin case mediaInfo_Get(handle, Stream_Video, vStreamIx, 'StreamKind', Info_Text, Info_Name) <> '' of TRUE: createVideoStream(vStreamIx); end; case mediaInfo_Get(handle, Stream_Audio, vStreamIx, 'StreamKind', Info_Text, Info_Name) <> '' of TRUE: createAudioStream(vStreamIx); end; diff --git a/mediaPlayer.pas b/mediaPlayer.pas index b857fe2..e82e2d6 100644 --- a/mediaPlayer.pas +++ b/mediaPlayer.pas @@ -21,7 +21,7 @@ interface uses - forms, vcl.extCtrls, system.classes, MPVBasePlayer; + forms, vcl.extCtrls, system.classes, MPVBasePlayer, consts; type TTimerEvent = (tePlay, teClose); @@ -36,6 +36,7 @@ TMediaPlayer = class(TObject) FAlwaysPot: boolean; FDontPlayNext: boolean; + FMediaType: TMediaType; FMuted: boolean; FOnBeforeNew: TNotifyEvent; FOnPlayNew: TNotifyEvent; @@ -130,6 +131,7 @@ TMediaPlayer = class(TObject) property formattedTime: string read getFormattedTime; property formattedVol: string read getFormattedVol; property keepOpen: boolean write setKeepOpen; + property mediaType: TMediaType read FMediaType; property onBeforeNew: TNotifyEvent read FOnBeforeNew write FOnBeforeNew; property onPlayNew: TNotifyEvent read FOnPlayNext write FOnPlayNew; property onPlayNext: TNotifyEvent read FOnPlayNext write FOnPlayNext; @@ -146,7 +148,7 @@ implementation uses vcl.controls, vcl.graphics, winAPI.windows, globalVars, formSubtitles, progressBar, keyboard, commonUtils, system.sysUtils, - formCaption, mediaInfo, mpvConst, consts, playlist, UIctrls, sysCommands, configFile, formHelp, mediaType, sendAll, _debugWindow; + formCaption, mediaInfo, mpvConst, playlist, UIctrls, sysCommands, configFile, formHelp, sendAll, mediaType, _debugWindow; var gMP: TMediaPlayer; @@ -411,7 +413,7 @@ procedure TMediaPlayer.onInitMPV(sender: TObject); setPropertyString('screenshot-png-compression', '0'); setPropertyString('screenshot-template', '%F %p %04n'); setPropertyString('sid', '1'); -// setPropertyString('image-display-duration', '10'); +// setPropertyDouble('image-display-duration', 100); // SetPropertyDouble('sub-delay', -00.99); end; end; @@ -548,27 +550,28 @@ function TMediaPlayer.play(const aURL: string): boolean; MI.initMediaInfo(aURL); - var vMediaType := MT.mediaType(lowerCase(extractFileExt(PL.currentItem))); + FMediaType := MT.mediaType(lowerCase(extractFileExt(PL.currentItem))); // reset the window size for an audio file in case the previous file was a video, or the previous audio had an image but this one doesn't - case UI.autoCentre or (vMediaType = mtAudio) of TRUE: UI.setWindowSize(vMediaType); end; + case UI.autoCentre OR (FMediaType = mtAudio) of TRUE: UI.setWindowSize(FMediaType, MI.hasCoverArt); end; + case UI.autoCentre AND (FMediaType <> mtImage) of TRUE: postMessage(GV.appWND, WM_CENTRE_CURSOR, 0, 0); end; openURL(aURL); mpv.volume := FVol; mpv.mute := FMuted; + FDontPlayNext := FMediaType = mtImage; + case ST.showData of TRUE: MI.getData(ST.dataMemo); end; MC.caption := PL.formattedItem; -// postMessage(GV.appWnd, WM_ADJUST_ASPECT_RATIO, 0, 0); application.processMessages; -// UI.smallerWindow(UI.handle); -// UI.tweakWindow; // force update SA.postToAll(WM_PROCESS_MESSAGES); checkPot; - case assigned(FOnPlayNew) of TRUE: FOnPlayNew(SELF); end; + case assigned(FOnPlayNew) of TRUE: FOnPlayNew(SELF); end; + case UI.autoCentre AND (FMediaType <> mtImage) of TRUE: postMessage(GV.appWND, WM_CENTRE_CURSOR, 0, 0); end; result := TRUE; end; diff --git a/progressBar.pas b/progressBar.pas index 10c5117..65c2f6a 100644 --- a/progressBar.pas +++ b/progressBar.pas @@ -44,11 +44,12 @@ TProgressBar = class(TObject) public destructor Destroy; override; function brighter: integer; + function centreCursor: boolean; function darker: integer; function formResize: boolean; function initProgressBar(const aForm: TForm): boolean; function resetColor: integer; - function setNewPosition(const x: integer): integer; + function setNewPosition(const x: integer): integer; property initialized: boolean read FInitialized; property max: integer read getMax write setMax; property position: integer read getPosition write setPosition; @@ -80,6 +81,12 @@ function TProgressBar.brighter: integer; result := FPB.barColor1; end; +function TProgressBar.centreCursor: boolean; +begin + var vPoint := FPB.clientToScreen(point(FPB.width div 2, FPB.height div 2)); + setCursorPos(vPoint.x, vPoint.y); +end; + constructor TProgressBar.create; begin inherited; diff --git a/uiCtrls.pas b/uiCtrls.pas index 655ab48..c6deac2 100644 --- a/uiCtrls.pas +++ b/uiCtrls.pas @@ -76,7 +76,7 @@ TUI = class(TObject) function renameFile(const aFilePath: string): boolean; function resize(const aWnd: HWND; const pt: TPoint; const X: int64; const Y: int64): boolean; function showAboutBox: boolean; - function setWindowSize(const aMediaType: TMediaType): boolean; + function setWindowSize(const aMediaType: TMediaType; coverArt: boolean = FALSE): boolean; function showWindow: boolean; function showXY: boolean; function shutTimeline: boolean; @@ -130,6 +130,8 @@ function TUI.adjustAspectRatio(const aWnd: HWND; const X: int64; const Y: int64) vRatio: double; vWidth, vHeight: integer; begin + case MP.mediaType = mtImage of TRUE: EXIT; end; + case (MP.mediaType = mtAudio) AND (NOT MI.hasCoverArt) of TRUE: EXIT; end; case GV.closeApp of TRUE: EXIT; end; case FMainForm.WindowState = wsMaximized of TRUE: EXIT; end; @@ -143,7 +145,6 @@ function TUI.adjustAspectRatio(const aWnd: HWND; const X: int64; const Y: int64) case (UI.width <> vWidth) or (UI.height <> vHeight) of TRUE: setWindowPos(aWnd, HWND_TOP, 0, 0, vWidth, vHeight, SWP_NOMOVE); end; // don't add SWP_SHOWWINDOW -// debugFormat('%dx%d AR=%f', [vWidth, vHeight, vRatio]); postMessage(GV.appWnd, WM_AUTO_CENTRE_WINDOW, 0, 0); @@ -456,6 +457,7 @@ function TUI.maximize: boolean; begin setWindowSize(mtVideo); end; + function TUI.minimizeWindow: boolean; begin @@ -549,16 +551,21 @@ procedure TUI.setWidth(const Value: integer); FMainForm.width := value; end; -function TUI.setWindowSize(const aMediaType: TMediaType): boolean; +function TUI.setWindowSize(const aMediaType: TMediaType; coverArt: boolean = FALSE): boolean; begin - case aMediaType of mtAudio: begin FMainForm.width := 600; - FMainForm.height := UI_DEFAULT_AUDIO_HEIGHT; end; + case aMediaType of mtAudio: begin case coverArt of TRUE: FMainForm.width := 600; + FALSE: FMainForm.width := 600; end; + case coverArt of FALSE: FMainForm.height := UI_DEFAULT_AUDIO_HEIGHT; + TRUE: FMainForm.height := 400; end;end; mtVideo: begin var vWidth := trunc((CU.getScreenHeight - 50) / CU.getAspectRatio(MI.X, MI.Y)); var VHeight := CU.getScreenHeight - 50; - SetWindowPos(FMainForm.Handle, HWND_TOP, (CU.getScreenWidth - vWidth) div 2, (CU.getScreenHeight - vHeight) div 2, vWidth, vHeight, SWP_NOSIZE); // center window - SetWindowPos(FMainForm.Handle, HWND_TOP, (CU.getScreenWidth - vWidth) div 2, (CU.getScreenHeight - vHeight) div 2, vWidth, vHeight, SWP_NOMOVE); // resize window -// debugFormat('vWidth&vHeight=%dx%d XY=%dx%d AR=%f', [vWidth, vHeight, MI.X, MI.Y, CU.getAspectRatio(MI.X, MI.Y)]); - end;end; + SetWindowPos(FMainForm.Handle, HWND_TOP, (CU.getScreenWidth - vWidth) div 2, (CU.getScreenHeight - vHeight) div 2, vWidth, vHeight, SWP_NOSIZE); // center window + SetWindowPos(FMainForm.Handle, HWND_TOP, (CU.getScreenWidth - vWidth) div 2, (CU.getScreenHeight - vHeight) div 2, vWidth, vHeight, SWP_NOMOVE); end; // resize window + mtImage: begin var vWidth := trunc((CU.getScreenHeight + 500)); // / CU.getAspectRatio(MI.imageWidth, MI.imageHeight)); + var VHeight := CU.getScreenHeight - 50; + SetWindowPos(FMainForm.Handle, HWND_TOP, (CU.getScreenWidth - vWidth) div 2, (CU.getScreenHeight - vHeight) div 2, vWidth, vHeight, SWP_NOSIZE); // center window + SetWindowPos(FMainForm.Handle, HWND_TOP, (CU.getScreenWidth - vWidth) div 2, (CU.getScreenHeight - vHeight) div 2, vWidth, vHeight, SWP_NOMOVE); end; // resize window + end; end; function TUI.setWindowStyle(const aForm: TForm): boolean;