2007-01-08 22:11:06 +01:00
// Copyright (c) 2005-2007, Rodrigo Braz Monteiro
2006-01-16 22:02:54 +01:00
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------------
//
// AEGISUB
//
// Website: http://aegisub.cellosoft.com
// Contact: mailto:zeratul@cellosoft.com
//
////////////
// Includes
2009-01-04 07:31:48 +01:00
# include "config.h"
2007-01-23 21:50:41 +01:00
# include <wx/glcanvas.h>
2007-09-12 01:22:26 +02:00
# ifdef __APPLE__
2007-04-22 04:24:27 +02:00
# include <OpenGL/GL.h>
# include <OpenGL/glu.h>
# else
2007-01-22 23:57:45 +01:00
# include <GL/gl.h>
# include <GL/glu.h>
2007-04-22 04:24:27 +02:00
# endif
2007-01-06 22:07:51 +01:00
# include <wx/image.h>
# include <string.h>
# include <wx/clipbrd.h>
# include <wx/filename.h>
# include <wx/config.h>
# include "utils.h"
2006-01-16 22:02:54 +01:00
# include "video_display.h"
2008-03-07 22:00:20 +01:00
# include "video_provider_manager.h"
2006-01-16 22:02:54 +01:00
# include "vfr.h"
# include "ass_file.h"
# include "ass_time.h"
# include "ass_dialogue.h"
2007-01-08 22:11:06 +01:00
# include "ass_style.h"
2006-01-16 22:02:54 +01:00
# include "subs_grid.h"
# include "vfw_wrap.h"
2006-02-23 02:44:48 +01:00
# include "mkv_wrap.h"
2006-01-16 22:02:54 +01:00
# include "options.h"
# include "subs_edit_box.h"
# include "audio_display.h"
# include "main.h"
# include "video_slider.h"
2007-01-11 04:53:20 +01:00
# include "video_box.h"
2007-06-28 22:29:56 +02:00
# include "gl_wrap.h"
2007-07-01 02:19:55 +02:00
# include "visual_tool.h"
# include "visual_tool_cross.h"
2007-07-01 04:23:57 +02:00
# include "visual_tool_rotatez.h"
2007-07-01 04:46:12 +02:00
# include "visual_tool_rotatexy.h"
2007-07-01 05:17:56 +02:00
# include "visual_tool_scale.h"
2007-07-01 05:36:17 +02:00
# include "visual_tool_clip.h"
2007-07-05 06:32:46 +02:00
# include "visual_tool_vector_clip.h"
2007-07-01 05:36:17 +02:00
# include "visual_tool_drag.h"
2006-01-16 22:02:54 +01:00
///////
// IDs
enum {
2007-04-08 00:03:06 +02:00
VIDEO_MENU_COPY_COORDS = 1230 ,
VIDEO_MENU_COPY_TO_CLIPBOARD ,
VIDEO_MENU_COPY_TO_CLIPBOARD_RAW ,
2006-01-16 22:02:54 +01:00
VIDEO_MENU_SAVE_SNAPSHOT ,
2007-04-08 00:03:06 +02:00
VIDEO_MENU_SAVE_SNAPSHOT_RAW
2006-01-16 22:02:54 +01:00
} ;
///////////////
// Event table
2007-01-21 07:30:19 +01:00
BEGIN_EVENT_TABLE ( VideoDisplay , wxGLCanvas )
EVT_MOUSE_EVENTS ( VideoDisplay : : OnMouseEvent )
2007-01-23 21:50:41 +01:00
EVT_KEY_DOWN ( VideoDisplay : : OnKey )
2007-01-21 07:30:19 +01:00
EVT_PAINT ( VideoDisplay : : OnPaint )
2007-01-23 05:42:08 +01:00
EVT_SIZE ( VideoDisplay : : OnSizeEvent )
2007-01-21 07:30:19 +01:00
EVT_ERASE_BACKGROUND ( VideoDisplay : : OnEraseBackground )
2006-01-16 22:02:54 +01:00
2007-04-08 00:03:06 +02:00
EVT_MENU ( VIDEO_MENU_COPY_COORDS , VideoDisplay : : OnCopyCoords )
2006-01-16 22:02:54 +01:00
EVT_MENU ( VIDEO_MENU_COPY_TO_CLIPBOARD , VideoDisplay : : OnCopyToClipboard )
EVT_MENU ( VIDEO_MENU_SAVE_SNAPSHOT , VideoDisplay : : OnSaveSnapshot )
2007-04-08 00:03:06 +02:00
EVT_MENU ( VIDEO_MENU_COPY_TO_CLIPBOARD_RAW , VideoDisplay : : OnCopyToClipboardRaw )
EVT_MENU ( VIDEO_MENU_SAVE_SNAPSHOT_RAW , VideoDisplay : : OnSaveSnapshotRaw )
2006-01-16 22:02:54 +01:00
END_EVENT_TABLE ( )
2007-01-22 23:57:45 +01:00
//////////////
// Parameters
2007-07-05 06:32:46 +02:00
int attribList [ ] = { WX_GL_RGBA , WX_GL_DOUBLEBUFFER , WX_GL_STENCIL_SIZE , 8 , 0 } ;
2007-01-22 23:57:45 +01:00
2006-01-16 22:02:54 +01:00
///////////////
// Constructor
VideoDisplay : : VideoDisplay ( wxWindow * parent , wxWindowID id , const wxPoint & pos , const wxSize & size , long style , const wxString & name )
2007-09-12 01:22:26 +02:00
# ifdef __WXMAC__
: wxGLCanvas ( parent , id , pos , size , style , name , attribList )
# else
2007-01-22 23:57:45 +01:00
: wxGLCanvas ( parent , id , attribList , pos , size , style , name )
2007-09-12 01:22:26 +02:00
# endif
2006-01-16 22:02:54 +01:00
{
2007-01-21 07:30:19 +01:00
// Set options
2007-07-04 06:24:47 +02:00
box = NULL ;
2007-01-23 21:50:41 +01:00
locked = false ;
2006-01-16 22:02:54 +01:00
ControlSlider = NULL ;
PositionDisplay = NULL ;
2007-01-23 21:50:41 +01:00
w = h = dx2 = dy2 = 8 ;
dx1 = dy1 = 0 ;
2006-01-16 22:02:54 +01:00
origSize = size ;
2007-01-21 07:30:19 +01:00
zoomValue = 1.0 ;
2007-01-23 07:32:16 +01:00
freeSize = false ;
2007-07-01 02:19:55 +02:00
visual = NULL ;
2007-01-21 07:30:19 +01:00
SetCursor ( wxNullCursor ) ;
2007-07-01 02:19:55 +02:00
visualMode = - 1 ;
SetVisualMode ( 0 ) ;
2006-01-16 22:02:54 +01:00
}
//////////////
// Destructor
VideoDisplay : : ~ VideoDisplay ( ) {
2007-01-08 22:11:06 +01:00
delete visual ;
2007-07-01 02:19:55 +02:00
visual = NULL ;
2007-01-21 07:30:19 +01:00
VideoContext : : Get ( ) - > RemoveDisplay ( this ) ;
2006-01-16 22:02:54 +01:00
}
2007-04-18 06:51:17 +02:00
///////////////
// Show cursor
void VideoDisplay : : ShowCursor ( bool show ) {
// Show
if ( show ) SetCursor ( wxNullCursor ) ;
// Hide
else {
// Bleeeh! Hate this 'solution':
# if __WXGTK__
static char cursor_image [ ] = { 0 } ;
wxCursor cursor ( cursor_image , 8 , 1 , - 1 , - 1 , cursor_image ) ;
# else
wxCursor cursor ( wxCURSOR_BLANK ) ;
# endif // __WXGTK__
SetCursor ( cursor ) ;
}
}
2007-01-21 07:30:19 +01:00
//////////
// Render
2009-06-01 17:26:26 +02:00
void VideoDisplay : : Render ( )
// Yes it's legal C++ to replace the body of a function with one huge try..catch statement
try {
2007-01-21 07:30:19 +01:00
// Is shown?
2007-01-23 05:42:08 +01:00
if ( ! IsShownOnScreen ( ) ) return ;
2008-01-13 06:57:09 +01:00
if ( ! wxIsMainThread ( ) ) throw _T ( " Error: trying to render from non-primary thread " ) ;
2007-01-21 07:30:19 +01:00
2007-04-02 01:07:29 +02:00
// Get video context
2007-01-21 07:30:19 +01:00
VideoContext * context = VideoContext : : Get ( ) ;
2007-03-30 01:04:26 +02:00
wxASSERT ( context ) ;
2007-04-02 01:07:29 +02:00
if ( ! context - > IsLoaded ( ) ) return ;
// Set GL context
2008-01-12 04:09:48 +01:00
//wxMutexLocker glLock(OpenGLWrapper::glMutex);
2007-09-12 01:22:26 +02:00
# ifdef __WXMAC__
SetCurrent ( ) ;
# else
2007-01-21 07:30:19 +01:00
SetCurrent ( * context - > GetGLContext ( this ) ) ;
2007-09-12 01:22:26 +02:00
# endif
2007-01-21 07:30:19 +01:00
// Get sizes
int w , h , sw , sh , pw , ph ;
GetClientSize ( & w , & h ) ;
2007-03-30 01:04:26 +02:00
wxASSERT ( w > 0 ) ;
wxASSERT ( h > 0 ) ;
2007-01-21 07:30:19 +01:00
context - > GetScriptSize ( sw , sh ) ;
pw = context - > GetWidth ( ) ;
ph = context - > GetHeight ( ) ;
2007-03-30 01:04:26 +02:00
wxASSERT ( pw > 0 ) ;
wxASSERT ( ph > 0 ) ;
2007-01-21 07:30:19 +01:00
2007-07-05 06:32:46 +02:00
// Clear frame buffer
glClearColor ( 0 , 0 , 0 , 0 ) ;
if ( glGetError ( ) ) throw _T ( " Error setting glClearColor(). " ) ;
glClearStencil ( 0 ) ;
if ( glGetError ( ) ) throw _T ( " Error setting glClearStencil(). " ) ;
glClear ( GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ) ;
if ( glGetError ( ) ) throw _T ( " Error calling glClear(). " ) ;
2007-01-23 07:32:16 +01:00
// Freesized transform
dx1 = 0 ;
dy1 = 0 ;
dx2 = w ;
dy2 = h ;
if ( freeSize ) {
2007-03-30 01:04:26 +02:00
// Set aspect ratio
2007-01-23 07:32:16 +01:00
float thisAr = float ( w ) / float ( h ) ;
float vidAr ;
if ( context - > GetAspectRatioType ( ) = = 0 ) vidAr = float ( pw ) / float ( ph ) ;
else vidAr = context - > GetAspectRatioValue ( ) ;
// Window is wider than video, blackbox left/right
if ( thisAr - vidAr > 0.01f ) {
2007-04-04 22:42:44 +02:00
int delta = int ( w - vidAr * h ) ;
2007-01-23 07:32:16 +01:00
dx1 + = delta / 2 ;
dx2 - = delta ;
}
// Video is wider than window, blackbox top/bottom
else if ( vidAr - thisAr > 0.01f ) {
2007-04-04 22:42:44 +02:00
int delta = int ( h - w / vidAr ) ;
2007-01-23 07:32:16 +01:00
dy1 + = delta / 2 ;
dy2 - = delta ;
}
}
2007-01-21 07:30:19 +01:00
// Set viewport
glEnable ( GL_TEXTURE_2D ) ;
2007-03-30 01:04:26 +02:00
if ( glGetError ( ) ) throw _T ( " Error enabling texturing. " ) ;
2007-01-22 21:48:45 +01:00
glMatrixMode ( GL_MODELVIEW ) ;
2007-01-21 07:30:19 +01:00
glLoadIdentity ( ) ;
2007-01-23 07:32:16 +01:00
glViewport ( dx1 , dy1 , dx2 , dy2 ) ;
2008-01-11 06:44:00 +01:00
if ( glGetError ( ) ) throw _T ( " Error setting GL viewport. " ) ;
2007-01-22 21:48:45 +01:00
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity ( ) ;
2007-01-21 07:30:19 +01:00
glOrtho ( 0.0f , sw , sh , 0.0f , - 1000.0f , 1000.0f ) ;
glMatrixMode ( GL_MODELVIEW ) ;
2007-03-30 01:04:26 +02:00
if ( glGetError ( ) ) throw _T ( " Error setting up matrices (wtf?). " ) ;
2007-06-28 22:29:56 +02:00
glShadeModel ( GL_FLAT ) ;
2007-01-21 07:30:19 +01:00
// Texture mode
if ( w ! = pw | | h ! = ph ) {
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
2007-03-30 01:04:26 +02:00
if ( glGetError ( ) ) throw _T ( " Error setting texture parameter min filter. " ) ;
2007-01-21 07:30:19 +01:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
2007-03-30 01:04:26 +02:00
if ( glGetError ( ) ) throw _T ( " Error setting texture parameter mag filter. " ) ;
2007-01-21 07:30:19 +01:00
}
else {
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
2007-03-30 01:04:26 +02:00
if ( glGetError ( ) ) throw _T ( " Error setting texture parameter min filter. " ) ;
2007-01-21 07:30:19 +01:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
2007-03-30 01:04:26 +02:00
if ( glGetError ( ) ) throw _T ( " Error setting texture parameter mag filter. " ) ;
2006-01-16 22:02:54 +01:00
}
2007-01-21 07:30:19 +01:00
// Texture coordinates
float top = 0.0f ;
float bot = context - > GetTexH ( ) ;
2007-03-30 01:04:26 +02:00
wxASSERT ( bot ! = 0.0f ) ;
2007-01-21 07:30:19 +01:00
if ( context - > IsInverted ( ) ) {
top = context - > GetTexH ( ) ;
bot = 0.0f ;
}
float left = 0.0 ;
float right = context - > GetTexW ( ) ;
2007-03-30 01:04:26 +02:00
wxASSERT ( right ! = 0.0f ) ;
2007-01-21 07:30:19 +01:00
2007-01-27 07:15:25 +01:00
// Draw frame
2007-01-21 07:30:19 +01:00
glDisable ( GL_BLEND ) ;
2007-03-30 01:04:26 +02:00
if ( glGetError ( ) ) throw _T ( " Error disabling blending. " ) ;
2007-01-27 07:15:25 +01:00
context - > SetShader ( true ) ;
2007-01-22 23:57:45 +01:00
glBindTexture ( GL_TEXTURE_2D , VideoContext : : Get ( ) - > GetFrameAsTexture ( - 1 ) ) ;
2007-03-30 01:04:26 +02:00
if ( glGetError ( ) ) throw _T ( " Error binding texture. " ) ;
2007-01-21 07:30:19 +01:00
glColor4f ( 1.0f , 1.0f , 1.0f , 1.0f ) ;
glBegin ( GL_QUADS ) ;
// Top-left
glTexCoord2f ( left , top ) ;
glVertex2f ( 0 , 0 ) ;
// Bottom-left
glTexCoord2f ( left , bot ) ;
glVertex2f ( 0 , sh ) ;
2007-01-22 23:57:45 +01:00
// Bottom-right
glTexCoord2f ( right , bot ) ;
glVertex2f ( sw , sh ) ;
// Top-right
glTexCoord2f ( right , top ) ;
glVertex2f ( sw , 0 ) ;
2007-01-21 07:30:19 +01:00
glEnd ( ) ;
2007-01-27 07:15:25 +01:00
context - > SetShader ( false ) ;
2007-06-28 22:29:56 +02:00
glDisable ( GL_TEXTURE_2D ) ;
// TV effects
DrawTVEffects ( ) ;
2007-01-02 21:07:52 +01:00
2007-01-21 07:30:19 +01:00
// Draw overlay
2007-07-01 02:19:55 +02:00
if ( visual ) visual - > Draw ( ) ;
2007-01-02 21:07:52 +01:00
2007-01-21 07:30:19 +01:00
// Swap buffers
2007-04-13 02:44:46 +02:00
glFinish ( ) ;
2007-03-30 01:09:40 +02:00
//if (glGetError()) throw _T("Error finishing gl operation.");
2007-01-21 07:30:19 +01:00
SwapBuffers ( ) ;
2007-01-02 21:07:52 +01:00
}
2009-06-01 17:26:26 +02:00
catch ( const wxChar * err ) {
wxLogError (
_T ( " An error occurred trying to render the video frame to screen. \n " )
2009-06-01 17:29:22 +02:00
_T ( " If you get this error regardless of which video file you use, and also if you use dummy video, Aegisub might not work with your graphics card's OpenGL driver. \n " )
2009-06-01 17:26:26 +02:00
_T ( " Error message reported: %s " ) ,
err ) ;
VideoContext : : Get ( ) - > Reset ( ) ;
}
catch ( . . . ) {
wxLogError (
_T ( " An error occurred trying to render the video frame to screen. \n " )
2009-06-01 17:29:22 +02:00
_T ( " If you get this error regardless of which video file you use, and also if you use dummy video, Aegisub might not work with your graphics card's OpenGL driver. \n " )
2009-06-01 17:26:26 +02:00
_T ( " No further error message given. " ) ) ;
VideoContext : : Get ( ) - > Reset ( ) ;
}
2007-01-02 21:07:52 +01:00
2007-06-28 22:29:56 +02:00
///////////////////////////////////
// TV effects (overscan and so on)
void VideoDisplay : : DrawTVEffects ( ) {
// Get coordinates
int sw , sh ;
VideoContext * context = VideoContext : : Get ( ) ;
context - > GetScriptSize ( sw , sh ) ;
2007-06-28 23:35:37 +02:00
bool drawOverscan = Options . AsBool ( _T ( " Show Overscan Mask " ) ) ;
2007-06-28 22:29:56 +02:00
// Draw overscan mask
if ( drawOverscan ) {
2007-06-29 01:27:37 +02:00
// Get aspect ration
double ar = context - > GetAspectRatioValue ( ) ;
// Based on BBC's guidelines: http://www.bbc.co.uk/guidelines/dq/pdf/tv/tv_standards_london.pdf
// 16:9 or wider
if ( ar > 1.75 ) {
DrawOverscanMask ( int ( sw * 0.1 ) , int ( sh * 0.05 ) , wxColour ( 30 , 70 , 200 ) , 0.5 ) ;
DrawOverscanMask ( int ( sw * 0.035 ) , int ( sh * 0.035 ) , wxColour ( 30 , 70 , 200 ) , 0.5 ) ;
}
// Less wide than 16:9 (use 4:3 standard)
else {
DrawOverscanMask ( int ( sw * 0.067 ) , int ( sh * 0.05 ) , wxColour ( 30 , 70 , 200 ) , 0.5 ) ;
DrawOverscanMask ( int ( sw * 0.033 ) , int ( sh * 0.035 ) , wxColour ( 30 , 70 , 200 ) , 0.5 ) ;
}
2007-06-28 22:29:56 +02:00
}
}
//////////////////////
// Draw overscan mask
void VideoDisplay : : DrawOverscanMask ( int sizeH , int sizeV , wxColour colour , double alpha ) {
// Parameters
int sw , sh ;
VideoContext * context = VideoContext : : Get ( ) ;
context - > GetScriptSize ( sw , sh ) ;
2007-06-28 23:35:37 +02:00
int rad1 = int ( sh * 0.05 ) ;
2007-06-28 22:29:56 +02:00
int gapH = sizeH + rad1 ;
int gapV = sizeV + rad1 ;
int rad2 = ( int ) sqrt ( double ( gapH * gapH + gapV * gapV ) ) + 1 ;
// Set up GL wrapper
OpenGLWrapper gl ;
gl . SetFillColour ( colour , alpha ) ;
gl . SetLineColour ( wxColour ( 0 , 0 , 0 ) , 0.0 , 1 ) ;
// Draw rectangles
gl . DrawRectangle ( gapH , 0 , sw - gapH , sizeV ) ; // Top
gl . DrawRectangle ( sw - sizeH , gapV , sw , sh - gapV ) ; // Right
gl . DrawRectangle ( gapH , sh - sizeV , sw - gapH , sh ) ; // Bottom
gl . DrawRectangle ( 0 , gapV , sizeH , sh - gapV ) ; // Left
// Draw corners
gl . DrawRing ( gapH , gapV , rad1 , rad2 , 1.0 , 180.0 , 270.0 ) ; // Top-left
gl . DrawRing ( sw - gapH , gapV , rad1 , rad2 , 1.0 , 90.0 , 180.0 ) ; // Top-right
gl . DrawRing ( sw - gapH , sh - gapV , rad1 , rad2 , 1.0 , 0.0 , 90.0 ) ; // Bottom-right
gl . DrawRing ( gapH , sh - gapV , rad1 , rad2 , 1.0 , 270.0 , 360.0 ) ; // Bottom-left
// Done
glDisable ( GL_BLEND ) ;
}
2007-01-21 07:30:19 +01:00
///////////////
// Update size
void VideoDisplay : : UpdateSize ( ) {
2008-01-11 06:44:00 +01:00
// Don't do anything if it's a free sizing display
//if (freeSize) return;
2007-01-23 07:32:16 +01:00
2007-01-22 00:16:03 +01:00
// Loaded?
2007-01-23 07:32:16 +01:00
VideoContext * con = VideoContext : : Get ( ) ;
2007-03-30 01:04:26 +02:00
wxASSERT ( con ) ;
2007-01-23 07:32:16 +01:00
if ( ! con - > IsLoaded ( ) ) return ;
2007-01-23 21:50:41 +01:00
if ( ! IsShownOnScreen ( ) ) return ;
2007-01-22 00:16:03 +01:00
2007-01-21 07:30:19 +01:00
// Get size
2008-01-11 06:44:00 +01:00
if ( freeSize ) {
GetClientSize ( & w , & h ) ;
}
else {
if ( con - > GetAspectRatioType ( ) = = 0 ) w = int ( con - > GetWidth ( ) * zoomValue ) ;
else w = int ( con - > GetHeight ( ) * zoomValue * con - > GetAspectRatioValue ( ) ) ;
h = int ( con - > GetHeight ( ) * zoomValue ) ;
}
2007-01-21 07:30:19 +01:00
int _w , _h ;
2007-01-23 21:50:41 +01:00
if ( w < = 1 | | h < = 1 ) return ;
locked = true ;
2006-01-16 22:02:54 +01:00
2007-01-21 07:30:19 +01:00
// Set the size for this control
SetSizeHints ( w , h , w , h ) ;
SetClientSize ( w , h ) ;
GetSize ( & _w , & _h ) ;
2007-03-30 01:04:26 +02:00
wxASSERT ( _w > 0 ) ;
wxASSERT ( _h > 0 ) ;
2007-01-21 07:30:19 +01:00
SetSizeHints ( _w , _h , _w , _h ) ;
box - > VideoSizer - > Fit ( box ) ;
// Layout
box - > GetParent ( ) - > Layout ( ) ;
SetClientSize ( w , h ) ;
2008-11-10 00:08:44 +01:00
GetSize ( & _w , & _h ) ;
SetMaxSize ( wxSize ( _w , _h ) ) ;
2006-01-16 22:02:54 +01:00
2007-01-21 07:30:19 +01:00
// Refresh
2007-01-23 21:50:41 +01:00
locked = false ;
2007-01-21 07:30:19 +01:00
Refresh ( false ) ;
2006-01-22 13:44:53 +01:00
}
2006-01-16 22:02:54 +01:00
2007-01-21 07:30:19 +01:00
//////////
// Resets
void VideoDisplay : : Reset ( ) {
2007-03-30 01:04:26 +02:00
// Only calculate sizes if it's visible
if ( ! IsShownOnScreen ( ) ) return ;
2007-01-21 07:30:19 +01:00
int w = origSize . GetX ( ) ;
int h = origSize . GetY ( ) ;
2007-03-30 01:04:26 +02:00
wxASSERT ( w > 0 ) ;
wxASSERT ( h > 0 ) ;
2007-01-21 07:30:19 +01:00
SetClientSize ( w , h ) ;
int _w , _h ;
GetSize ( & _w , & _h ) ;
2007-03-30 01:04:26 +02:00
wxASSERT ( _w > 0 ) ;
wxASSERT ( _h > 0 ) ;
2007-01-21 07:30:19 +01:00
SetSizeHints ( _w , _h , _w , _h ) ;
2006-01-16 22:02:54 +01:00
}
2007-01-23 05:42:08 +01:00
///////////////
// Paint event
2006-01-16 22:02:54 +01:00
void VideoDisplay : : OnPaint ( wxPaintEvent & event ) {
wxPaintDC dc ( this ) ;
2007-01-21 07:30:19 +01:00
Render ( ) ;
2006-01-16 22:02:54 +01:00
}
2007-01-23 05:42:08 +01:00
//////////////
// Size Event
void VideoDisplay : : OnSizeEvent ( wxSizeEvent & event ) {
2007-01-23 21:50:41 +01:00
//Refresh(false);
2008-01-11 06:44:00 +01:00
if ( freeSize ) {
UpdateSize ( ) ;
}
2007-01-23 21:50:41 +01:00
event . Skip ( ) ;
2007-01-23 05:42:08 +01:00
}
2006-01-16 22:02:54 +01:00
///////////////
// Mouse stuff
void VideoDisplay : : OnMouseEvent ( wxMouseEvent & event ) {
2007-01-23 21:50:41 +01:00
// Locked?
if ( locked ) return ;
2008-03-07 00:27:54 +01:00
// Mouse coordinates
mouse_x = event . GetX ( ) ;
mouse_y = event . GetY ( ) ;
2006-01-16 22:02:54 +01:00
// Disable when playing
2007-01-21 07:30:19 +01:00
if ( VideoContext : : Get ( ) - > IsPlaying ( ) ) return ;
2006-01-16 22:02:54 +01:00
// Right click
if ( event . ButtonUp ( wxMOUSE_BTN_RIGHT ) ) {
2007-04-18 06:51:17 +02:00
// Create menu
2006-01-16 22:02:54 +01:00
wxMenu menu ;
menu . Append ( VIDEO_MENU_SAVE_SNAPSHOT , _ ( " Save PNG snapshot " ) ) ;
menu . Append ( VIDEO_MENU_COPY_TO_CLIPBOARD , _ ( " Copy image to Clipboard " ) ) ;
2007-04-08 00:03:06 +02:00
menu . AppendSeparator ( ) ;
2009-05-15 14:44:36 +02:00
menu . Append ( VIDEO_MENU_SAVE_SNAPSHOT_RAW , _ ( " Save PNG snapshot (no subtitles) " ) ) ;
menu . Append ( VIDEO_MENU_COPY_TO_CLIPBOARD_RAW , _ ( " Copy image to Clipboard (no subtitles) " ) ) ;
2007-04-08 00:03:06 +02:00
menu . AppendSeparator ( ) ;
2006-01-16 22:02:54 +01:00
menu . Append ( VIDEO_MENU_COPY_COORDS , _ ( " Copy coordinates to Clipboard " ) ) ;
2007-04-18 06:51:17 +02:00
// Show cursor and popup
ShowCursor ( true ) ;
2006-01-16 22:02:54 +01:00
PopupMenu ( & menu ) ;
return ;
}
2007-04-18 06:51:17 +02:00
// Enforce correct cursor display
2007-07-01 02:19:55 +02:00
ShowCursor ( visualMode ! = 0 ) ;
2007-04-18 06:51:17 +02:00
2007-01-09 02:52:30 +01:00
// Click?
if ( event . ButtonDown ( wxMOUSE_BTN_ANY ) ) {
SetFocus ( ) ;
}
2007-01-08 22:11:06 +01:00
// Send to visual
2007-07-01 02:19:55 +02:00
if ( visual ) visual - > OnMouseEvent ( event ) ;
2006-01-16 22:02:54 +01:00
}
2007-01-09 02:52:30 +01:00
/////////////
// Key event
void VideoDisplay : : OnKey ( wxKeyEvent & event ) {
2007-07-01 02:19:55 +02:00
// FIXME: should these be configurable?
// Think of the frenchmen and other people not using qwerty layout
if ( event . GetKeyCode ( ) = = ' A ' ) SetVisualMode ( 0 ) ;
if ( event . GetKeyCode ( ) = = ' S ' ) SetVisualMode ( 1 ) ;
if ( event . GetKeyCode ( ) = = ' D ' ) SetVisualMode ( 2 ) ;
if ( event . GetKeyCode ( ) = = ' F ' ) SetVisualMode ( 3 ) ;
if ( event . GetKeyCode ( ) = = ' G ' ) SetVisualMode ( 4 ) ;
2007-07-05 06:32:46 +02:00
if ( event . GetKeyCode ( ) = = ' H ' ) SetVisualMode ( 5 ) ;
if ( event . GetKeyCode ( ) = = ' J ' ) SetVisualMode ( 6 ) ;
2007-07-27 06:05:18 +02:00
event . Skip ( ) ;
2007-01-09 02:52:30 +01:00
}
2006-01-16 22:02:54 +01:00
///////////////////
// Sets zoom level
void VideoDisplay : : SetZoom ( double value ) {
2006-02-19 03:31:25 +01:00
zoomValue = value ;
2007-01-21 07:30:19 +01:00
UpdateSize ( ) ;
2006-01-16 22:02:54 +01:00
}
//////////////////////
// Sets zoom position
void VideoDisplay : : SetZoomPos ( int value ) {
if ( value < 0 ) value = 0 ;
if ( value > 15 ) value = 15 ;
SetZoom ( double ( value + 1 ) / 8.0 ) ;
if ( zoomBox - > GetSelection ( ) ! = value ) zoomBox - > SetSelection ( value ) ;
}
////////////////////////////
// Updates position display
void VideoDisplay : : UpdatePositionDisplay ( ) {
// Update position display control
if ( ! PositionDisplay ) {
throw _T ( " Position Display not set! " ) ;
}
// Get time
2007-01-21 07:30:19 +01:00
int frame_n = VideoContext : : Get ( ) - > GetFrameN ( ) ;
2006-02-25 00:07:30 +01:00
int time = VFR_Output . GetTimeAtFrame ( frame_n , true , true ) ;
2006-01-16 22:02:54 +01:00
int temp = time ;
int h = 0 , m = 0 , s = 0 , ms = 0 ;
while ( temp > = 3600000 ) {
temp - = 3600000 ;
h + + ;
}
while ( temp > = 60000 ) {
temp - = 60000 ;
m + + ;
}
while ( temp > = 1000 ) {
temp - = 1000 ;
s + + ;
}
ms = temp ;
// Position display update
PositionDisplay - > SetValue ( wxString : : Format ( _T ( " %01i:%02i:%02i.%03i - %i " ) , h , m , s , ms , frame_n ) ) ;
2007-01-21 07:30:19 +01:00
if ( VideoContext : : Get ( ) - > GetKeyFrames ( ) . Index ( frame_n ) ! = wxNOT_FOUND ) {
2006-01-16 22:02:54 +01:00
PositionDisplay - > SetBackgroundColour ( Options . AsColour ( _T ( " Grid selection background " ) ) ) ;
PositionDisplay - > SetForegroundColour ( Options . AsColour ( _T ( " Grid selection foreground " ) ) ) ;
}
else {
PositionDisplay - > SetBackgroundColour ( wxNullColour ) ;
PositionDisplay - > SetForegroundColour ( wxNullColour ) ;
}
// Subs position display update
UpdateSubsRelativeTime ( ) ;
}
////////////////////////////////////////////////////
// Updates box with subs position relative to frame
void VideoDisplay : : UpdateSubsRelativeTime ( ) {
// Set variables
wxString startSign ;
wxString endSign ;
int startOff , endOff ;
2007-01-21 07:30:19 +01:00
int frame_n = VideoContext : : Get ( ) - > GetFrameN ( ) ;
AssDialogue * curLine = VideoContext : : Get ( ) - > curLine ;
2006-01-16 22:02:54 +01:00
// Set start/end
if ( curLine ) {
2006-02-25 00:07:30 +01:00
int time = VFR_Output . GetTimeAtFrame ( frame_n , true , true ) ;
2006-01-16 22:02:54 +01:00
startOff = time - curLine - > Start . GetMS ( ) ;
endOff = time - curLine - > End . GetMS ( ) ;
}
// Fallback to zero
else {
startOff = 0 ;
endOff = 0 ;
}
// Positive signs
if ( startOff > 0 ) startSign = _T ( " + " ) ;
if ( endOff > 0 ) endSign = _T ( " + " ) ;
// Update line
SubsPosition - > SetValue ( wxString : : Format ( _T ( " %s%ims; %s%ims " ) , startSign . c_str ( ) , startOff , endSign . c_str ( ) , endOff ) ) ;
}
/////////////////////
// Copy to clipboard
void VideoDisplay : : OnCopyToClipboard ( wxCommandEvent & event ) {
if ( wxTheClipboard - > Open ( ) ) {
2007-01-21 07:30:19 +01:00
wxTheClipboard - > SetData ( new wxBitmapDataObject ( wxBitmap ( VideoContext : : Get ( ) - > GetFrame ( - 1 ) . GetImage ( ) , 24 ) ) ) ;
2006-01-16 22:02:54 +01:00
wxTheClipboard - > Close ( ) ;
}
}
2007-04-08 00:03:06 +02:00
//////////////////////////
// Copy to clipboard (raw)
void VideoDisplay : : OnCopyToClipboardRaw ( wxCommandEvent & event ) {
if ( wxTheClipboard - > Open ( ) ) {
wxTheClipboard - > SetData ( new wxBitmapDataObject ( wxBitmap ( VideoContext : : Get ( ) - > GetFrame ( - 1 , true ) . GetImage ( ) , 24 ) ) ) ;
wxTheClipboard - > Close ( ) ;
}
}
2006-01-16 22:02:54 +01:00
/////////////////
// Save snapshot
void VideoDisplay : : OnSaveSnapshot ( wxCommandEvent & event ) {
2007-04-08 00:03:06 +02:00
VideoContext : : Get ( ) - > SaveSnapshot ( false ) ;
}
//////////////////////
// Save snapshot (raw)
void VideoDisplay : : OnSaveSnapshotRaw ( wxCommandEvent & event ) {
VideoContext : : Get ( ) - > SaveSnapshot ( true ) ;
2006-01-16 22:02:54 +01:00
}
/////////////////////
// Copy coordinates
void VideoDisplay : : OnCopyCoords ( wxCommandEvent & event ) {
if ( wxTheClipboard - > Open ( ) ) {
int sw , sh ;
2007-01-21 07:30:19 +01:00
VideoContext : : Get ( ) - > GetScriptSize ( sw , sh ) ;
2008-03-07 00:27:54 +01:00
int vx = ( sw * mouse_x + w / 2 ) / w ;
int vy = ( sh * mouse_y + h / 2 ) / h ;
2006-01-16 22:02:54 +01:00
wxTheClipboard - > SetData ( new wxTextDataObject ( wxString : : Format ( _T ( " %i,%i " ) , vx , vy ) ) ) ;
wxTheClipboard - > Close ( ) ;
}
}
2007-01-23 07:32:16 +01:00
/////////////////////////////
// Convert mouse coordinates
void VideoDisplay : : ConvertMouseCoords ( int & x , int & y ) {
int w , h ;
GetClientSize ( & w , & h ) ;
2007-03-30 01:04:26 +02:00
wxASSERT ( dx2 > 0 ) ;
wxASSERT ( dy2 > 0 ) ;
wxASSERT ( w > 0 ) ;
wxASSERT ( h > 0 ) ;
2007-01-23 07:32:16 +01:00
x = ( x - dx1 ) * w / dx2 ;
y = ( y - dy1 ) * h / dy2 ;
}
2007-07-01 02:19:55 +02:00
////////////
// Set mode
void VideoDisplay : : SetVisualMode ( int mode ) {
// Set visual
2007-07-04 06:24:47 +02:00
if ( visualMode ! = mode ) {
// Get toolbar
2007-07-07 05:21:52 +02:00
wxToolBar * toolBar = NULL ;
2007-07-04 06:24:47 +02:00
if ( box ) {
toolBar = box - > visualSubToolBar ;
2007-07-07 05:21:52 +02:00
toolBar - > ClearTools ( ) ;
toolBar - > Realize ( ) ;
toolBar - > Show ( false ) ;
2007-07-06 07:47:03 +02:00
if ( ! box - > visualToolBar - > GetToolState ( mode + Video_Mode_Standard ) ) box - > visualToolBar - > ToggleTool ( mode + Video_Mode_Standard , true ) ;
2007-07-04 06:24:47 +02:00
}
// Replace mode
visualMode = mode ;
delete visual ;
switch ( mode ) {
case 0 : visual = new VisualToolCross ( this ) ; break ;
2007-07-07 05:21:52 +02:00
case 1 : visual = new VisualToolDrag ( this , toolBar ) ; break ;
2007-07-04 06:24:47 +02:00
case 2 : visual = new VisualToolRotateZ ( this ) ; break ;
case 3 : visual = new VisualToolRotateXY ( this ) ; break ;
case 4 : visual = new VisualToolScale ( this ) ; break ;
case 5 : visual = new VisualToolClip ( this ) ; break ;
2007-07-07 05:21:52 +02:00
case 6 : visual = new VisualToolVectorClip ( this , toolBar ) ; break ;
2007-07-04 06:24:47 +02:00
default : visual = NULL ;
}
// Update size to reflect toolbar changes
UpdateSize ( ) ;
2007-07-01 02:19:55 +02:00
}
// Render
Render ( ) ;
}