2006-01-16 22:02:54 +01:00
// Copyright (c) 2005, Rodrigo Braz Monteiro
// 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
# include "video_display.h"
2006-02-24 09:30:08 +01:00
# include "video_provider.h"
2006-01-16 22:02:54 +01:00
# include "vfr.h"
# include "ass_file.h"
# include "ass_time.h"
# include "ass_dialogue.h"
# include "subs_grid.h"
# include "vfw_wrap.h"
2006-04-15 00:53:12 +02:00
#if 0
2006-02-23 02:44:48 +01:00
# include "mkv_wrap.h"
2006-04-15 00:53:12 +02:00
# endif
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"
# include <wx/image.h>
# include <string.h>
# include <wx/clipbrd.h>
# include <wx/filename.h>
# include <wx/config.h>
2006-02-26 03:49:38 +01:00
# ifndef NO_FEX
2006-03-05 20:14:42 +01:00
# include "../FexTrackerSource/FexTracker.h"
# include "../FexTrackerSource/FexTrackingFeature.h"
# include "../FexTrackerSource/FexMovement.h"
2006-02-26 03:49:38 +01:00
# endif
2006-01-16 22:02:54 +01:00
///////
// IDs
enum {
VIDEO_MENU_COPY_TO_CLIPBOARD = 1230 ,
VIDEO_MENU_COPY_COORDS ,
VIDEO_MENU_SAVE_SNAPSHOT ,
VIDEO_PLAY_TIMER
} ;
///////////////
// Event table
BEGIN_EVENT_TABLE ( VideoDisplay , wxWindow )
EVT_MOUSE_EVENTS ( VideoDisplay : : OnMouseEvent )
EVT_LEAVE_WINDOW ( VideoDisplay : : OnMouseLeave )
EVT_PAINT ( VideoDisplay : : OnPaint )
EVT_TIMER ( VIDEO_PLAY_TIMER , VideoDisplay : : OnPlayTimer )
EVT_MENU ( VIDEO_MENU_COPY_TO_CLIPBOARD , VideoDisplay : : OnCopyToClipboard )
EVT_MENU ( VIDEO_MENU_SAVE_SNAPSHOT , VideoDisplay : : OnSaveSnapshot )
EVT_MENU ( VIDEO_MENU_COPY_COORDS , VideoDisplay : : OnCopyCoords )
END_EVENT_TABLE ( )
///////////////
// Constructor
VideoDisplay : : VideoDisplay ( wxWindow * parent , wxWindowID id , const wxPoint & pos , const wxSize & size , long style , const wxString & name )
: wxWindow ( parent , id , pos , size , style , name )
{
2006-01-22 13:44:53 +01:00
provider = NULL ;
2006-01-16 22:02:54 +01:00
curLine = NULL ;
backbuffer = NULL ;
ControlSlider = NULL ;
PositionDisplay = NULL ;
loaded = false ;
frame_n = 0 ;
origSize = size ;
arType = 0 ;
IsPlaying = false ;
threaded = Options . AsBool ( _T ( " Threaded Video " ) ) ;
nextFrame = - 1 ;
2006-02-19 03:31:25 +01:00
zoomValue = 0.5 ;
2006-01-16 22:02:54 +01:00
// Create PNG handler
wxPNGHandler * png = new wxPNGHandler ;
wxImage : : AddHandler ( png ) ;
// Set cursor
2006-03-26 05:05:43 +02:00
// Bleeeh! Hate this 'solution':
# if __WXGTK__
static char cursor_image [ ] = { 0 } ;
wxCursor cursor ( cursor_image , 8 , 1 , - 1 , - 1 , cursor_image ) ;
# else
2006-01-16 22:02:54 +01:00
wxCursor cursor ( wxCURSOR_BLANK ) ;
2006-03-26 05:05:43 +02:00
# endif // __WXGTK__
2006-01-16 22:02:54 +01:00
SetCursor ( cursor ) ;
}
//////////////
// Destructor
VideoDisplay : : ~ VideoDisplay ( ) {
2006-02-22 07:49:20 +01:00
wxRemoveFile ( tempfile ) ;
tempfile = _T ( " " ) ;
2006-01-22 13:44:53 +01:00
SetVideo ( _T ( " " ) ) ;
delete backbuffer ;
2006-01-16 22:02:54 +01:00
}
2006-01-22 13:44:53 +01:00
void VideoDisplay : : UpdateSize ( ) {
if ( provider ) {
w = provider - > GetWidth ( ) ;
h = provider - > GetHeight ( ) ;
2006-01-16 22:02:54 +01:00
2006-01-22 13:44:53 +01:00
// Set the size for this control
SetClientSize ( w , h ) ;
int _w , _h ;
GetSize ( & _w , & _h ) ;
SetSizeHints ( _w , _h , _w , _h ) ;
2006-01-16 22:02:54 +01:00
}
}
///////////////////////
2006-01-22 13:44:53 +01:00
// Sets video filename
void VideoDisplay : : SetVideo ( const wxString & filename ) {
2006-02-24 09:30:08 +01:00
// Unload video
2006-02-25 21:48:32 +01:00
delete provider ;
provider = NULL ;
2006-04-04 15:22:45 +02:00
//if (VFR_Output.GetFrameRateType() == VFR) VFR_Output.Unload();
//VFR_Input.Unload();
2006-02-25 21:48:32 +01:00
videoName = _T ( " " ) ;
loaded = false ;
frame_n = 0 ;
Reset ( ) ;
2006-02-24 09:30:08 +01:00
// Load video
2006-02-25 21:48:32 +01:00
if ( ! filename . IsEmpty ( ) ) {
2006-01-16 22:02:54 +01:00
try {
grid - > CommitChanges ( true ) ;
2006-02-24 09:30:08 +01:00
// Choose a provider
provider = VideoProvider : : GetProvider ( filename , GetTempWorkFile ( ) ) ;
2006-02-24 09:43:44 +01:00
provider - > SetZoom ( zoomValue ) ;
provider - > SetDAR ( GetARFromType ( arType ) ) ;
2006-02-25 21:48:32 +01:00
2006-04-15 00:53:12 +02:00
KeyFrames . Clear ( ) ;
#if 0
2006-02-25 21:48:32 +01:00
// Read extra data from file
bool mkvOpen = MatroskaWrapper : : wrapper . IsOpen ( ) ;
2006-02-23 02:44:48 +01:00
wxString ext = filename . Right ( 4 ) . Lower ( ) ;
2006-02-25 21:48:32 +01:00
KeyFrames . Clear ( ) ;
if ( ext = = _T ( " .mkv " ) | | mkvOpen ) {
2006-02-23 02:44:48 +01:00
// Parse mkv
2006-02-25 21:48:32 +01:00
if ( ! mkvOpen ) MatroskaWrapper : : wrapper . Open ( filename ) ;
2006-02-23 02:44:48 +01:00
// Get keyframes
2006-02-25 21:48:32 +01:00
KeyFrames = MatroskaWrapper : : wrapper . GetKeyFrames ( ) ;
2006-02-23 02:44:48 +01:00
// Ask to override timecodes
int override = wxYES ;
2006-02-24 17:45:10 +01:00
if ( VFR_Output . GetFrameRateType ( ) = = VFR ) override = wxMessageBox ( _T ( " You already have timecodes loaded. Replace them with the timecodes from the Matroska file? " ) , _T ( " Replace timecodes? " ) , wxYES_NO | wxICON_QUESTION ) ;
2006-02-25 21:48:32 +01:00
if ( override = = wxYES ) MatroskaWrapper : : wrapper . SetToTimecodes ( VFR_Output ) ;
2006-02-23 02:44:48 +01:00
// Close mkv
2006-02-25 21:48:32 +01:00
MatroskaWrapper : : wrapper . Close ( ) ;
2006-02-23 02:44:48 +01:00
}
2006-02-26 03:53:45 +01:00
# ifdef __WIN32__
2006-02-25 21:48:32 +01:00
else if ( ext = = _T ( " .avi " ) ) KeyFrames = VFWWrapper : : GetKeyFrames ( filename ) ;
2006-04-15 00:53:12 +02:00
# endif
2006-02-26 03:53:45 +01:00
# endif
2006-01-16 22:02:54 +01:00
2006-02-25 21:48:32 +01:00
// Update size
2006-01-22 13:44:53 +01:00
UpdateSize ( ) ;
2006-01-16 22:02:54 +01:00
2006-01-22 13:44:53 +01:00
//Gather video parameters
length = provider - > GetFrameCount ( ) ;
fps = provider - > GetFPS ( ) ;
VFR_Input . SetCFR ( fps ) ;
2006-02-24 17:45:10 +01:00
if ( ! VFR_Output . IsLoaded ( ) )
VFR_Output . SetCFR ( fps ) ;
2006-01-16 22:02:54 +01:00
2006-01-22 13:44:53 +01:00
// Set range of slider
ControlSlider - > SetRange ( 0 , length - 1 ) ;
ControlSlider - > SetValue ( 0 ) ;
2006-01-16 22:02:54 +01:00
2006-01-22 13:44:53 +01:00
videoName = filename ;
2006-01-16 22:02:54 +01:00
2006-01-22 13:44:53 +01:00
// Add to recent
Options . AddToRecentList ( filename , _T ( " Recent vid " ) ) ;
2006-01-16 22:02:54 +01:00
2006-01-22 13:44:53 +01:00
RefreshVideo ( ) ;
2006-02-25 00:07:30 +01:00
UpdatePositionDisplay ( ) ;
2006-01-22 13:44:53 +01:00
} catch ( wxString & e ) {
wxMessageBox ( e , _T ( " Error setting video " ) , wxICON_ERROR | wxOK ) ;
2006-01-16 22:02:54 +01:00
}
}
2006-01-22 13:44:53 +01:00
loaded = provider ! = NULL ;
}
2006-01-16 22:02:54 +01:00
//////////
// Resets
void VideoDisplay : : Reset ( ) {
w = origSize . GetX ( ) ;
h = origSize . GetY ( ) ;
SetClientSize ( w , h ) ;
int _w , _h ;
GetSize ( & _w , & _h ) ;
SetSizeHints ( _w , _h , _w , _h ) ;
}
2006-01-22 13:44:53 +01:00
void VideoDisplay : : RefreshSubtitles ( ) {
provider - > RefreshSubtitles ( ) ;
RefreshVideo ( ) ;
2006-01-16 22:02:54 +01:00
}
/////////////////
// OnPaint event
void VideoDisplay : : OnPaint ( wxPaintEvent & event ) {
wxPaintDC dc ( this ) ;
// Draw frame
2006-01-22 13:44:53 +01:00
dc . BeginDrawing ( ) ;
dc . DrawBitmap ( GetFrame ( frame_n ) , 0 , 0 ) ;
dc . EndDrawing ( ) ;
2006-01-16 22:02:54 +01:00
}
///////////////
// Mouse stuff
void VideoDisplay : : OnMouseEvent ( wxMouseEvent & event ) {
// Disable when playing
if ( IsPlaying ) return ;
2006-02-01 23:15:21 +01:00
if ( event . Leaving ( ) ) {
// OnMouseLeave isn't called as long as we have an OnMouseEvent
// Just check for it and call it manually instead
OnMouseLeave ( event ) ;
event . Skip ( true ) ;
return ;
}
2006-01-16 22:02:54 +01:00
// Right click
if ( event . ButtonUp ( wxMOUSE_BTN_RIGHT ) ) {
wxMenu menu ;
menu . Append ( VIDEO_MENU_SAVE_SNAPSHOT , _ ( " Save PNG snapshot " ) ) ;
menu . Append ( VIDEO_MENU_COPY_TO_CLIPBOARD , _ ( " Copy image to Clipboard " ) ) ;
menu . Append ( VIDEO_MENU_COPY_COORDS , _ ( " Copy coordinates to Clipboard " ) ) ;
PopupMenu ( & menu ) ;
return ;
}
2006-01-29 21:48:05 +01:00
// Coords
int x = event . GetX ( ) ;
int y = event . GetY ( ) ;
2006-02-26 03:49:38 +01:00
# ifndef NO_FEX
2006-01-28 22:47:46 +01:00
if ( event . ButtonDown ( wxMOUSE_BTN_LEFT ) )
2006-01-29 21:48:05 +01:00
{
MouseDownX = x ;
MouseDownY = y ;
2006-01-28 22:47:46 +01:00
bTrackerEditing = 1 ;
2006-01-29 21:48:05 +01:00
}
2006-01-28 22:47:46 +01:00
if ( event . ButtonUp ( wxMOUSE_BTN_LEFT ) )
bTrackerEditing = 0 ;
// Do tracker influence if needed
if ( bTrackerEditing )
{
AssDialogue * curline = grid - > GetDialogue ( grid - > editBox - > linen ) ;
int StartFrame , EndFrame , localframe ;
if ( curline
2006-02-24 17:45:10 +01:00
& & ( StartFrame = VFR_Output . GetFrameAtTime ( curline - > Start . GetMS ( ) , true ) ) < = frame_n
& & ( EndFrame = VFR_Output . GetFrameAtTime ( curline - > End . GetMS ( ) , false ) ) > = frame_n
2006-01-28 22:47:46 +01:00
)
2006-01-29 21:48:05 +01:00
{
localframe = frame_n - StartFrame ;
2006-02-24 21:04:04 +01:00
if ( TrackerEdit ! = 0 & & curline - > Tracker & & localframe < curline - > Tracker - > GetFrame ( ) )
2006-01-29 21:48:05 +01:00
curline - > Tracker - > InfluenceFeatures ( localframe , float ( x ) / provider - > GetZoom ( ) , float ( y ) / provider - > GetZoom ( ) , TrackerEdit ) ;
2006-02-24 21:04:04 +01:00
if ( MovementEdit ! = 0 & & curline - > Movement & & localframe < curline - > Movement - > Frames . size ( ) )
2006-01-29 21:48:05 +01:00
{ // no /provider->GetZoom() to improve precision
if ( MovementEdit = = 1 )
{
for ( int i = 0 ; i < curline - > Movement - > Frames . size ( ) ; i + + )
{
curline - > Movement - > Frames [ i ] . Pos . x + = float ( x - MouseDownX ) ;
curline - > Movement - > Frames [ i ] . Pos . y + = float ( y - MouseDownY ) ;
}
}
else if ( MovementEdit = = 2 )
{
curline - > Movement - > Frames [ localframe ] . Pos . x + = float ( x - MouseDownX ) ;
curline - > Movement - > Frames [ localframe ] . Pos . y + = float ( y - MouseDownY ) ;
}
2006-02-22 20:24:17 +01:00
else if ( MovementEdit = = 3 )
{
for ( int i = 0 ; i < = localframe ; i + + )
{
curline - > Movement - > Frames [ i ] . Pos . x + = float ( x - MouseDownX ) ;
curline - > Movement - > Frames [ i ] . Pos . y + = float ( y - MouseDownY ) ;
}
}
else if ( MovementEdit = = 4 )
{
for ( int i = localframe ; i < curline - > Movement - > Frames . size ( ) ; i + + )
{
curline - > Movement - > Frames [ i ] . Pos . x + = float ( x - MouseDownX ) ;
curline - > Movement - > Frames [ i ] . Pos . y + = float ( y - MouseDownY ) ;
}
}
2006-01-29 21:48:05 +01:00
}
MouseDownX = x ;
MouseDownY = y ;
}
2006-01-28 22:47:46 +01:00
}
2006-02-26 03:49:38 +01:00
# endif
2006-01-28 22:47:46 +01:00
2006-01-16 22:02:54 +01:00
// Text of current coords
int sw , sh ;
GetScriptSize ( sw , sh ) ;
int vx = ( sw * x + w / 2 ) / w ;
int vy = ( sh * y + h / 2 ) / h ;
wxString text ;
if ( ! event . ShiftDown ( ) ) text = wxString : : Format ( _T ( " %i,%i " ) , vx , vy ) ;
else text = wxString : : Format ( _T ( " %i,%i " ) , vx - sw , vy - sh ) ;
// Double click
if ( event . LeftDClick ( ) ) {
grid - > editBox - > SetOverride ( _T ( " \\ pos " ) , wxString : : Format ( _T ( " (%i,%i) " ) , vx , vy ) , 0 ) ;
grid - > editBox - > CommitText ( ) ;
grid - > ass - > FlagAsModified ( ) ;
grid - > CommitChanges ( ) ;
}
// Hover
if ( x ! = mouse_x | | y ! = mouse_y ) {
// Set coords
mouse_x = x ;
mouse_y = y ;
// Create backbuffer
bool needCreate = false ;
if ( ! backbuffer ) needCreate = true ;
else if ( backbuffer - > GetWidth ( ) ! = w | | backbuffer - > GetHeight ( ) ! = h ) {
needCreate = true ;
delete backbuffer ;
}
if ( needCreate ) backbuffer = new wxBitmap ( w , h ) ;
// Prepare drawing
wxMemoryDC dc ;
dc . SelectObject ( * backbuffer ) ;
dc . BeginDrawing ( ) ;
// Draw frame
2006-01-22 13:44:53 +01:00
dc . DrawBitmap ( GetFrame ( frame_n ) , 0 , 0 ) ;
2006-01-28 20:48:35 +01:00
// Draw the control points for FexTracker
DrawTrackingOverlay ( dc ) ;
2006-01-16 22:02:54 +01:00
2006-01-28 22:47:46 +01:00
dc . SetPen ( wxPen ( wxColour ( 255 , 255 , 255 ) , 1 ) ) ;
dc . SetLogicalFunction ( wxINVERT ) ;
2006-01-16 22:02:54 +01:00
// Current position info
if ( x > = 0 & & x < w & & y > = 0 & & y < h ) {
// Draw cross
dc . DrawLine ( 0 , y , w - 1 , y ) ;
dc . DrawLine ( x , 0 , x , h - 1 ) ;
// Setup text
wxFont font ( 10 , wxFONTFAMILY_DEFAULT , wxFONTSTYLE_NORMAL , wxFONTWEIGHT_BOLD , false , _T ( " Verdana " ) ) ;
dc . SetFont ( font ) ;
int tw , th ;
GetTextExtent ( text , & tw , & th , NULL , NULL , & font ) ;
// Inversion
2006-02-01 23:15:21 +01:00
bool left = x > w / 2 ;
bool bottom = y < h / 2 ;
2006-01-16 22:02:54 +01:00
// Text draw coords
int dx = x , dy = y ;
if ( left ) dx - = tw + 4 ;
else dx + = 4 ;
if ( bottom ) dy + = 3 ;
else dy - = th + 3 ;
// Draw text
dc . SetTextForeground ( wxColour ( 64 , 64 , 64 ) ) ;
dc . DrawText ( text , dx + 1 , dy - 1 ) ;
dc . DrawText ( text , dx + 1 , dy + 1 ) ;
dc . DrawText ( text , dx - 1 , dy - 1 ) ;
dc . DrawText ( text , dx - 1 , dy + 1 ) ;
dc . SetTextForeground ( wxColour ( 255 , 255 , 255 ) ) ;
dc . DrawText ( text , dx , dy ) ;
}
// End
dc . EndDrawing ( ) ;
// Blit to screen
wxClientDC dcScreen ( this ) ;
dcScreen . BeginDrawing ( ) ;
//dcScreen.DrawBitmap(backbuffer,0,0);
dcScreen . Blit ( 0 , 0 , w , h , & dc , 0 , 0 ) ;
dcScreen . EndDrawing ( ) ;
}
}
//////////////////////
// Mouse left display
void VideoDisplay : : OnMouseLeave ( wxMouseEvent & event ) {
if ( IsPlaying ) return ;
2006-01-28 22:47:46 +01:00
bTrackerEditing = 0 ;
2006-01-22 13:44:53 +01:00
RefreshVideo ( ) ;
2006-01-16 22:02:54 +01:00
}
///////////////////////////////////////
// Jumps to a frame and update display
void VideoDisplay : : JumpToFrame ( int n ) {
// Loaded?
if ( ! loaded ) return ;
// Prevent intervention during playback
if ( IsPlaying & & n ! = PlayNextFrame ) return ;
// Set frame
2006-01-22 13:44:53 +01:00
GetFrame ( n ) ;
// Display
RefreshVideo ( ) ;
UpdatePositionDisplay ( ) ;
2006-01-16 22:02:54 +01:00
// Update slider
2006-01-22 13:44:53 +01:00
ControlSlider - > SetValue ( n ) ;
2006-01-16 22:02:54 +01:00
// Update grid
2006-02-22 05:59:39 +01:00
if ( ! IsPlaying & & Options . AsBool ( _T ( " Highlight subs in frame " ) ) ) grid - > Refresh ( false ) ;
2006-01-16 22:02:54 +01:00
}
////////////////////////////
// Jumps to a specific time
void VideoDisplay : : JumpToTime ( int ms ) {
2006-02-24 17:45:10 +01:00
JumpToFrame ( VFR_Output . GetFrameAtTime ( ms ) ) ;
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 ;
2006-01-22 13:44:53 +01:00
if ( provider ) {
provider - > SetZoom ( value ) ;
UpdateSize ( ) ;
RefreshVideo ( ) ;
GetParent ( ) - > Layout ( ) ;
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 ) ;
}
2006-02-24 09:43:44 +01:00
//////////////////////////
// Calculate aspect ratio
double VideoDisplay : : GetARFromType ( int type ) {
if ( type = = 0 ) return ( double ) provider - > GetSourceWidth ( ) / ( double ) provider - > GetSourceHeight ( ) ;
if ( type = = 1 ) return 4.0 / 3.0 ;
if ( type = = 2 ) return 16.0 / 9.0 ;
2006-02-24 21:04:04 +01:00
return 1 ; //error
2006-02-24 09:43:44 +01:00
}
/////////////////////
// Sets aspect ratio
2006-01-16 22:02:54 +01:00
void VideoDisplay : : SetAspectRatio ( int value ) {
2006-01-22 13:44:53 +01:00
if ( provider ) {
2006-02-24 09:43:44 +01:00
provider - > SetDAR ( GetARFromType ( value ) ) ;
2006-02-19 03:31:25 +01:00
arType = value ;
2006-01-22 13:44:53 +01:00
UpdateSize ( ) ;
RefreshVideo ( ) ;
GetParent ( ) - > Layout ( ) ;
2006-01-16 22:02:54 +01:00
}
}
////////////////////////////
// Updates position display
void VideoDisplay : : UpdatePositionDisplay ( ) {
// Update position display control
if ( ! PositionDisplay ) {
throw _T ( " Position Display not set! " ) ;
}
// Get time
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 ) ) ;
if ( KeyFrames . Index ( frame_n ) ! = wxNOT_FOUND ) {
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 ;
// 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 ( ) ) {
2006-01-22 13:44:53 +01:00
wxTheClipboard - > SetData ( new wxBitmapDataObject ( GetFrame ( frame_n ) ) ) ;
2006-01-16 22:02:54 +01:00
wxTheClipboard - > Close ( ) ;
}
}
/////////////////
// Save snapshot
void VideoDisplay : : OnSaveSnapshot ( wxCommandEvent & event ) {
SaveSnapshot ( ) ;
}
void VideoDisplay : : SaveSnapshot ( ) {
// Get path
wxFileName file = videoName ;
wxString basepath = file . GetPath ( ) + _T ( " / " ) + file . GetName ( ) ;
wxString path ;
for ( int i = 0 ; ; i + + ) {
path = basepath + wxString : : Format ( _T ( " _%03i.png " ) , i ) ;
wxFileName tryPath ( path ) ;
if ( ! tryPath . FileExists ( ) ) break ;
}
// Save
2006-01-22 13:44:53 +01:00
GetFrame ( frame_n ) . ConvertToImage ( ) . SaveFile ( path , wxBITMAP_TYPE_PNG ) ;
2006-01-16 22:02:54 +01:00
}
/////////////////////
// Copy coordinates
void VideoDisplay : : OnCopyCoords ( wxCommandEvent & event ) {
if ( wxTheClipboard - > Open ( ) ) {
int sw , sh ;
GetScriptSize ( sw , sh ) ;
int vx = ( sw * mouse_x + w / 2 ) / w ;
int vy = ( sh * mouse_y + h / 2 ) / h ;
wxTheClipboard - > SetData ( new wxTextDataObject ( wxString : : Format ( _T ( " %i,%i " ) , vx , vy ) ) ) ;
wxTheClipboard - > Close ( ) ;
}
}
2006-01-28 20:48:35 +01:00
//////////////////
// Draw Tracking Overlay
void VideoDisplay : : DrawTrackingOverlay ( wxDC & dc )
{
2006-02-26 03:49:38 +01:00
# ifndef NO_FEX
2006-01-28 20:48:35 +01:00
if ( IsPlaying ) return ;
// Get line
AssDialogue * curline = grid - > GetDialogue ( grid - > editBox - > linen ) ;
2006-01-29 16:08:51 +01:00
if ( ! curline ) return ;
2006-01-28 20:48:35 +01:00
2006-02-24 17:45:10 +01:00
int StartFrame = VFR_Output . GetFrameAtTime ( curline - > Start . GetMS ( ) , true ) ;
int EndFrame = VFR_Output . GetFrameAtTime ( curline - > End . GetMS ( ) , false ) ;
2006-01-28 20:48:35 +01:00
if ( frame_n < StartFrame | | frame_n > EndFrame ) return ;
int localframe = frame_n - StartFrame ;
2006-01-29 16:08:51 +01:00
if ( curline - > Tracker )
{
if ( curline - > Tracker - > GetFrame ( ) < = localframe ) return ;
dc . SetLogicalFunction ( wxCOPY ) ;
for ( int i = 0 ; i < curline - > Tracker - > GetCount ( ) ; i + + )
{
FexTrackingFeature * f = ( * curline - > Tracker ) [ i ] ;
if ( f - > StartTime > localframe ) continue ;
int llf = localframe - f - > StartTime ;
if ( f - > Pos . size ( ) < = llf ) continue ;
vec2 pt = f - > Pos [ llf ] ;
pt . x * = provider - > GetZoom ( ) ;
pt . y * = provider - > GetZoom ( ) ;
pt . x = int ( pt . x ) ;
pt . y = int ( pt . y ) ;
dc . SetPen ( wxPen ( wxColour ( 255 * ( 1 - f - > Influence ) , 255 * f - > Influence , 0 ) , 1 ) ) ;
dc . DrawLine ( pt . x - 2 , pt . y , pt . x , pt . y ) ;
dc . DrawLine ( pt . x , pt . y - 2 , pt . x , pt . y ) ;
dc . DrawLine ( pt . x + 1 , pt . y , pt . x + 3 , pt . y ) ;
dc . DrawLine ( pt . x , pt . y + 1 , pt . x , pt . y + 3 ) ;
}
}
2006-02-24 21:04:04 +01:00
if ( curline - > Movement )
2006-01-28 20:48:35 +01:00
{
2006-01-29 16:08:51 +01:00
if ( curline - > Movement - > Frames . size ( ) < = localframe ) return ;
dc . SetPen ( wxPen ( wxColour ( 255 , 0 , 0 ) , 2 ) ) ;
FexMovementFrame f = curline - > Movement - > Frames . lVal [ localframe ] ;
f . Pos . x * = provider - > GetZoom ( ) ;
f . Pos . y * = provider - > GetZoom ( ) ;
f . Scale . x * = 30 * provider - > GetZoom ( ) ;
f . Scale . y * = 30 * provider - > GetZoom ( ) ;
2006-01-29 21:59:58 +01:00
FexMovementFrame f3 = f ;
dc . SetPen ( wxPen ( wxColour ( 0 , 0 , 255 ) , 1 ) ) ;
int nBack = 8 ;
while ( - - localframe > 0 & & nBack - - > 0 )
{
FexMovementFrame f2 = curline - > Movement - > Frames . lVal [ localframe ] ;
f2 . Pos . x * = provider - > GetZoom ( ) ;
f2 . Pos . y * = provider - > GetZoom ( ) ;
dc . DrawLine ( f2 . Pos . x , f2 . Pos . y , f3 . Pos . x , f3 . Pos . y ) ;
f3 = f2 ;
}
dc . SetPen ( wxPen ( wxColour ( 255 , 0 , 0 ) , 2 ) ) ;
2006-01-29 16:08:51 +01:00
dc . DrawLine ( f . Pos . x - f . Scale . x , f . Pos . y , f . Pos . x + f . Scale . x + 1 , f . Pos . y ) ;
dc . DrawLine ( f . Pos . x , f . Pos . y - f . Scale . y , f . Pos . x , f . Pos . y + f . Scale . y + 1 ) ;
2006-01-29 21:59:58 +01:00
f3 = f ;
dc . SetPen ( wxPen ( wxColour ( 0 , 255 , 0 ) , 1 ) ) ;
int nFront = 8 ;
localframe = frame_n - StartFrame ;
while ( + + localframe < curline - > Movement - > Frames . size ( ) & & nFront - - > 0 )
{
FexMovementFrame f2 = curline - > Movement - > Frames . lVal [ localframe ] ;
f2 . Pos . x * = provider - > GetZoom ( ) ;
f2 . Pos . y * = provider - > GetZoom ( ) ;
dc . DrawLine ( f2 . Pos . x , f2 . Pos . y , f3 . Pos . x , f3 . Pos . y ) ;
f3 = f2 ;
}
2006-01-28 20:48:35 +01:00
}
2006-02-26 03:49:38 +01:00
# endif
2006-01-28 20:48:35 +01:00
}
2006-01-16 22:02:54 +01:00
//////////////////
// Refresh screen
2006-01-22 13:44:53 +01:00
void VideoDisplay : : RefreshVideo ( ) {
// Draw frame
wxClientDC dc ( this ) ;
dc . BeginDrawing ( ) ;
dc . DrawBitmap ( GetFrame ( ) , 0 , 0 ) ;
2006-01-28 20:48:35 +01:00
// Draw the control points for FexTracker
DrawTrackingOverlay ( dc ) ;
dc . EndDrawing ( ) ;
}
//////////////////
// DrawVideoWithOverlay
void VideoDisplay : : DrawText ( wxPoint Pos , wxString text ) {
// Draw frame
wxClientDC dc ( this ) ;
dc . BeginDrawing ( ) ;
dc . SetBrush ( wxBrush ( wxColour ( 128 , 128 , 128 ) , wxSOLID ) ) ;
dc . DrawRectangle ( 0 , 0 , provider - > GetWidth ( ) , provider - > GetHeight ( ) ) ;
dc . SetTextForeground ( wxColour ( 64 , 64 , 64 ) ) ;
dc . DrawText ( text , Pos . x + 1 , Pos . y - 1 ) ;
dc . DrawText ( text , Pos . x + 1 , Pos . y + 1 ) ;
dc . DrawText ( text , Pos . x - 1 , Pos . y - 1 ) ;
dc . DrawText ( text , Pos . x - 1 , Pos . y + 1 ) ;
dc . SetTextForeground ( wxColour ( 255 , 255 , 255 ) ) ;
dc . DrawText ( text , Pos . x , Pos . y ) ;
2006-01-22 13:44:53 +01:00
dc . EndDrawing ( ) ;
2006-01-16 22:02:54 +01:00
}
////////////////////////
// Requests a new frame
2006-01-22 13:44:53 +01:00
wxBitmap VideoDisplay : : GetFrame ( int n ) {
frame_n = n ;
2006-01-16 22:02:54 +01:00
2006-01-22 13:44:53 +01:00
return provider - > GetFrame ( n ) ;
RefreshVideo ( ) ;
2006-01-16 22:02:54 +01:00
}
////////////////////////////
// Get dimensions of script
void VideoDisplay : : GetScriptSize ( int & sw , int & sh ) {
// Height
wxString temp = grid - > ass - > GetScriptInfo ( _T ( " PlayResY " ) ) ;
2006-02-20 22:32:58 +01:00
if ( temp . IsEmpty ( ) | | ! temp . IsNumber ( ) ) {
2006-01-16 22:02:54 +01:00
//sh = orig_h;
sh = 384 ;
}
else {
long templ ;
temp . ToLong ( & templ ) ;
sh = templ ;
}
// Width
temp = grid - > ass - > GetScriptInfo ( _T ( " PlayResX " ) ) ;
2006-02-20 22:32:58 +01:00
if ( temp . IsEmpty ( ) | | ! temp . IsNumber ( ) ) {
2006-01-16 22:02:54 +01:00
sw = 288 ;
}
else {
long templ ;
temp . ToLong ( & templ ) ;
sw = templ ;
}
}
////////
// Play
void VideoDisplay : : Play ( ) {
// Stop if already playing
if ( IsPlaying ) {
Stop ( ) ;
return ;
}
// Set variables
IsPlaying = true ;
StartTime = clock ( ) ;
PlayTime = StartTime ;
StartFrame = frame_n ;
EndFrame = - 1 ;
// Start playing audio
audio - > Play ( VFR_Output . GetTimeAtFrame ( StartFrame ) , - 1 ) ;
// Start timer
Playback . SetOwner ( this , VIDEO_PLAY_TIMER ) ;
Playback . Start ( 1 ) ;
}
/////////////
// Play line
void VideoDisplay : : PlayLine ( ) {
// Get line
AssDialogue * curline = grid - > GetDialogue ( grid - > editBox - > linen ) ;
if ( ! curline ) return ;
// Set variables
IsPlaying = true ;
2006-02-24 17:45:10 +01:00
StartFrame = VFR_Output . GetFrameAtTime ( curline - > Start . GetMS ( ) , true ) ;
EndFrame = VFR_Output . GetFrameAtTime ( curline - > End . GetMS ( ) , false ) ;
2006-01-16 22:02:54 +01:00
// Jump to start
PlayNextFrame = StartFrame ;
JumpToFrame ( StartFrame ) ;
// Set other variables
StartTime = clock ( ) ;
PlayTime = StartTime ;
// Start playing audio
audio - > Play ( curline - > Start . GetMS ( ) , curline - > End . GetMS ( ) ) ;
// Start timer
Playback . SetOwner ( this , VIDEO_PLAY_TIMER ) ;
Playback . Start ( 1 ) ;
}
////////
// Stop
void VideoDisplay : : Stop ( ) {
Playback . Stop ( ) ;
audio - > Stop ( ) ;
IsPlaying = false ;
}
//////////////
// Play timer
void VideoDisplay : : OnPlayTimer ( wxTimerEvent & event ) {
// Get time difference
clock_t cur = clock ( ) ;
int dif = ( clock ( ) - StartTime ) * 1000 / CLOCKS_PER_SEC ;
if ( ! dif ) return ;
PlayTime = cur ;
// Find next frame
int startMs = VFR_Output . GetTimeAtFrame ( StartFrame ) ;
int nextFrame = frame_n ;
for ( int i = 0 ; i < 10 ; i + + ) {
if ( nextFrame > = length ) break ;
if ( dif < VFR_Output . GetTimeAtFrame ( nextFrame ) - startMs ) {
break ;
}
nextFrame + + ;
}
// Same frame
if ( nextFrame = = frame_n ) return ;
// End
if ( nextFrame > = length | | ( EndFrame ! = - 1 & & nextFrame > EndFrame ) ) {
Stop ( ) ;
return ;
}
// Jump to next frame
PlayNextFrame = nextFrame ;
JumpToFrame ( nextFrame ) ;
2006-02-20 23:24:25 +01:00
// Sync audio
2006-02-25 08:14:39 +01:00
if ( nextFrame % 10 = = 0 ) {
2006-02-20 23:24:25 +01:00
__int64 audPos = audio - > GetSampleAtMS ( VFR_Output . GetTimeAtFrame ( nextFrame ) ) ;
2006-02-25 08:41:18 +01:00
__int64 curPos = audio - > player - > GetCurrentPosition ( ) ;
if ( abs ( int ( audPos - curPos ) ) > audio - > provider - > GetSampleRate ( ) / 10 ) audio - > player - > SetCurrentPosition ( audPos ) ;
2006-02-20 23:24:25 +01:00
}
2006-01-16 22:02:54 +01:00
}
2006-02-22 07:49:20 +01:00
//////////////////////////////
// Get name of temp work file
wxString VideoDisplay : : GetTempWorkFile ( ) {
if ( tempfile . IsEmpty ( ) ) {
tempfile = wxFileName : : CreateTempFileName ( _T ( " aegisub " ) ) ;
2006-03-31 11:44:48 +02:00
wxRemoveFile ( tempfile ) ;
2006-02-22 07:49:20 +01:00
tempfile + = _T ( " .ass " ) ;
}
return tempfile ;
}