aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/base/UIni.pas24
-rw-r--r--src/base/UMusic.pas75
-rw-r--r--src/media/UMedia_dummy.pas126
-rw-r--r--src/media/UVideo.pas467
-rw-r--r--src/media/UVisualizer.pas129
-rw-r--r--src/menu/UMenuBackgroundVideo.pas6
-rw-r--r--src/screens/UScreenSing.pas5
-rw-r--r--src/screens/UScreenSong.pas123
8 files changed, 859 insertions, 96 deletions
diff --git a/src/base/UIni.pas b/src/base/UIni.pas
index d7676f51..6d01ddc1 100644
--- a/src/base/UIni.pas
+++ b/src/base/UIni.pas
@@ -125,6 +125,8 @@ type
Spectrum: integer;
Spectrograph: integer;
MovieSize: integer;
+ VideoPreview: integer;
+ VideoEnabled: integer;
// Sound
MicBoost: integer;
@@ -218,6 +220,8 @@ const
ISpectrum: array[0..1] of UTF8String = ('Off', 'On');
ISpectrograph: array[0..1] of UTF8String = ('Off', 'On');
IMovieSize: array[0..2] of UTF8String = ('Half', 'Full [Vid]', 'Full [BG+Vid]');
+ IVideoPreview: array[0..1] of UTF8String = ('Off', 'On');
+ IVideoEnabled: array[0..1] of UTF8String = ('Off', 'On');
IClickAssist: array[0..1] of UTF8String = ('Off', 'On');
IBeatClick: array[0..1] of UTF8String = ('Off', 'On');
@@ -299,6 +303,8 @@ var
ISpectrumTranslated: array[0..1] of UTF8String = ('Off', 'On');
ISpectrographTranslated: array[0..1] of UTF8String = ('Off', 'On');
IMovieSizeTranslated: array[0..2] of UTF8String = ('Half', 'Full [Vid]', 'Full [BG+Vid]');
+ IVideoPreviewTranslated: array[0..1] of UTF8String = ('Off', 'On');
+ IVideoEnabledTranslated: array[0..1] of UTF8String = ('Off', 'On');
IClickAssistTranslated: array[0..1] of UTF8String = ('Off', 'On');
IBeatClickTranslated: array[0..1] of UTF8String = ('Off', 'On');
@@ -419,6 +425,12 @@ begin
IMovieSizeTranslated[1] := ULanguage.Language.Translate('OPTION_VALUE_FULL_VID');
IMovieSizeTranslated[2] := ULanguage.Language.Translate('OPTION_VALUE_FULL_VID_BG');
+ IVideoPreviewTranslated[0] := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+ IVideoPreviewTranslated[1] := ULanguage.Language.Translate('OPTION_VALUE_ON');
+
+ IVideoEnabledTranslated[0] := ULanguage.Language.Translate('OPTION_VALUE_OFF');
+ IVideoEnabledTranslated[1] := ULanguage.Language.Translate('OPTION_VALUE_ON');
+
IClickAssistTranslated[0] := ULanguage.Language.Translate('OPTION_VALUE_OFF');
IClickAssistTranslated[1] := ULanguage.Language.Translate('OPTION_VALUE_ON');
@@ -934,6 +946,12 @@ begin
// MovieSize
MovieSize := GetArrayIndex(IMovieSize, IniFile.ReadString('Graphics', 'MovieSize', IMovieSize[2]));
+ // VideoPreview
+ VideoPreview := GetArrayIndex(IVideoPreview, IniFile.ReadString('Graphics', 'VideoPreview', IVideoPreview[1]));
+
+ // VideoEnabled
+ VideoEnabled := GetArrayIndex(IVideoEnabled, IniFile.ReadString('Graphics', 'VideoEnabled', IVideoEnabled[1]));
+
// ClickAssist
ClickAssist := GetArrayIndex(IClickAssist, IniFile.ReadString('Sound', 'ClickAssist', 'Off'));
@@ -1081,6 +1099,12 @@ begin
// Movie Size
IniFile.WriteString('Graphics', 'MovieSize', IMovieSize[MovieSize]);
+ // VideoPreview
+ IniFile.WriteString('Graphics', 'VideoPreview', IVideoPreview[VideoPreview]);
+
+ // VideoEnabled
+ IniFile.WriteString('Graphics', 'VideoEnabled', IVideoEnabled[VideoEnabled]);
+
// ClickAssist
IniFile.WriteString('Sound', 'ClickAssist', IClickAssist[ClickAssist]);
diff --git a/src/base/UMusic.pas b/src/base/UMusic.pas
index 7f2b3e30..41d6e80c 100644
--- a/src/base/UMusic.pas
+++ b/src/base/UMusic.pas
@@ -43,6 +43,27 @@ uses
type
TNoteType = (ntFreestyle, ntNormal, ntGolden);
+ {**
+ * acoStretch: Stretch to screen width and height
+ * - ignores aspect
+ * + no borders
+ * + no image data loss
+ * acoCrop: Stretch to screen width or height, crop the other dimension
+ * + keeps aspect
+ * + no borders
+ * - frame borders are cropped (image data loss)
+ * acoLetterBox: Stretch to screen width, add bars at or crop top and bottom
+ * + keeps aspect
+ * - borders at top and bottom
+ * o top/bottom is cropped if width < height (unusual)
+ *}
+ TAspectCorrection = (acoStretch, acoCrop, acoLetterBox);
+
+ TRectCoords = record
+ Left, Right: double;
+ Upper, Lower: double;
+ end;
+
const
// ScoreFactor defines how a notehit of a specified notetype is
// measured in comparison to the other types
@@ -334,9 +355,49 @@ type
procedure SetPosition(Time: real);
function GetPosition: real;
- procedure GetFrame(Time: Extended);
- procedure DrawGL(Screen: integer);
+ procedure SetScreen(Screen: integer);
+ function GetScreen(): integer;
+
+ procedure SetScreenPosition(X, Y: double; Z: double = 0.0);
+ procedure GetScreenPosition(var X, Y, Z: double);
+
+ procedure SetWidth(Width: double);
+ function GetWidth(): double;
+
+ procedure SetHeight(Height: double);
+ function GetHeight(): double;
+
+ {**
+ * Sub-image of the video frame to draw.
+ * This can be used for zooming or similar purposes.
+ *}
+ procedure SetFrameRange(Range: TRectCoords);
+ function GetFrameRange(): TRectCoords;
+
+ function GetFrameAspect(): real;
+
+ procedure SetAspectCorrection(AspectCorrection: TAspectCorrection);
+ function GetAspectCorrection(): TAspectCorrection;
+
+
+ procedure SetAlpha(Alpha: double);
+ function GetAlpha(): double;
+
+ procedure SetReflectionSpacing(Spacing: double);
+ function GetReflectionSpacing(): double;
+ procedure GetFrame(Time: Extended);
+ procedure Draw();
+ procedure DrawReflection();
+
+
+ property Screen: integer read GetScreen;
+ property Width: double read GetWidth write SetWidth;
+ property Height: double read GetHeight write SetHeight;
+ property Alpha: double read GetAlpha write SetAlpha;
+ property ReflectionSpacing: double read GetReflectionSpacing write SetReflectionSpacing;
+ property FrameAspect: real read GetFrameAspect;
+ property AspectCorrection: TAspectCorrection read GetAspectCorrection write SetAspectCorrection;
property Loop: boolean read GetLoop write SetLoop;
property Position: real read GetPosition write SetPosition;
end;
@@ -414,7 +475,15 @@ type
(*
IVideoDecoder = Interface( IGenericDecoder )
['{2F184B2B-FE69-44D5-9031-0A2462391DCA}']
- function Open(const Filename: IPath): TVideoDecodeStream;
+ function Open(const Filename: IPath): TVideoDecodeStream;
+
+ procedure SetPosition(Time: real);
+ function GetPosition: real;
+
+ procedure UpdateTexture(Texture: glUint);
+
+ property Loop: boolean read GetLoop write SetLoop;
+ property Position: real read GetPosition write SetPosition;
end;
*)
diff --git a/src/media/UMedia_dummy.pas b/src/media/UMedia_dummy.pas
index 8ebfd3a9..46cbe6b8 100644
--- a/src/media/UMedia_dummy.pas
+++ b/src/media/UMedia_dummy.pas
@@ -112,9 +112,43 @@ type
procedure SetPosition(Time: real);
function GetPosition: real;
- procedure GetFrame(Time: Extended);
- procedure DrawGL(Screen: integer);
+ procedure SetScreen(Screen: integer);
+ function GetScreen(): integer;
+
+ procedure SetScreenPosition(X, Y, Z: double);
+ procedure GetScreenPosition(var X, Y, Z: double);
+
+ procedure SetWidth(Width: double);
+ function GetWidth(): double;
+
+ procedure SetHeight(Height: double);
+ function GetHeight(): double;
+
+ procedure SetFrameRange(Range: TRectCoords);
+ function GetFrameRange(): TRectCoords;
+
+ function GetFrameAspect(): real;
+
+ procedure SetAspectCorrection(AspectCorrection: TAspectCorrection);
+ function GetAspectCorrection(): TAspectCorrection;
+
+ procedure SetAlpha(Alpha: double);
+ function GetAlpha(): double;
+
+ procedure SetReflectionSpacing(Spacing: double);
+ function GetReflectionSpacing(): double;
+ procedure GetFrame(Time: Extended);
+ procedure Draw();
+ procedure DrawReflection();
+
+ property Screen: integer read GetScreen;
+ property Width: double read GetWidth write SetWidth;
+ property Height: double read GetHeight write SetWidth;
+ property Alpha: double read GetAlpha write SetAlpha;
+ property ReflectionSpacing: double read GetReflectionSpacing write SetReflectionSpacing;
+ property FrameAspect: real read GetFrameAspect;
+ property AspectCorrection: TAspectCorrection read GetAspectCorrection;
property Loop: boolean read GetLoop write SetLoop;
property Position: real read GetPosition write SetPosition;
end;
@@ -329,11 +363,97 @@ begin
Result := 0;
end;
+procedure TVideo_Dummy.SetScreen(Screen: integer);
+begin
+end;
+
+function TVideo_Dummy.GetScreen(): integer;
+begin
+ Result := 0;
+end;
+
+procedure TVideo_Dummy.SetScreenPosition(X, Y, Z: double);
+begin
+end;
+
+procedure TVideo_Dummy.GetScreenPosition(var X, Y, Z: double);
+begin
+ X := 0;
+ Y := 0;
+ Z := 0;
+end;
+
+procedure TVideo_Dummy.SetWidth(Width: double);
+begin
+end;
+
+function TVideo_Dummy.GetWidth(): double;
+begin
+ Result := 0;
+end;
+
+procedure TVideo_Dummy.SetHeight(Height: double);
+begin
+end;
+
+function TVideo_Dummy.GetHeight(): double;
+begin
+ Result := 0;
+end;
+
+procedure TVideo_Dummy.SetFrameRange(Range: TRectCoords);
+begin
+end;
+
+function TVideo_Dummy.GetFrameRange(): TRectCoords;
+begin
+ Result.Left := 0;
+ Result.Right := 0;
+ Result.Upper := 0;
+ Result.Lower := 0;
+end;
+
+function TVideo_Dummy.GetFrameAspect(): real;
+begin
+ Result := 0;
+end;
+
+procedure TVideo_Dummy.SetAspectCorrection(AspectCorrection: TAspectCorrection);
+begin
+end;
+
+function TVideo_Dummy.GetAspectCorrection(): TAspectCorrection;
+begin
+ Result := acoStretch;
+end;
+
+procedure TVideo_Dummy.SetAlpha(Alpha: double);
+begin
+end;
+
+function TVideo_Dummy.GetAlpha(): double;
+begin
+ Result := 0;
+end;
+
+procedure TVideo_Dummy.SetReflectionSpacing(Spacing: double);
+begin
+end;
+
+function TVideo_Dummy.GetReflectionSpacing(): double;
+begin
+ Result := 0;
+end;
+
procedure TVideo_Dummy.GetFrame(Time: Extended);
begin
end;
-procedure TVideo_Dummy.DrawGL(Screen: integer);
+procedure TVideo_Dummy.Draw();
+begin
+end;
+
+procedure TVideo_Dummy.DrawReflection();
begin
end;
diff --git a/src/media/UVideo.pas b/src/media/UVideo.pas
index c7d59fc8..e8cfbbf7 100644
--- a/src/media/UVideo.pas
+++ b/src/media/UVideo.pas
@@ -48,24 +48,6 @@ interface
{$DEFINE PIXEL_FMT_BGR}
{$ENDIF}
-type
- {**
- * vacStretch: Stretch to screen width and height
- * - ignores aspect
- * + no borders
- * + no image data loss
- * vacCrop: Stretch to screen width or height, crop the other dimension
- * + keeps aspect
- * + no borders
- * - frame borders are cropped (image data loss)
- * vacLetterBox: Stretch to screen width, add bars at or crop top and bottom
- * + keeps aspect
- * - borders at top and bottom
- * o top/bottom is cropped if width < height (unusual)
- *}
- TAspectCorrection = (acoStretch, acoCrop, acoLetterBox);
-
-
implementation
uses
@@ -112,12 +94,9 @@ const
PIXEL_FMT_SIZE = 3;
{$ENDIF}
-type
- TRectCoords = record
- Left, Right: double;
- Upper, Lower: double;
- end;
+ ReflectionH = 0.5; //reflection height (50%)
+type
IVideo_FFmpeg = interface (IVideo)
['{E640E130-C8C0-4399-AF02-67A3569313AB}']
function Open(const FileName: IPath): boolean;
@@ -149,6 +128,20 @@ type
fSwScaleContext: PSwsContext;
{$ENDIF}
+ fScreen: integer; //actual screen to draw on
+
+ fPosX: double;
+ fPosY: double;
+ fPosZ: double;
+ fWidth: double;
+ fHeight: double;
+
+ fFrameRange: TRectCoords;
+
+ fAlpha: double;
+ fReflectionSpacing: double;
+
+
fAspect: real; //**< width/height ratio
fAspectCorrection: TAspectCorrection;
@@ -163,6 +156,8 @@ type
procedure SynchronizeTime(Frame: PAVFrame; var pts: double);
procedure GetVideoRect(var ScreenRect, TexRect: TRectCoords);
+ procedure DrawBorders(ScreenRect: TRectCoords);
+ procedure DrawBordersReflected(ScreenRect: TRectCoords; AlphaUpper, AlphaLower: double);
procedure ShowDebugInfo();
@@ -183,8 +178,39 @@ type
procedure SetPosition(Time: real);
function GetPosition: real;
- procedure GetFrame(Time: Extended);
- procedure DrawGL(Screen: integer);
+ procedure SetScreen(Screen: integer);
+ function GetScreen(): integer;
+
+ procedure SetScreenPosition(X, Y, Z: double);
+ procedure GetScreenPosition(var X, Y, Z: double);
+
+ procedure SetWidth(Width: double);
+ function GetWidth(): double;
+
+ procedure SetHeight(Height: double);
+ function GetHeight(): double;
+
+ {**
+ * Sub-image of the video frame to draw.
+ * This can be used for zooming or similar purposes.
+ *}
+ procedure SetFrameRange(Range: TRectCoords);
+ function GetFrameRange(): TRectCoords;
+
+ function GetFrameAspect(): real;
+
+ procedure SetAspectCorrection(AspectCorrection: TAspectCorrection);
+ function GetAspectCorrection(): TAspectCorrection;
+
+ procedure SetAlpha(Alpha: double);
+ function GetAlpha(): double;
+
+ procedure SetReflectionSpacing(Spacing: double);
+ function GetReflectionSpacing(): double;
+
+ procedure GetFrame(Time: Extended);
+ procedure Draw();
+ procedure DrawReflection();
end;
TVideoPlayback_FFmpeg = class( TInterfacedObject, IVideoPlayback )
@@ -498,6 +524,22 @@ begin
fPboId := 0;
fAspectCorrection := acoCrop;
+
+ fScreen := 1;
+
+ fPosX := 0;
+ fPosY := 0;
+ fPosZ := 0;
+ fWidth := RenderW;
+ fHeight := RenderH;
+
+ fFrameRange.Left := 0;
+ fFrameRange.Right := 1;
+ fFrameRange.Upper := 0;
+ fFrameRange.Lower := 1;
+
+ fAlpha := 1;
+ fReflectionSpacing := 0;
end;
procedure TVideo_FFmpeg.Close;
@@ -889,72 +931,142 @@ procedure TVideo_FFmpeg.GetVideoRect(var ScreenRect, TexRect: TRectCoords);
var
ScreenAspect: double; // aspect of screen resolution
ScaledVideoWidth, ScaledVideoHeight: double;
+
begin
// Three aspects to take into account:
// 1. Screen/display resolution (e.g. 1920x1080 -> 16:9)
- // 2. Render aspect (fixed to 800x600 -> 4:3)
+ // 2. Render aspect (fWidth x fHeight -> variable)
// 3. Movie aspect (video frame aspect stored in fAspect)
- ScreenAspect := ScreenW / ScreenH;
+ ScreenAspect := fWidth*((ScreenW/Screens)/RenderW)/(fHeight*(ScreenH/RenderH));
case fAspectCorrection of
acoStretch: begin
- ScaledVideoWidth := RenderW;
- ScaledVideoHeight := RenderH;
+ ScaledVideoWidth := fWidth;
+ ScaledVideoHeight := fHeight;
end;
+
acoCrop: begin
if (ScreenAspect >= fAspect) then
begin
- ScaledVideoWidth := RenderW;
- ScaledVideoHeight := RenderH * ScreenAspect/fAspect;
- end
- else
+ ScaledVideoWidth := fWidth;
+ ScaledVideoHeight := fHeight * ScreenAspect/fAspect;
+ end else
begin
- ScaledVideoHeight := RenderH;
- ScaledVideoWidth := RenderW * fAspect/ScreenAspect;
+ ScaledVideoHeight := fHeight;
+ ScaledVideoWidth := fWidth * fAspect/ScreenAspect;
end;
end;
+
acoLetterBox: begin
- ScaledVideoWidth := RenderW;
- ScaledVideoHeight := RenderH * ScreenAspect/fAspect;
- end
- else
+ if (ScreenAspect <= fAspect) then
+ begin
+ ScaledVideoWidth := fWidth;
+ ScaledVideoHeight := fHeight * ScreenAspect/fAspect;
+ end else
+ begin
+ ScaledVideoHeight := fHeight;
+ ScaledVideoWidth := fWidth * fAspect/ScreenAspect;
+ end;
+ end else
raise Exception.Create('Unhandled aspect correction!');
end;
- // center video
- ScreenRect.Left := (RenderW - ScaledVideoWidth) / 2;
+ //center video
+ ScreenRect.Left := (fWidth - ScaledVideoWidth) / 2 + fPosX;
ScreenRect.Right := ScreenRect.Left + ScaledVideoWidth;
- ScreenRect.Upper := (RenderH - ScaledVideoHeight) / 2;
+ ScreenRect.Upper := (fHeight - ScaledVideoHeight) / 2 + fPosY;
ScreenRect.Lower := ScreenRect.Upper + ScaledVideoHeight;
// texture contains right/lower (power-of-2) padding.
// Determine the texture coords of the video frame.
- TexRect.Left := 0;
- TexRect.Right := fCodecContext^.width / fTexWidth;
- TexRect.Upper := 0;
- TexRect.Lower := fCodecContext^.height / fTexHeight;
+ TexRect.Left := (fCodecContext^.width / fTexWidth) * fFrameRange.Left;
+ TexRect.Right := (fCodecContext^.width / fTexWidth) * fFrameRange.Right;
+ TexRect.Upper := (fCodecContext^.height / fTexHeight) * fFrameRange.Upper;
+ TexRect.Lower := (fCodecContext^.height / fTexHeight) * fFrameRange.Lower;
end;
-procedure TVideo_FFmpeg.DrawGL(Screen: integer);
-var
- ScreenRect: TRectCoords;
- TexRect: TRectCoords;
+procedure TVideo_FFmpeg.DrawBorders(ScreenRect: TRectCoords);
+ procedure DrawRect(left, right, upper, lower: double);
+ begin
+ glColor4f(0, 0, 0, fAlpha);
+ glBegin(GL_QUADS);
+ glVertex3f(left, upper, fPosZ);
+ glVertex3f(right, upper, fPosZ);
+ glVertex3f(right, lower, fPosZ);
+ glVertex3f(left, lower, fPosZ);
+ glEnd;
+ end;
begin
- // have a nice black background to draw on
- // (even if there were errors opening the vid)
- // TODO: Philipp: IMO TVideoPlayback should not clear the screen at
- // all, because clearing is already done by the background class
- // at this moment.
- if (Screen = 1) then
+ //upper border
+ if(ScreenRect.Upper > fPosY) then
+ DrawRect(fPosX, fPosX+fWidth, fPosY, ScreenRect.Upper);
+
+ //lower border
+ if(ScreenRect.Lower < fPosY+fHeight) then
+ DrawRect(fPosX, fPosX+fWidth, ScreenRect.Lower, fPosY+fHeight);
+
+ //left border
+ if(ScreenRect.Left > fPosX) then
+ DrawRect(fPosX, ScreenRect.Left, fPosY, fPosY+fHeight);
+
+ //right border
+ if(ScreenRect.Right < fPosX+fWidth) then
+ DrawRect(ScreenRect.Right, fPosX+fWidth, fPosY, fPosY+fHeight);
+end;
+
+procedure TVideo_FFmpeg.DrawBordersReflected(ScreenRect: TRectCoords; AlphaUpper, AlphaLower: double);
+var
+ rPosUpper, rPosLower: double;
+
+ procedure DrawRect(left, right, upper, lower: double);
+ var
+ AlphaTop: double;
+ AlphaBottom: double;
+
begin
- // It is important that we just clear once before we start
- // drawing the first screen otherwise the first screen
- // would be cleared by the drawgl called when the second
- // screen is drawn
- glClearColor(0, 0, 0, 0);
- glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
+ AlphaTop := AlphaUpper+(AlphaLower-AlphaUpper)*(upper-rPosUpper)/(fHeight*ReflectionH);
+ AlphaBottom := AlphaLower+(AlphaUpper-AlphaLower)*(rPosLower-lower)/(fHeight*ReflectionH);
+
+ glBegin(GL_QUADS);
+ glColor4f(0, 0, 0, AlphaTop);
+ glVertex3f(left, upper, fPosZ);
+ glVertex3f(right, upper, fPosZ);
+
+ glColor4f(0, 0, 0, AlphaBottom);
+ glVertex3f(right, lower, fPosZ);
+ glVertex3f(left, lower, fPosZ);
+ glEnd;
end;
+begin
+ rPosUpper := fPosY+fHeight+fReflectionSpacing;
+ rPosLower := rPosUpper+fHeight*ReflectionH;
+
+ //upper border
+ if(ScreenRect.Upper > rPosUpper) then
+ DrawRect(fPosX, fPosX+fWidth, rPosUpper, ScreenRect.Upper);
+
+ //lower border
+ if(ScreenRect.Lower < rPosLower) then
+ DrawRect(fPosX, fPosX+fWidth, ScreenRect.Lower, rPosLower);
+
+ //left border
+ if(ScreenRect.Left > fPosX) then
+ DrawRect(fPosX, ScreenRect.Left, rPosUpper, rPosLower);
+ //right border
+ if(ScreenRect.Right < fPosX+fWidth) then
+ DrawRect(ScreenRect.Right, fPosX+fWidth, rPosUpper, rPosLower);
+end;
+
+
+procedure TVideo_FFmpeg.Draw();
+var
+ ScreenRect: TRectCoords;
+ TexRect: TRectCoords;
+ HeightFactor: double;
+ WidthFactor: double;
+
+begin
// exit if there's nothing to draw
if (not fOpened) then
Exit;
@@ -966,31 +1078,53 @@ begin
// get texture and screen positions
GetVideoRect(ScreenRect, TexRect);
- // we could use blending for brightness control, but do we need this?
- glDisable(GL_BLEND);
+ WidthFactor := (ScreenW/Screens) / RenderW;
+ HeightFactor := ScreenH / RenderH;
+
+ glScissor(
+ round(fPosX*WidthFactor + HeightFactor*(fScreen-1)),
+ round((RenderH-fPosY-fHeight)*HeightFactor),
+ round(fWidth*WidthFactor),
+ round(fHeight*HeightFactor)
+ );
+
+ glEnable(GL_SCISSOR_TEST);
+ glEnable(GL_BLEND);
+ glDepthRange(0, 10);
+ glDepthFunc(GL_LEQUAL);
+ glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, fFrameTex);
- glColor3f(1, 1, 1);
+ glColor4f(1, 1, 1, fAlpha);
glBegin(GL_QUADS);
// upper-left coord
glTexCoord2f(TexRect.Left, TexRect.Upper);
- glVertex2f(ScreenRect.Left, ScreenRect.Upper);
+ glVertex3f(ScreenRect.Left, ScreenRect.Upper, fPosZ);
// lower-left coord
glTexCoord2f(TexRect.Left, TexRect.Lower);
- glVertex2f(ScreenRect.Left, ScreenRect.Lower);
+ glVertex3f(ScreenRect.Left, ScreenRect.Lower, fPosZ);
// lower-right coord
glTexCoord2f(TexRect.Right, TexRect.Lower);
- glVertex2f(ScreenRect.Right, ScreenRect.Lower);
+ glVertex3f(ScreenRect.Right, ScreenRect.Lower, fPosZ);
// upper-right coord
glTexCoord2f(TexRect.Right, TexRect.Upper);
- glVertex2f(ScreenRect.Right, ScreenRect.Upper);
+ glVertex3f(ScreenRect.Right, ScreenRect.Upper, fPosZ);
glEnd;
+
glDisable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ //draw black borders
+ DrawBorders(ScreenRect);
+
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_BLEND);
+ glDisable(GL_SCISSOR_TEST);
{$IFDEF VideoBenchmark}
Log.BenchmarkEnd(15);
- Log.LogBenchmark('DrawGL', 15);
+ Log.LogBenchmark('Draw', 15);
{$ENDIF}
{$IF Defined(Info) or Defined(DebugFrames)}
@@ -998,6 +1132,94 @@ begin
{$IFEND}
end;
+procedure TVideo_FFmpeg.DrawReflection();
+var
+ ScreenRect: TRectCoords;
+ TexRect: TRectCoords;
+ HeightFactor: double;
+ WidthFactor: double;
+
+ AlphaTop: double;
+ AlphaBottom: double;
+
+ AlphaUpper: double;
+ AlphaLower: double;
+
+begin
+ // exit if there's nothing to draw
+ if (not fOpened) then
+ Exit;
+
+ // get texture and screen positions
+ GetVideoRect(ScreenRect, TexRect);
+
+ WidthFactor := (ScreenW/Screens) / RenderW;
+ HeightFactor := ScreenH / RenderH;
+
+ glScissor(
+ round(fPosX*WidthFactor + HeightFactor*(fScreen-1)),
+ round((RenderH-fPosY-fHeight-fReflectionSpacing-fHeight*ReflectionH)*HeightFactor),
+ round(fWidth*WidthFactor),
+ round(fHeight*HeightFactor*ReflectionH)
+ );
+
+ glEnable(GL_SCISSOR_TEST);
+ glEnable(GL_BLEND);
+ glDepthRange(0, 10);
+ glDepthFunc(GL_LEQUAL);
+ glEnable(GL_DEPTH_TEST);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, fFrameTex);
+
+ //calculate new ScreenRect coordinates for Reflection
+ ScreenRect.Lower := fPosY + fHeight + fReflectionSpacing
+ + (ScreenRect.Upper-fPosY) + (ScreenRect.Lower-ScreenRect.Upper)*ReflectionH;
+ ScreenRect.Upper := fPosY + fHeight + fReflectionSpacing
+ + (ScreenRect.Upper-fPosY);
+
+ AlphaUpper := fAlpha-0.3;
+ AlphaLower := 0;
+
+ AlphaTop := AlphaUpper-(AlphaLower-AlphaUpper)*
+ (ScreenRect.Upper-fPosY-fHeight-fReflectionSpacing)/fHeight;
+ AlphaBottom := AlphaLower+(AlphaUpper-AlphaLower)*
+ (fPosY+fHeight+fReflectionSpacing+fHeight*ReflectionH-ScreenRect.Lower)/fHeight;
+
+ glBegin(GL_QUADS);
+ //Top Left
+ glColor4f(1, 1, 1, AlphaTop);
+ glTexCoord2f(TexRect.Left, TexRect.Lower);
+ glVertex3f(ScreenRect.Left, ScreenRect.Upper, fPosZ);
+
+ //Bottom Left
+ glColor4f(1, 1, 1, AlphaBottom);
+ glTexCoord2f(TexRect.Left, (TexRect.Lower-TexRect.Upper)*(1-ReflectionH));
+ glVertex3f(ScreenRect.Left, ScreenRect.Lower, fPosZ);
+
+ //Bottom Right
+ glColor4f(1, 1, 1, AlphaBottom);
+ glTexCoord2f(TexRect.Right, (TexRect.Lower-TexRect.Upper)*(1-ReflectionH));
+ glVertex3f(ScreenRect.Right, ScreenRect.Lower, fPosZ);
+
+ //Top Right
+ glColor4f(1, 1, 1, AlphaTop);
+ glTexCoord2f(TexRect.Right, TexRect.Lower);
+ glVertex3f(ScreenRect.Right, ScreenRect.Upper, fPosZ);
+ glEnd;
+
+ glDisable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ //draw black borders
+ DrawBordersReflected(ScreenRect, AlphaUpper, AlphaLower);
+
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_BLEND);
+ glDisable(GL_SCISSOR_TEST);
+end;
+
procedure TVideo_FFmpeg.ShowDebugInfo();
begin
{$IFDEF Info}
@@ -1107,6 +1329,111 @@ begin
Result := fFrameTime;
end;
+procedure TVideo_FFmpeg.SetScreen(Screen: integer);
+begin
+ fScreen := Screen;
+end;
+
+function TVideo_FFmpeg.GetScreen(): integer;
+begin
+ Result := fScreen;
+end;
+
+
+procedure TVideo_FFmpeg.SetScreenPosition(X, Y, Z: double);
+begin
+ fPosX := X;
+ fPosY := Y;
+ fPosZ := Z;
+end;
+
+procedure TVideo_FFmpeg.GetScreenPosition(var X, Y, Z: double);
+begin
+ X := fPosX;
+ Y := fPosY;
+ Z := fPosZ;
+end;
+
+
+procedure TVideo_FFmpeg.SetWidth(Width: double);
+begin
+ fWidth := Width;
+end;
+
+function TVideo_FFmpeg.GetWidth(): double;
+begin
+ Result := fWidth;
+end;
+
+
+procedure TVideo_FFmpeg.SetHeight(Height: double);
+begin
+ fHeight := Height;
+end;
+
+function TVideo_FFmpeg.GetHeight(): double;
+begin
+ Result := fHeight;
+end;
+
+
+procedure TVideo_FFmpeg.SetFrameRange(Range: TRectCoords);
+begin
+ fFrameRange := Range;
+end;
+
+function TVideo_FFmpeg.GetFrameRange(): TRectCoords;
+begin
+ Result := fFrameRange;
+end;
+
+
+function TVideo_FFmpeg.GetFrameAspect(): real;
+begin
+ Result := fAspect;
+end;
+
+
+procedure TVideo_FFmpeg.SetAspectCorrection(AspectCorrection: TAspectCorrection);
+begin
+ fAspectCorrection := AspectCorrection;
+end;
+
+function TVideo_FFmpeg.GetAspectCorrection(): TAspectCorrection;
+begin
+ Result := fAspectCorrection;
+end;
+
+
+
+procedure TVideo_FFmpeg.SetAlpha(Alpha: double);
+begin
+ fAlpha := Alpha;
+
+ if (fAlpha>1) then
+ fAlpha := 1;
+
+ if (fAlpha<0) then
+ fAlpha := 0;
+end;
+
+function TVideo_FFmpeg.GetAlpha(): double;
+begin
+ Result := fAlpha;
+end;
+
+
+procedure TVideo_FFmpeg.SetReflectionSpacing(Spacing: double);
+begin
+ fReflectionSpacing := Spacing;
+end;
+
+function TVideo_FFmpeg.GetReflectionSpacing(): double;
+begin
+ Result := fReflectionSpacing;
+end;
+
+
initialization
MediaManager.Add(TVideoPlayback_FFmpeg.Create);
diff --git a/src/media/UVisualizer.pas b/src/media/UVisualizer.pas
index 4f553521..1cdc3500 100644
--- a/src/media/UVisualizer.pas
+++ b/src/media/UVisualizer.pas
@@ -110,6 +110,8 @@ type
fState: TProjectMState;
+ fScreen: integer;
+
fVisualTex: GLuint;
fPCMData: TPCMData;
fRndPCMcount: integer;
@@ -144,8 +146,35 @@ type
procedure SetLoop(Enable: boolean);
function GetLoop(): boolean;
+ procedure SetScreen(Screen: integer);
+ function GetScreen(): integer;
+
+ procedure SetScreenPosition(X, Y, Z: double);
+ procedure GetScreenPosition(var X, Y, Z: double);
+
+ procedure SetWidth(Width: double);
+ function GetWidth(): double;
+
+ procedure SetHeight(Height: double);
+ function GetHeight(): double;
+
+ procedure SetFrameRange(Range: TRectCoords);
+ function GetFrameRange(): TRectCoords;
+
+ function GetFrameAspect(): real;
+
+ procedure SetAspectCorrection(AspectCorrection: TAspectCorrection);
+ function GetAspectCorrection(): TAspectCorrection;
+
+ procedure SetAlpha(Alpha: double);
+ function GetAlpha(): double;
+
+ procedure SetReflectionSpacing(Spacing: double);
+ function GetReflectionSpacing(): double;
+
procedure GetFrame(Time: Extended);
- procedure DrawGL(Screen: integer);
+ procedure Draw();
+ procedure DrawReflection();
end;
TVideoPlayback_ProjectM = class( TInterfacedObject, IVideoVisualization )
@@ -262,6 +291,88 @@ begin
Result := true;
end;
+procedure TVideo_ProjectM.SetScreen(Screen: integer);
+begin
+end;
+
+function TVideo_ProjectM.GetScreen(): integer;
+begin
+ Result := 0;
+end;
+
+procedure TVideo_ProjectM.SetScreenPosition(X, Y, Z: double);
+begin
+end;
+
+procedure TVideo_ProjectM.GetScreenPosition(var X, Y, Z: double);
+begin
+ X := 0;
+ Y := 0;
+ Z := 0;
+end;
+
+procedure TVideo_ProjectM.SetWidth(Width: double);
+begin
+end;
+
+function TVideo_ProjectM.GetWidth(): double;
+begin
+ Result := 0;
+end;
+
+procedure TVideo_ProjectM.SetHeight(Height: double);
+begin
+end;
+
+function TVideo_ProjectM.GetHeight(): double;
+begin
+ Result := 0;
+end;
+
+procedure TVideo_ProjectM.SetFrameRange(Range: TRectCoords);
+begin
+end;
+
+function TVideo_ProjectM.GetFrameRange(): TRectCoords;
+begin
+ Result.Left := 0;
+ Result.Right := 0;
+ Result.Upper := 0;
+ Result.Lower := 0;
+end;
+
+function TVideo_ProjectM.GetFrameAspect(): real;
+begin
+ Result := 0;
+end;
+
+procedure TVideo_ProjectM.SetAspectCorrection(AspectCorrection: TAspectCorrection);
+begin
+end;
+
+function TVideo_ProjectM.GetAspectCorrection(): TAspectCorrection;
+begin
+ Result := acoStretch;
+end;
+
+procedure TVideo_ProjectM.SetAlpha(Alpha: double);
+begin
+end;
+
+function TVideo_ProjectM.GetAlpha(): double;
+begin
+ Result := 1;
+end;
+
+procedure TVideo_ProjectM.SetReflectionSpacing(Spacing: double);
+begin
+end;
+
+function TVideo_ProjectM.GetReflectionSpacing(): double;
+begin
+ Result := 0;
+end;
+
{**
* Returns the stack depth of the given OpenGL matrix mode stack.
*}
@@ -485,11 +596,11 @@ end;
* Draws the current frame to screen.
* TODO: this is not used yet. Data is directly drawn on GetFrame().
*}
-procedure TVideo_ProjectM.DrawGL(Screen: integer);
+procedure TVideo_ProjectM.Draw();
begin
{$IFDEF UseTexture}
// have a nice black background to draw on
- if (Screen = 1) then
+ if (fScreen = 1) then
begin
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
@@ -521,10 +632,10 @@ begin
// draw projectM frame
// Screen is 1 to 2. So current screen is from (Screen - 1) to (Screen)
glBegin(GL_QUADS);
- glTexCoord2f(0, 0); glVertex2f((Screen - 1), 0);
- glTexCoord2f(1, 0); glVertex2f(Screen, 0);
- glTexCoord2f(1, 1); glVertex2f(Screen, 1);
- glTexCoord2f(0, 1); glVertex2f((Screen - 1), 1);
+ glTexCoord2f(0, 0); glVertex2f((fScreen - 1), 0);
+ glTexCoord2f(1, 0); glVertex2f(fScreen, 0);
+ glTexCoord2f(1, 1); glVertex2f(fScreen, 1);
+ glTexCoord2f(0, 1); glVertex2f((fScreen - 1), 1);
glEnd();
glDisable(GL_TEXTURE_2D);
@@ -538,6 +649,10 @@ begin
{$ENDIF}
end;
+procedure TVideo_ProjectM.DrawReflection();
+begin
+end;
+
{**
* Produces random "sound"-data in case no audio-data is available.
* Otherwise the visualization will look rather boring.
diff --git a/src/menu/UMenuBackgroundVideo.pas b/src/menu/UMenuBackgroundVideo.pas
index bfaee702..9a33e721 100644
--- a/src/menu/UMenuBackgroundVideo.pas
+++ b/src/menu/UMenuBackgroundVideo.pas
@@ -151,14 +151,14 @@ begin
glClear(GL_DEPTH_BUFFER_BIT);
// video failure -> draw blank background
if (fBgVideo = nil) then
- glClear(GL_COLOR_BUFFER_BIT);
+ glClear(GL_COLOR_BUFFER_BIT);
end;
if (fBgVideo <> nil) then
begin
fBgVideo.GetFrame(VideoBGTimer.GetTime());
- // FIXME: why do we draw on screen 2? Seems to be wrong.
- fBgVideo.DrawGL(2);
+ fBgVideo.SetScreen(ScreenAct);
+ fBgVideo.Draw();
end;
end;
diff --git a/src/screens/UScreenSing.pas b/src/screens/UScreenSing.pas
index fe8ea8e8..3e0d8078 100644
--- a/src/screens/UScreenSing.pas
+++ b/src/screens/UScreenSing.pas
@@ -522,7 +522,7 @@ begin
*}
fShowVisualization := false;
VideoFile := CurrentSong.Path.Append(CurrentSong.Video);
- if (CurrentSong.Video.IsSet) and VideoFile.IsFile then
+ if (Ini.VideoEnabled = 1) and CurrentSong.Video.IsSet() and VideoFile.IsFile then
begin
fVideoClip := VideoPlayback.Open(VideoFile);
fCurrentVideo := fVideoClip;
@@ -859,7 +859,8 @@ begin
fCurrentVideo.GetFrame(VideoFrameTime);
end;
- fCurrentVideo.DrawGL(ScreenAct);
+ fCurrentVideo.SetScreen(ScreenAct);
+ fCurrentVideo.Draw;
end;
// draw static menu (FG)
diff --git a/src/screens/UScreenSong.pas b/src/screens/UScreenSong.pas
index 6b83d522..764a0d47 100644
--- a/src/screens/UScreenSong.pas
+++ b/src/screens/UScreenSong.pas
@@ -62,8 +62,12 @@ type
isScrolling: boolean; // true if song flow is about to move
+ fCurrentVideo: IVideo;
+
procedure StartMusicPreview();
procedure StopMusicPreview();
+ procedure StartVideoPreview();
+ procedure StopVideoPreview();
public
TextArtist: integer;
TextTitle: integer;
@@ -128,6 +132,7 @@ type
function Draw: boolean; override;
procedure GenerateThumbnails();
procedure OnShow; override;
+ procedure OnShowFinish; override;
procedure OnHide; override;
procedure SelectNext;
procedure SelectPrev;
@@ -886,6 +891,8 @@ begin
PreviewOpened := -1;
isScrolling := false;
+
+ fCurrentVideo := nil;
end;
procedure TScreenSong.GenerateThumbnails();
@@ -960,6 +967,7 @@ begin
if (Ini.PreviewVolume <> 0) then
begin
StartMusicPreview;
+ StartVideoPreview;
end;
// fade in detailed cover
@@ -973,6 +981,7 @@ begin
UnLoadDetailedCover;
StopMusicPreview();
+ StopVideoPreview();
PreviewOpened := -1;
end;
@@ -1506,6 +1515,9 @@ begin
AudioPlayback.Stop;
PreviewOpened := -1;
+ // reset video playback engine
+ fCurrentVideo := nil;
+
if Ini.Players <= 3 then PlayersPlay := Ini.Players + 1;
if Ini.Players = 4 then PlayersPlay := 6;
@@ -1544,11 +1556,17 @@ begin
end;
end;
- isScrolling := true;
+ isScrolling := false;
SetJoker;
SetStatics;
end;
+procedure TScreenSong.OnShowFinish;
+begin
+ isScrolling := true;
+ CoverTime := 10;
+end;
+
procedure TScreenSong.OnHide;
begin
// turn music volume to 100%
@@ -1556,6 +1574,7 @@ begin
// stop preview
StopMusicPreview();
+ StopVideoPreview();
end;
procedure TScreenSong.DrawExtensions;
@@ -1573,9 +1592,10 @@ end;
function TScreenSong.Draw: boolean;
var
- dx: real;
- dt: real;
- I: integer;
+ dx: real;
+ dt: real;
+ I: integer;
+ VideoAlpha: real;
begin
if isScrolling then
begin
@@ -1611,7 +1631,7 @@ begin
//Log.LogBenchmark('SetScroll4', 5);
//Fading Functions, Only if Covertime is under 5 Seconds
- if (CoverTime < 5) then
+ if (CoverTime < 9) then
begin
// cover fade
if (CoverTime < 1) and (CoverTime + TimeSkip >= 1) then
@@ -1641,10 +1661,43 @@ begin
//Draw BG
DrawBG;
+ VideoAlpha := Button[interaction].Texture.Alpha*(CoverTime-1);
//Instead of Draw FG Procedure:
//We draw Buttons for our own
for I := 0 to Length(Button) - 1 do
- Button[I].Draw;
+ begin
+ if (I<>Interaction) or not Assigned(fCurrentVideo) or (VideoAlpha<1) or AudioPlayback.Finished then
+ Button[I].Draw;
+ end;
+
+ if AudioPlayback.Finished then
+ StopVideoPreview;
+
+ if Assigned(fCurrentVideo) then
+ begin
+ // Just call this once
+ // when Screens = 2
+ if (ScreenAct = 1) then
+ fCurrentVideo.GetFrame(CatSongs.Song[Interaction].VideoGAP + AudioPlayback.Position);
+
+ fCurrentVideo.SetScreen(ScreenAct);
+ fCurrentVideo.Alpha := VideoAlpha;
+
+ //set up window
+ with Button[interaction] do
+ begin
+ fCurrentVideo.SetScreenPosition(X, Y, Z);
+ fCurrentVideo.Width := W;
+ fCurrentVideo.Height := H;
+ fCurrentVideo.ReflectionSpacing := Reflectionspacing;
+ end;
+ fCurrentVideo.AspectCorrection := acoCrop;
+
+ fCurrentVideo.Draw;
+
+ if Button[interaction].Reflection then
+ fCurrentVideo.DrawReflection;
+ end;
// Statics
for I := 0 to Length(Statics) - 1 do
@@ -1743,7 +1796,7 @@ begin
if CatSongs.VisibleSongs = 0 then
Exit;
-
+
Song := CatSongs.Song[Interaction];
if not assigned(Song) then
Exit;
@@ -1755,7 +1808,7 @@ begin
if AudioPlayback.Open(Song.Path.Append(Song.Mp3)) then
begin
PreviewOpened := Interaction;
-
+
AudioPlayback.Position := AudioPlayback.Length / 4;
// set preview volume
if (Ini.PreviewFading = 0) then
@@ -1779,12 +1832,66 @@ begin
AudioPlayback.Stop;
end;
+procedure TScreenSong.StartVideoPreview();
+var
+ VideoFile: IPath;
+ Song: TSong;
+
+begin
+ if (Ini.VideoPreview=0) then
+ Exit;
+
+ if Assigned(fCurrentVideo) then
+ begin
+ fCurrentVideo.Stop();
+ fCurrentVideo := nil;
+ end;
+
+ //if no audio open => exit
+ if (PreviewOpened = -1) then
+ Exit;
+
+ if CatSongs.VisibleSongs = 0 then
+ Exit;
+
+ Song := CatSongs.Song[Interaction];
+ if not assigned(Song) then
+ Exit;
+
+ //fix: if main cat than there is nothing to play
+ if Song.main then
+ Exit;
+
+ VideoFile := Song.Path.Append(Song.Video);
+ if (Song.Video.IsSet) and VideoFile.IsFile then
+ begin
+ fCurrentVideo := VideoPlayback.Open(VideoFile);
+ if (fCurrentVideo <> nil) then
+ begin
+ fCurrentVideo.Position := Song.VideoGAP + AudioPlayback.Position;
+ fCurrentVideo.Play;
+ end;
+ end;
+end;
+
+procedure TScreenSong.StopVideoPreview();
+begin
+ // Stop video preview of previous song
+ if Assigned(fCurrentVideo) then
+ begin
+ fCurrentVideo.Stop();
+ fCurrentVideo := nil;
+ end;
+end;
+
// Changes previewed song
procedure TScreenSong.ChangeMusic;
begin
StopMusicPreview();
+ StopVideoPreview();
PreviewOpened := -1;
StartMusicPreview();
+ StartVideoPreview();
end;
procedure TScreenSong.SkipTo(Target: cardinal);