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
//
///////////
// Headers
# include <wx/tglbtn.h>
2006-08-27 21:54:51 +02:00
# include <math.h>
# include <vector>
2006-01-16 22:02:54 +01:00
# include "audio_display.h"
2006-07-04 08:13:54 +02:00
# include "audio_provider_stream.h"
2006-01-16 22:02:54 +01:00
# include "main.h"
# include "ass_dialogue.h"
# include "subs_grid.h"
# include "ass_file.h"
# include "subs_edit_box.h"
# include "options.h"
# include "audio_karaoke.h"
# include "audio_box.h"
# include "fft.h"
2007-01-21 18:01:22 +01:00
# include "video_context.h"
2006-01-16 22:02:54 +01:00
# include "vfr.h"
# include "colorspace.h"
# include "hotkeys.h"
# include "utils.h"
2007-01-08 04:05:26 +01:00
# include "timeedit_ctrl.h"
2006-01-16 22:02:54 +01:00
///////////////
// Constructor
2007-01-21 18:01:22 +01:00
AudioDisplay : : AudioDisplay ( wxWindow * parent )
2006-01-16 22:02:54 +01:00
: wxWindow ( parent , - 1 , wxDefaultPosition , wxSize ( 200 , Options . AsInt ( _T ( " Audio Display Height " ) ) ) , wxSUNKEN_BORDER | wxWANTS_CHARS , _T ( " Audio Display " ) )
{
// Set variables
origImage = NULL ;
spectrumDisplay = NULL ;
2007-01-07 05:44:11 +01:00
spectrumDisplaySelected = NULL ;
spectrumRenderer = NULL ;
2006-01-16 22:02:54 +01:00
ScrollBar = NULL ;
dialogue = NULL ;
karaoke = NULL ;
peak = NULL ;
min = NULL ;
hasSel = false ;
diagUpdated = false ;
NeedCommit = false ;
loaded = false ;
2006-07-01 08:32:11 +02:00
temporary = false ;
2006-01-16 22:02:54 +01:00
blockUpdate = false ;
dontReadTimes = false ;
2006-02-21 22:33:15 +01:00
holding = false ;
2006-03-07 01:12:50 +01:00
draggingScale = false ;
2006-07-04 08:13:54 +02:00
scrubbing = false ;
2006-01-16 22:02:54 +01:00
Position = 0 ;
PositionSample = 0 ;
oldCurPos = 0 ;
scale = 1.0f ;
provider = NULL ;
2006-02-25 08:41:18 +01:00
player = NULL ;
2006-01-16 22:02:54 +01:00
hold = 0 ;
hasFocus = ( wxWindow : : FindFocus ( ) = = this ) ;
// Init
UpdateTimer . SetOwner ( this , Audio_Update_Timer ) ;
2006-03-06 01:45:24 +01:00
GetClientSize ( & w , & h ) ;
2007-01-06 07:14:35 +01:00
h - = Options . AsBool ( _T ( " Audio Draw Timeline " ) ) ? 20 : 0 ;
2006-01-16 22:02:54 +01:00
SetSamplesPercent ( 50 , false ) ;
// Set cursor
//wxCursor cursor(wxCURSOR_BLANK);
//SetCursor(cursor);
//wxLog::SetActiveTarget(new wxLogWindow(NULL,_T("Log"),true,false));
}
//////////////
// Destructor
AudioDisplay : : ~ AudioDisplay ( ) {
2006-02-25 08:41:18 +01:00
if ( player ) player - > CloseStream ( ) ;
delete provider ;
delete player ;
delete origImage ;
2007-01-07 05:44:11 +01:00
delete spectrumRenderer ;
2006-02-25 08:41:18 +01:00
delete spectrumDisplay ;
2007-01-07 05:44:11 +01:00
delete spectrumDisplaySelected ;
2006-02-25 08:41:18 +01:00
delete peak ;
delete min ;
2007-01-21 07:30:19 +01:00
provider = NULL ;
player = NULL ;
origImage = NULL ;
spectrumRenderer = NULL ;
spectrumDisplay = NULL ;
spectrumDisplaySelected = NULL ;
peak = NULL ;
min = NULL ;
2006-01-16 22:02:54 +01:00
}
/////////
// Reset
void AudioDisplay : : Reset ( ) {
hasSel = false ;
diagUpdated = false ;
NeedCommit = false ;
karaoke - > enabled = false ;
karaoke - > syllables . clear ( ) ;
box - > karaokeMode = false ;
box - > KaraokeButton - > SetValue ( false ) ;
dialogue = NULL ;
}
////////////////
// Update image
void AudioDisplay : : UpdateImage ( bool weak ) {
2006-07-04 23:59:30 +02:00
// Loaded?
if ( ! loaded | | ! provider ) return ;
2006-01-16 22:02:54 +01:00
// Prepare bitmap
2007-01-06 07:14:35 +01:00
int timelineHeight = Options . AsBool ( _T ( " Audio Draw Timeline " ) ) ? 20 : 0 ;
int displayH = h + timelineHeight ;
2006-01-16 22:02:54 +01:00
if ( origImage ) {
2006-03-06 01:45:24 +01:00
if ( origImage - > GetWidth ( ) ! = w | | origImage - > GetHeight ( ) ! = displayH ) {
2006-01-16 22:02:54 +01:00
delete origImage ;
origImage = NULL ;
}
}
2007-04-07 04:39:18 +02:00
// Options
2006-01-16 22:02:54 +01:00
bool draw_boundary_lines = Options . AsBool ( _T ( " Audio Draw Secondary Lines " ) ) ;
bool draw_selection_background = Options . AsBool ( _T ( " Audio Draw Selection Background " ) ) ;
2007-04-07 04:39:18 +02:00
bool drawKeyframes = Options . AsBool ( _T ( " Audio Draw Keyframes " ) ) ;
2006-01-16 22:02:54 +01:00
// Invalid dimensions
2006-03-06 01:45:24 +01:00
if ( w = = 0 | | displayH = = 0 ) return ;
2006-01-16 22:02:54 +01:00
// New bitmap
2006-03-06 01:45:24 +01:00
if ( ! origImage ) origImage = new wxBitmap ( w , displayH , - 1 ) ;
2006-01-16 22:02:54 +01:00
// Is spectrum?
bool spectrum = false ;
if ( provider & & Options . AsBool ( _T ( " Audio Spectrum " ) ) ) {
spectrum = true ;
}
// Update samples
UpdateSamples ( ) ;
// Draw image to be displayed
wxMemoryDC dc ;
dc . SelectObject ( * origImage ) ;
// Black background
dc . SetPen ( * wxTRANSPARENT_PEN ) ;
dc . SetBrush ( wxBrush ( Options . AsColour ( _T ( " Audio Background " ) ) ) ) ;
dc . DrawRectangle ( 0 , 0 , w , h ) ;
// Selection position
hasSel = false ;
hasKaraoke = karaoke - > enabled ;
selStart = 0 ;
selEnd = 0 ;
lineStart = 0 ;
lineEnd = 0 ;
selStartCap = 0 ;
selEndCap = 0 ;
2007-01-06 21:11:38 +01:00
__int64 drawSelStart = 0 ;
__int64 drawSelEnd = 0 ;
2006-01-16 22:02:54 +01:00
if ( dialogue ) {
GetDialoguePos ( lineStart , lineEnd , false ) ;
hasSel = true ;
if ( hasKaraoke ) {
GetKaraokePos ( selStartCap , selEndCap , true ) ;
2007-01-06 21:11:38 +01:00
GetKaraokePos ( drawSelStart , drawSelEnd , false ) ;
selStart = lineStart ;
selEnd = lineEnd ;
2006-01-16 22:02:54 +01:00
}
else {
GetDialoguePos ( selStartCap , selEndCap , true ) ;
selStart = lineStart ;
selEnd = lineEnd ;
2007-01-06 21:11:38 +01:00
drawSelStart = lineStart ;
drawSelEnd = lineEnd ;
2006-01-16 22:02:54 +01:00
}
}
// Draw selection bg
2007-01-06 21:11:38 +01:00
if ( hasSel & & drawSelStart < drawSelEnd & & draw_selection_background ) {
2006-01-16 22:02:54 +01:00
if ( NeedCommit & & ! karaoke - > enabled ) dc . SetBrush ( wxBrush ( Options . AsColour ( _T ( " Audio Selection Background Modified " ) ) ) ) ;
else dc . SetBrush ( wxBrush ( Options . AsColour ( _T ( " Audio Selection Background " ) ) ) ) ;
2007-01-06 21:11:38 +01:00
dc . DrawRectangle ( drawSelStart , 0 , drawSelEnd - drawSelStart , h ) ;
2006-01-16 22:02:54 +01:00
}
// Draw spectrum
if ( spectrum ) {
DrawSpectrum ( dc , weak ) ;
}
2007-04-07 04:39:18 +02:00
// Waveform
else if ( provider ) {
DrawWaveform ( dc , weak ) ;
}
// Nothing
else {
dc . DrawLine ( 0 , h / 2 , w , h / 2 ) ;
}
2006-01-16 22:02:54 +01:00
// Draw seconds boundaries
if ( draw_boundary_lines ) {
__int64 start = Position * samples ;
2006-02-02 19:17:54 +01:00
int rate = provider - > GetSampleRate ( ) ;
2006-01-16 22:02:54 +01:00
int pixBounds = rate / samples ;
dc . SetPen ( wxPen ( Options . AsColour ( _T ( " Audio Seconds Boundaries " ) ) , 1 , wxDOT ) ) ;
if ( pixBounds > = 8 ) {
for ( int x = 0 ; x < w ; x + + ) {
if ( ( ( x * samples ) + start ) % rate < samples ) {
dc . DrawLine ( x , 0 , x , h ) ;
}
}
}
}
// Draw keyframes
2007-04-07 04:39:18 +02:00
if ( drawKeyframes & & VideoContext : : Get ( ) - > KeyFramesLoaded ( ) ) {
DrawKeyframes ( dc ) ;
2006-01-16 22:02:54 +01:00
}
// Draw previous line
int shadeType = Options . AsInt ( _T ( " Audio Inactive Lines Display Mode " ) ) ;
if ( shadeType = = 1 | | shadeType = = 2 ) {
dc . SetBrush ( wxBrush ( Options . AsColour ( _T ( " Audio Line boundary inactive line " ) ) ) ) ;
int selWidth = Options . AsInt ( _T ( " Audio Line boundaries Thickness " ) ) ;
AssDialogue * shade ;
int shadeX1 , shadeX2 ;
int shadeFrom , shadeTo ;
// Only previous
if ( shadeType = = 1 ) {
shadeFrom = this - > line_n - 1 ;
shadeTo = shadeFrom + 1 ;
}
// All
else {
shadeFrom = 0 ;
shadeTo = grid - > GetRows ( ) ;
}
for ( int j = shadeFrom ; j < shadeTo ; j + + ) {
if ( j = = line_n ) continue ;
shade = grid - > GetDialogue ( j ) ;
if ( shade ) {
// Get coordinates
shadeX1 = GetXAtMS ( shade - > Start . GetMS ( ) ) ;
shadeX2 = GetXAtMS ( shade - > End . GetMS ( ) ) ;
if ( shadeX2 < 0 | | shadeX1 > w ) continue ;
// Draw over waveform
if ( ! spectrum ) {
int x1 = MAX ( 0 , shadeX1 ) ;
int x2 = MIN ( w , shadeX2 ) ;
dc . SetPen ( wxPen ( Options . AsColour ( _T ( " Audio Waveform Inactive " ) ) ) ) ;
for ( __int64 i = x1 ; i < x2 ; i + + ) {
dc . DrawLine ( i , peak [ i ] , i , min [ i ] - 1 ) ;
}
}
// Draw boundaries
dc . SetPen ( wxPen ( Options . AsColour ( _T ( " Audio Line boundary inactive line " ) ) ) ) ;
dc . DrawRectangle ( shadeX1 - selWidth / 2 + 1 , 0 , selWidth , h ) ;
dc . DrawRectangle ( shadeX2 - selWidth / 2 + 1 , 0 , selWidth , h ) ;
}
}
}
if ( hasSel ) {
// Draw boundaries
2007-01-06 05:19:00 +01:00
if ( true ) {
// Draw start boundary
int selWidth = Options . AsInt ( _T ( " Audio Line boundaries Thickness " ) ) ;
dc . SetPen ( wxPen ( Options . AsColour ( _T ( " Audio Line boundary start " ) ) ) ) ;
dc . SetBrush ( wxBrush ( Options . AsColour ( _T ( " Audio Line boundary start " ) ) ) ) ;
dc . DrawRectangle ( lineStart - selWidth / 2 + 1 , 0 , selWidth , h ) ;
wxPoint points1 [ 3 ] = { wxPoint ( lineStart , 0 ) , wxPoint ( lineStart + 10 , 0 ) , wxPoint ( lineStart , 10 ) } ;
wxPoint points2 [ 3 ] = { wxPoint ( lineStart , h - 1 ) , wxPoint ( lineStart + 10 , h - 1 ) , wxPoint ( lineStart , h - 11 ) } ;
dc . DrawPolygon ( 3 , points1 ) ;
dc . DrawPolygon ( 3 , points2 ) ;
// Draw end boundary
dc . SetPen ( wxPen ( Options . AsColour ( _T ( " Audio Line boundary end " ) ) ) ) ;
dc . SetBrush ( wxBrush ( Options . AsColour ( _T ( " Audio Line boundary end " ) ) ) ) ;
dc . DrawRectangle ( lineEnd - selWidth / 2 + 1 , 0 , selWidth , h ) ;
wxPoint points3 [ 3 ] = { wxPoint ( lineEnd , 0 ) , wxPoint ( lineEnd - 10 , 0 ) , wxPoint ( lineEnd , 10 ) } ;
wxPoint points4 [ 3 ] = { wxPoint ( lineEnd , h - 1 ) , wxPoint ( lineEnd - 10 , h - 1 ) , wxPoint ( lineEnd , h - 11 ) } ;
dc . DrawPolygon ( 3 , points3 ) ;
dc . DrawPolygon ( 3 , points4 ) ;
}
2006-01-16 22:02:54 +01:00
// Draw karaoke
if ( hasKaraoke ) {
2006-02-20 08:12:01 +01:00
try {
// Prepare
wxPen curPen ( Options . AsColour ( _T ( " Audio Syllable boundaries " ) ) , 1 , wxDOT ) ;
dc . SetPen ( curPen ) ;
wxFont curFont ( 9 , wxFONTFAMILY_DEFAULT , wxFONTSTYLE_NORMAL , wxFONTWEIGHT_BOLD , false , _T ( " Verdana " ) , wxFONTENCODING_SYSTEM ) ;
dc . SetFont ( curFont ) ;
if ( ! spectrum ) dc . SetTextForeground ( Options . AsColour ( _T ( " Audio Syllable text " ) ) ) ;
else dc . SetTextForeground ( wxColour ( 255 , 255 , 255 ) ) ;
size_t karn = karaoke - > syllables . size ( ) ;
__int64 pos1 , pos2 ;
int len , curpos ;
wxCoord tw = 0 , th = 0 ;
KaraokeSyllable * curSyl ;
wxString temptext ;
// Draw syllables
for ( size_t i = 0 ; i < karn ; i + + ) {
2006-01-16 22:02:54 +01:00
curSyl = & karaoke - > syllables . at ( i ) ;
len = curSyl - > length * 10 ;
curpos = curSyl - > position * 10 ;
if ( len ! = - 1 ) {
pos1 = GetXAtMS ( curStartMS + curpos ) ;
pos2 = GetXAtMS ( curStartMS + len + curpos ) ;
dc . DrawLine ( pos2 , 0 , pos2 , h ) ;
temptext = curSyl - > contents ;
temptext . Trim ( true ) ;
temptext . Trim ( false ) ;
GetTextExtent ( temptext , & tw , & th , NULL , NULL , & curFont ) ;
2007-01-07 07:36:10 +01:00
dc . DrawText ( temptext , ( pos1 + pos2 - tw ) / 2 , 4 ) ;
2006-01-16 22:02:54 +01:00
}
}
2006-02-20 08:12:01 +01:00
}
catch ( . . . ) {
2007-01-07 05:44:11 +01:00
// FIXME?
2006-01-16 22:02:54 +01:00
}
}
}
// Modified text
if ( NeedCommit ) {
2007-01-07 05:44:11 +01:00
dc . SetFont ( wxFont ( 9 , wxDEFAULT , wxFONTSTYLE_NORMAL , wxFONTWEIGHT_BOLD , false , _T ( " Verdana " ) ) ) ; // FIXME: hardcoded font name
2006-01-16 22:02:54 +01:00
dc . SetTextForeground ( wxColour ( 255 , 0 , 0 ) ) ;
if ( selStart < = selEnd ) {
dc . DrawText ( _T ( " Modified " ) , 4 , 4 ) ;
}
else {
dc . DrawText ( _T ( " Negative time " ) , 4 , 4 ) ;
}
}
2007-04-07 04:39:18 +02:00
// Draw timescale
if ( timelineHeight ) {
DrawTimescale ( dc ) ;
}
2006-01-16 22:02:54 +01:00
// Draw selection border
if ( hasFocus ) {
dc . SetPen ( * wxGREEN_PEN ) ;
dc . SetBrush ( * wxTRANSPARENT_BRUSH ) ;
dc . DrawRectangle ( 0 , 0 , w , h ) ;
}
2007-04-07 04:39:18 +02:00
// Done
Refresh ( false ) ;
}
//////////////////
// Draw keyframes
void AudioDisplay : : DrawKeyframes ( wxDC & dc ) {
wxArrayInt KeyFrames = VideoContext : : Get ( ) - > GetKeyFrames ( ) ;
int nKeys = ( int ) KeyFrames . Count ( ) ;
dc . SetPen ( wxPen ( wxColour ( 255 , 0 , 255 ) , 1 ) ) ;
// Get min and max frames to care about
int minFrame = VFR_Output . GetFrameAtTime ( GetMSAtX ( 0 ) , true ) ;
int maxFrame = VFR_Output . GetFrameAtTime ( GetMSAtX ( w ) , true ) ;
// Scan list
for ( int i = 0 ; i < nKeys ; i + + ) {
int cur = KeyFrames [ i ] ;
if ( cur > = minFrame & & cur < = maxFrame ) {
int x = GetXAtMS ( VFR_Output . GetTimeAtFrame ( cur , true ) ) ;
dc . DrawLine ( x , 0 , x , h ) ;
}
else if ( cur > maxFrame ) break ;
}
}
2006-03-06 01:45:24 +01:00
2007-04-07 04:39:18 +02:00
//////////////////
// Draw timescale
void AudioDisplay : : DrawTimescale ( wxDC & dc ) {
// Set size
int timelineHeight = Options . AsBool ( _T ( " Audio Draw Timeline " ) ) ? 20 : 0 ;
// Set colours
dc . SetBrush ( wxSystemSettings : : GetColour ( wxSYS_COLOUR_BTNFACE ) ) ;
dc . SetPen ( * wxTRANSPARENT_PEN ) ;
dc . DrawRectangle ( 0 , h , w , timelineHeight ) ;
dc . SetPen ( wxSystemSettings : : GetColour ( wxSYS_COLOUR_3DLIGHT ) ) ;
dc . DrawLine ( 0 , h , w , h ) ;
dc . SetPen ( wxSystemSettings : : GetColour ( wxSYS_COLOUR_3DHIGHLIGHT ) ) ;
dc . DrawLine ( 0 , h + 1 , w , h + 1 ) ;
dc . SetPen ( wxSystemSettings : : GetColour ( wxSYS_COLOUR_BTNTEXT ) ) ;
dc . SetTextForeground ( wxSystemSettings : : GetColour ( wxSYS_COLOUR_BTNTEXT ) ) ;
wxFont scaleFont ;
scaleFont . SetFaceName ( _T ( " Tahoma " ) ) ; // FIXME: hardcoded font name
scaleFont . SetPointSize ( 8 ) ;
dc . SetFont ( scaleFont ) ;
// Timescale ticks
__int64 start = Position * samples ;
int rate = provider - > GetSampleRate ( ) ;
for ( int i = 1 ; i < 32 ; i * = 2 ) {
int pixBounds = rate / ( samples * 4 / i ) ;
if ( pixBounds > = 8 ) {
for ( int x = 0 ; x < w ; x + + ) {
__int64 pos = ( x * samples ) + start ;
// Second boundary
if ( pos % rate < samples ) {
dc . DrawLine ( x , h + 2 , x , h + 8 ) ;
// Draw text
wxCoord textW , textH ;
int hr = 0 ;
int m = 0 ;
int s = pos / rate ;
while ( s > = 3600 ) {
s - = 3600 ;
hr + + ;
2007-01-06 07:14:35 +01:00
}
2007-04-07 04:39:18 +02:00
while ( s > = 60 ) {
s - = 60 ;
m + + ;
}
wxString text ;
if ( hr ) text = wxString : : Format ( _T ( " %i:%02i:%02i " ) , hr , m , s ) ;
else if ( m ) text = wxString : : Format ( _T ( " %i:%02i " ) , m , s ) ;
else text = wxString : : Format ( _T ( " %i " ) , s ) ;
dc . GetTextExtent ( text , & textW , & textH , NULL , NULL , & scaleFont ) ;
dc . DrawText ( text , MAX ( 0 , x - textW / 2 ) + 1 , h + 8 ) ;
}
// Other
else if ( pos % ( rate / 4 * i ) < samples ) {
dc . DrawLine ( x , h + 2 , x , h + 5 ) ;
2006-03-06 01:45:24 +01:00
}
}
2007-04-07 04:39:18 +02:00
break ;
2006-03-06 01:45:24 +01:00
}
}
2006-01-16 22:02:54 +01:00
}
////////////
// Waveform
void AudioDisplay : : DrawWaveform ( wxDC & dc , bool weak ) {
// Prepare Waveform
if ( ! weak | | peak = = NULL | | min = = NULL ) {
if ( peak ) delete peak ;
if ( min ) delete min ;
peak = new int [ w ] ;
min = new int [ w ] ;
}
// Get waveform
if ( ! weak ) {
provider - > GetWaveForm ( min , peak , Position * samples , w , h , samples , scale ) ;
}
// Draw pre-selection
if ( ! hasSel ) selStartCap = w ;
dc . SetPen ( wxPen ( Options . AsColour ( _T ( " Audio Waveform " ) ) ) ) ;
for ( __int64 i = 0 ; i < selStartCap ; i + + ) {
dc . DrawLine ( i , peak [ i ] , i , min [ i ] - 1 ) ;
}
if ( hasSel ) {
// Draw selection
if ( Options . AsBool ( _T ( " Audio Draw Selection Background " ) ) ) {
if ( NeedCommit & & ! karaoke - > enabled ) dc . SetPen ( wxPen ( Options . AsColour ( _T ( " Audio Waveform Modified " ) ) ) ) ;
else dc . SetPen ( wxPen ( Options . AsColour ( _T ( " Audio Waveform Selected " ) ) ) ) ;
}
for ( __int64 i = selStartCap ; i < selEndCap ; i + + ) {
dc . DrawLine ( i , peak [ i ] , i , min [ i ] - 1 ) ;
}
// Draw post-selection
dc . SetPen ( wxPen ( Options . AsColour ( _T ( " Audio Waveform " ) ) ) ) ;
for ( __int64 i = selEndCap ; i < w ; i + + ) {
dc . DrawLine ( i , peak [ i ] , i , min [ i ] - 1 ) ;
}
}
}
//////////////////////////
// Draw spectrum analyzer
void AudioDisplay : : DrawSpectrum ( wxDC & finaldc , bool weak ) {
if ( ! weak | | ! spectrumDisplay | | spectrumDisplay - > GetWidth ( ) ! = w | | spectrumDisplay - > GetHeight ( ) ! = h ) {
2007-01-06 22:56:25 +01:00
if ( spectrumDisplay ) {
delete spectrumDisplay ;
2007-01-07 05:44:11 +01:00
delete spectrumDisplaySelected ;
2007-01-06 22:56:25 +01:00
spectrumDisplay = 0 ;
2007-01-07 05:44:11 +01:00
spectrumDisplaySelected = 0 ;
2007-01-06 22:56:25 +01:00
}
2006-01-16 22:02:54 +01:00
weak = false ;
}
if ( ! weak ) {
2007-01-07 05:44:11 +01:00
unsigned char * img = ( unsigned char * ) malloc ( h * w * 3 ) ; // wxImage requires using malloc
2006-01-16 22:02:54 +01:00
2007-01-07 05:44:11 +01:00
if ( ! spectrumRenderer )
spectrumRenderer = new AudioSpectrum ( provider , 1 < < Options . AsInt ( _T ( " Audio Spectrum Window " ) ) ) ;
2006-01-16 22:02:54 +01:00
2007-01-07 05:44:11 +01:00
spectrumRenderer - > SetScaling ( scale ) ;
// Use a slightly slower, but simple way
// Always draw the spectrum for the entire width
// Hack: without those divs by 2 the display is horizontally compressed
spectrumRenderer - > RenderRange ( Position * samples , ( Position + w ) * samples , false , img , 0 , w , w , h ) ;
2006-08-27 21:54:51 +02:00
2007-01-07 05:44:11 +01:00
// The spectrum bitmap will have been deleted above already, so just make a new one
wxImage imgobj ( w , h , img , false ) ;
spectrumDisplay = new wxBitmap ( imgobj ) ;
}
2006-01-16 22:02:54 +01:00
2007-01-07 05:52:33 +01:00
if ( hasSel & & selStartCap < selEndCap & & ! spectrumDisplaySelected ) {
// There is a visible selection and we don't have a rendered one
// This should be done regardless whether we're "weak" or not
// Assume a few things were already set up when things were first rendered though
unsigned char * img = ( unsigned char * ) malloc ( h * w * 3 ) ;
spectrumRenderer - > RenderRange ( Position * samples , ( Position + w ) * samples , true , img , 0 , w , w , h ) ;
wxImage imgobj ( w , h , img , false ) ;
spectrumDisplaySelected = new wxBitmap ( imgobj ) ;
2006-01-16 22:02:54 +01:00
}
// Draw
wxMemoryDC dc ;
dc . SelectObject ( * spectrumDisplay ) ;
finaldc . Blit ( 0 , 0 , w , h , & dc , 0 , 0 ) ;
2007-01-07 05:44:11 +01:00
if ( hasSel & & spectrumDisplaySelected & & selStartCap < selEndCap ) {
dc . SelectObject ( * spectrumDisplaySelected ) ;
2007-01-07 07:36:10 +01:00
finaldc . Blit ( selStartCap , 0 , selEndCap - selStartCap , h , & dc , selStartCap , 0 ) ;
2007-01-07 05:44:11 +01:00
}
}
2006-01-16 22:02:54 +01:00
//////////////////////////
// Get selection position
void AudioDisplay : : GetDialoguePos ( __int64 & selStart , __int64 & selEnd , bool cap ) {
selStart = GetXAtMS ( curStartMS ) ;
selEnd = GetXAtMS ( curEndMS ) ;
if ( cap ) {
if ( selStart < 0 ) selStart = 0 ;
if ( selEnd < 0 ) selEnd = 0 ;
if ( selStart > = w ) selStart = w - 1 ;
if ( selEnd > = w ) selEnd = w - 1 ;
}
}
////////////////////////
// Get karaoke position
void AudioDisplay : : GetKaraokePos ( __int64 & karStart , __int64 & karEnd , bool cap ) {
2006-02-20 08:12:01 +01:00
try {
// Wrap around
2006-08-28 00:29:14 +02:00
int nsyls = ( int ) karaoke - > syllables . size ( ) ;
2006-02-20 08:12:01 +01:00
if ( karaoke - > curSyllable = = - 1 ) {
karaoke - > SetSyllable ( nsyls - 1 ) ;
}
if ( karaoke - > curSyllable > = nsyls ) karaoke - > curSyllable = nsyls - 1 ;
2006-01-16 22:02:54 +01:00
2006-02-20 08:12:01 +01:00
// Get positions
int pos = karaoke - > syllables . at ( karaoke - > curSyllable ) . position ;
int len = karaoke - > syllables . at ( karaoke - > curSyllable ) . length ;
karStart = GetXAtMS ( curStartMS + pos * 10 ) ;
karEnd = GetXAtMS ( curStartMS + pos * 10 + len * 10 ) ;
// Cap
if ( cap ) {
if ( karStart < 0 ) karStart = 0 ;
if ( karEnd < 0 ) karEnd = 0 ;
if ( karStart > = w ) karStart = w - 1 ;
if ( karEnd > = w ) karEnd = w - 1 ;
}
}
catch ( . . . ) {
2006-01-16 22:02:54 +01:00
}
}
//////////
// Update
void AudioDisplay : : Update ( ) {
if ( blockUpdate ) return ;
if ( loaded ) {
2006-02-02 19:24:58 +01:00
if ( Options . AsBool ( _T ( " Audio Autoscroll " ) ) )
MakeDialogueVisible ( ) ;
else
2006-01-16 22:02:54 +01:00
UpdateImage ( true ) ;
}
}
2007-01-06 07:14:35 +01:00
//////////////////////
// Recreate the image
void AudioDisplay : : RecreateImage ( ) {
GetClientSize ( & w , & h ) ;
h - = Options . AsBool ( _T ( " Audio Draw Timeline " ) ) ? 20 : 0 ;
delete origImage ;
origImage = NULL ;
UpdateImage ( false ) ;
}
2006-01-16 22:02:54 +01:00
/////////////////////////
// Make dialogue visible
void AudioDisplay : : MakeDialogueVisible ( bool force ) {
// Variables
int temp1 = 0 , temp2 = 0 ;
GetTimesSelection ( temp1 , temp2 ) ;
int startPos = GetSampleAtMS ( temp1 ) ;
int endPos = GetSampleAtMS ( temp2 ) ;
int startX = GetXAtMS ( temp1 ) ;
int endX = GetXAtMS ( temp2 ) ;
if ( force | | startX < 50 | | endX > w - 50 ) {
UpdatePosition ( ( startPos + endPos - w * samples ) / 2 , true ) ;
}
// Update
UpdateImage ( ) ;
}
////////////////
// Set position
void AudioDisplay : : SetPosition ( int pos ) {
Position = pos ;
PositionSample = pos * samples ;
UpdateImage ( ) ;
}
///////////////////
// Update position
void AudioDisplay : : UpdatePosition ( int pos , bool IsSample ) {
// Safeguards
if ( IsSample ) pos / = samples ;
int len = provider - > GetNumSamples ( ) / samples ;
if ( pos < 0 ) pos = 0 ;
if ( pos > = len ) pos = len - 1 ;
// Set
Position = pos ;
PositionSample = pos * samples ;
UpdateScrollbar ( ) ;
}
/////////////////////////////
// Set samples in percentage
// Note: aka Horizontal Zoom
void AudioDisplay : : SetSamplesPercent ( int percent , bool update , float pivot ) {
// Calculate
if ( percent < 1 ) percent = 1 ;
if ( percent > 100 ) percent = 100 ;
if ( samplesPercent = = percent ) return ;
samplesPercent = percent ;
// Update
if ( update ) {
// Center scroll
int oldSamples = samples ;
2006-02-25 01:11:54 +01:00
UpdateSamples ( ) ;
2007-04-04 22:42:44 +02:00
PositionSample + = __int64 ( ( oldSamples - samples ) * w * pivot ) ;
2006-01-16 22:02:54 +01:00
if ( PositionSample < 0 ) PositionSample = 0 ;
// Update
2006-02-25 01:11:54 +01:00
UpdateSamples ( ) ;
2006-01-16 22:02:54 +01:00
UpdateScrollbar ( ) ;
UpdateImage ( ) ;
2006-02-25 01:11:54 +01:00
Refresh ( false ) ;
2006-01-16 22:02:54 +01:00
}
}
//////////////////
// Update samples
void AudioDisplay : : UpdateSamples ( ) {
// Set samples
2006-07-04 23:59:30 +02:00
if ( ! provider ) return ;
2006-02-02 19:17:54 +01:00
__int64 totalSamples = provider - > GetNumSamples ( ) ;
2006-01-16 22:02:54 +01:00
int total = totalSamples / w ;
int max = 5760000 / w ; // 2 minutes at 48 kHz maximum
if ( total > max ) total = max ;
int min = 8 ;
if ( total < min ) total = min ;
int range = total - min ;
2007-04-04 22:42:44 +02:00
samples = int ( range * pow ( samplesPercent / 100.0 , 3 ) + min ) ;
2006-01-16 22:02:54 +01:00
// Set position
int length = w * samples ;
if ( PositionSample + length > totalSamples ) {
PositionSample = totalSamples - length ;
if ( PositionSample < 0 ) PositionSample = 0 ;
Position = PositionSample / samples ;
}
}
/////////////
// Set scale
void AudioDisplay : : SetScale ( float _scale ) {
if ( scale = = _scale ) return ;
scale = _scale ;
UpdateImage ( ) ;
}
//////////////////
// Load from file
2006-04-15 00:35:39 +02:00
void AudioDisplay : : SetFile ( wxString file , VideoProvider * vprovider ) {
2006-02-25 08:41:18 +01:00
// Unload
2006-02-20 22:32:58 +01:00
if ( file . IsEmpty ( ) ) {
2006-02-25 08:41:18 +01:00
if ( player ) player - > CloseStream ( ) ;
delete provider ;
delete player ;
2007-01-07 05:44:11 +01:00
delete spectrumRenderer ;
2006-01-16 22:02:54 +01:00
provider = NULL ;
2006-02-25 08:41:18 +01:00
player = NULL ;
2007-01-07 05:44:11 +01:00
spectrumRenderer = NULL ;
2006-01-16 22:02:54 +01:00
Reset ( ) ;
2006-02-02 19:17:54 +01:00
loaded = false ;
2006-07-04 23:59:30 +02:00
temporary = false ;
2006-01-16 22:02:54 +01:00
}
2006-02-25 08:41:18 +01:00
// Load
2006-01-16 22:02:54 +01:00
else {
SetFile ( _T ( " " ) ) ;
try {
2006-02-25 08:41:18 +01:00
// Get provider
2007-01-23 05:42:08 +01:00
provider = AudioProviderFactory : : GetAudioProvider ( file ) ;
2006-01-16 22:02:54 +01:00
2006-02-25 08:41:18 +01:00
// Get player
player = AudioPlayer : : GetAudioPlayer ( ) ;
player - > SetDisplayTimer ( & UpdateTimer ) ;
player - > SetProvider ( provider ) ;
player - > OpenStream ( ) ;
2006-02-02 19:17:54 +01:00
loaded = true ;
2006-01-16 22:02:54 +01:00
// Add to recent
Options . AddToRecentList ( file , _T ( " Recent aud " ) ) ;
2006-02-02 19:17:54 +01:00
// Update
UpdateImage ( ) ;
2006-01-16 22:02:54 +01:00
}
catch ( wxString & err ) {
wxMessageBox ( err , _T ( " Error loading audio " ) , wxICON_ERROR | wxOK ) ;
}
}
2006-02-02 19:17:54 +01:00
assert ( loaded = = ( provider ! = NULL ) ) ;
2006-01-16 22:02:54 +01:00
// Set default selection
int n = grid - > editBox - > linen ;
SetDialogue ( grid , grid - > GetDialogue ( n ) , n ) ;
}
///////////////////
// Load from video
void AudioDisplay : : SetFromVideo ( ) {
2007-01-21 07:30:19 +01:00
if ( VideoContext : : Get ( ) - > IsLoaded ( ) ) {
wxString extension = VideoContext : : Get ( ) - > videoName . Right ( 4 ) ;
2006-01-16 22:02:54 +01:00
extension . LowerCase ( ) ;
2007-01-21 07:30:19 +01:00
if ( extension ! = _T ( " .d2v " ) ) SetFile ( VideoContext : : Get ( ) - > videoName , VideoContext : : Get ( ) - > GetProvider ( ) ) ;
2006-01-16 22:02:54 +01:00
}
}
////////////////////
// Update scrollbar
void AudioDisplay : : UpdateScrollbar ( ) {
2006-07-04 23:59:30 +02:00
if ( ! provider ) return ;
2006-01-16 22:02:54 +01:00
int page = w / 12 ;
int len = provider - > GetNumSamples ( ) / samples / 12 ;
Position = PositionSample / samples ;
2007-04-04 22:42:44 +02:00
ScrollBar - > SetScrollbar ( Position / 12 , page , len , int ( page * 0.7 ) , true ) ;
2006-01-16 22:02:54 +01:00
}
//////////////////////////////////////////////
// Gets the sample number at the x coordinate
__int64 AudioDisplay : : GetSampleAtX ( int x ) {
return ( x + Position ) * samples ;
}
/////////////////////////////////////////////////
// Gets the x coordinate corresponding to sample
int AudioDisplay : : GetXAtSample ( __int64 n ) {
return ( n / samples ) - Position ;
}
/////////////////
// Get MS from X
int AudioDisplay : : GetMSAtX ( __int64 x ) {
2006-02-02 19:17:54 +01:00
return ( PositionSample + ( x * samples ) ) * 1000 / provider - > GetSampleRate ( ) ;
2006-01-16 22:02:54 +01:00
}
/////////////////
// Get X from MS
int AudioDisplay : : GetXAtMS ( __int64 ms ) {
2006-02-02 19:17:54 +01:00
return ( ( ms * provider - > GetSampleRate ( ) / 1000 ) - PositionSample ) / samples ;
2006-01-16 22:02:54 +01:00
}
////////////////////
// Get MS At sample
int AudioDisplay : : GetMSAtSample ( __int64 x ) {
2006-02-02 19:17:54 +01:00
return x * 1000 / provider - > GetSampleRate ( ) ;
2006-01-16 22:02:54 +01:00
}
////////////////////
// Get Sample at MS
__int64 AudioDisplay : : GetSampleAtMS ( __int64 ms ) {
2006-02-02 19:17:54 +01:00
return ms * provider - > GetSampleRate ( ) / 1000 ;
2006-01-16 22:02:54 +01:00
}
////////
// Play
void AudioDisplay : : Play ( int start , int end ) {
2007-03-18 02:20:25 +01:00
Stop ( ) ;
2006-01-16 22:02:54 +01:00
// Check provider
2006-07-01 08:32:11 +02:00
if ( ! provider ) {
// Load temporary provider from video
2007-01-21 07:30:19 +01:00
if ( VideoContext : : Get ( ) - > IsLoaded ( ) ) {
2006-07-01 08:32:11 +02:00
try {
// Get provider
2007-01-23 05:42:08 +01:00
provider = AudioProviderFactory : : GetAudioProvider ( VideoContext : : Get ( ) - > videoName , 0 ) ;
2006-07-01 08:32:11 +02:00
// Get player
player = AudioPlayer : : GetAudioPlayer ( ) ;
player - > SetDisplayTimer ( & UpdateTimer ) ;
player - > SetProvider ( provider ) ;
player - > OpenStream ( ) ;
temporary = true ;
}
catch ( . . . ) {
return ;
}
}
if ( ! provider ) return ;
}
2006-01-16 22:02:54 +01:00
// Set defaults
__int64 num_samples = provider - > GetNumSamples ( ) ;
start = GetSampleAtMS ( start ) ;
if ( end ! = - 1 ) end = GetSampleAtMS ( end ) ;
else end = num_samples - 1 ;
// Sanity checking
if ( start < 0 ) start = 0 ;
if ( start > = num_samples ) start = num_samples - 1 ;
if ( end < 0 ) end = 0 ;
if ( end > = num_samples ) end = num_samples - 1 ;
if ( end < start ) end = start ;
// Call play
2006-02-25 08:41:18 +01:00
player - > Play ( start , end - start ) ;
2006-01-16 22:02:54 +01:00
}
////////
// Stop
void AudioDisplay : : Stop ( ) {
2007-01-21 18:01:22 +01:00
if ( VideoContext : : Get ( ) - > IsPlaying ( ) ) VideoContext : : Get ( ) - > Stop ( ) ;
2007-03-18 02:20:25 +01:00
if ( player ) player - > Stop ( ) ;
2006-01-16 22:02:54 +01:00
}
///////////////////////////
// Get samples of dialogue
void AudioDisplay : : GetTimesDialogue ( int & start , int & end ) {
if ( ! dialogue ) {
start = 0 ;
end = 0 ;
return ;
}
start = dialogue - > Start . GetMS ( ) ;
end = dialogue - > End . GetMS ( ) ;
}
////////////////////////////
// Get samples of selection
void AudioDisplay : : GetTimesSelection ( int & start , int & end ) {
2006-02-20 08:12:01 +01:00
start = 0 ;
end = 0 ;
if ( ! dialogue ) return ;
2006-01-16 22:02:54 +01:00
2006-02-20 08:12:01 +01:00
try {
if ( karaoke - > enabled ) {
int pos = karaoke - > syllables . at ( karaoke - > curSyllable ) . position ;
int len = karaoke - > syllables . at ( karaoke - > curSyllable ) . length ;
start = curStartMS + pos * 10 ;
end = curStartMS + pos * 10 + len * 10 ;
}
else {
start = curStartMS ;
end = curEndMS ;
}
2006-01-16 22:02:54 +01:00
}
2006-02-20 08:12:01 +01:00
catch ( . . . ) { }
2006-01-16 22:02:54 +01:00
}
/////////////////////////////
// Set the current selection
void AudioDisplay : : SetSelection ( int start , int end ) {
curStartMS = start ;
curEndMS = end ;
Update ( ) ;
}
////////////////
// Set dialogue
void AudioDisplay : : SetDialogue ( SubtitlesGrid * _grid , AssDialogue * diag , int n ) {
// Actual parameters
if ( _grid ) {
// Set variables
grid = _grid ;
line_n = n ;
dialogue = diag ;
// Set flags
diagUpdated = false ;
NeedCommit = false ;
// Set times
2007-04-09 20:25:58 +02:00
if ( dialogue & & ! dontReadTimes & & Options . AsBool ( _T ( " Audio grab times on select " ) ) ) {
int s = dialogue - > Start . GetMS ( ) ;
int e = dialogue - > End . GetMS ( ) ;
// Never do it for 0:00:00.00->0:00:00.00 lines
if ( s ! = 0 | | e ! = 0 ) {
curStartMS = s ;
curEndMS = e ;
}
2006-01-16 22:02:54 +01:00
}
}
// Read karaoke data
if ( dialogue & & karaoke - > enabled ) {
NeedCommit = karaoke - > LoadFromDialogue ( dialogue ) ;
// Reset karaoke pos
2006-08-28 00:29:14 +02:00
if ( karaoke - > curSyllable = = - 1 ) karaoke - > SetSyllable ( ( int ) karaoke - > syllables . size ( ) - 1 ) ;
2006-01-16 22:02:54 +01:00
else karaoke - > SetSyllable ( 0 ) ;
}
// Update
Update ( ) ;
}
//////////////////
// Commit changes
2007-01-06 00:43:24 +01:00
void AudioDisplay : : CommitChanges ( bool nextLine ) {
2006-07-04 23:59:30 +02:00
// Loaded?
if ( ! loaded ) return ;
2007-01-06 04:40:58 +01:00
// Check validity
bool wasKaraSplitting = false ;
bool validCommit = true ;
2007-01-06 00:43:24 +01:00
if ( ! box - > audioKaraoke - > splitting ) {
2007-01-06 04:40:58 +01:00
if ( ! NeedCommit | | curEndMS < curStartMS ) validCommit = false ;
2006-01-16 22:02:54 +01:00
}
// Update karaoke
int karSyl = 0 ;
if ( karaoke - > enabled ) {
2006-01-27 01:48:59 +01:00
wasKaraSplitting = box - > audioKaraoke - > splitting ;
2006-01-16 22:02:54 +01:00
karaoke - > Commit ( ) ;
karSyl = karaoke - > curSyllable ;
}
2007-01-06 04:40:58 +01:00
// Commit ok?
if ( validCommit ) {
// Reset flags
diagUpdated = false ;
NeedCommit = false ;
2006-01-16 22:02:54 +01:00
2007-01-06 04:40:58 +01:00
// Update dialogues
blockUpdate = true ;
wxArrayInt sel = grid - > GetSelection ( ) ;
int sels = ( int ) sel . Count ( ) ;
AssDialogue * curDiag ;
for ( int i = - 1 ; i < sels ; i + + ) {
if ( i = = - 1 ) curDiag = dialogue ;
else {
curDiag = grid - > GetDialogue ( sel [ i ] ) ;
if ( curDiag = = dialogue ) continue ;
}
curDiag - > Start . SetMS ( curStartMS ) ;
curDiag - > End . SetMS ( curEndMS ) ;
2007-01-10 02:36:05 +01:00
if ( ! karaoke - > enabled )
// If user was editing karaoke stuff, that should take precedence of manual changes in the editbox,
// so only updated from editbox when not in kara mode
curDiag - > Text = grid - > editBox - > TextEdit - > GetText ( ) ;
2007-01-06 04:40:58 +01:00
curDiag - > UpdateData ( ) ;
2006-02-20 23:32:20 +01:00
}
2007-01-08 04:05:26 +01:00
// Update edit box
grid - > editBox - > StartTime - > Update ( ) ;
grid - > editBox - > EndTime - > Update ( ) ;
grid - > editBox - > Duration - > Update ( ) ;
2007-01-06 04:40:58 +01:00
// Update grid
grid - > editBox - > Update ( ! karaoke - > enabled ) ;
2007-01-26 01:47:42 +01:00
grid - > ass - > FlagAsModified ( _T ( " " ) ) ;
2007-01-06 04:40:58 +01:00
grid - > CommitChanges ( ) ;
karaoke - > curSyllable = karSyl ;
blockUpdate = false ;
2006-02-20 23:32:20 +01:00
}
2007-01-06 00:43:24 +01:00
// Next line
2007-01-06 05:19:00 +01:00
if ( nextLine & & ! karaoke - > enabled & & Options . AsBool ( _T ( " Audio Next Line on Commit " ) ) & & ! wasKaraSplitting ) {
2006-12-18 21:13:23 +01:00
// Insert a line if it doesn't exist
int nrows = grid - > GetRows ( ) ;
if ( nrows = = line_n + 1 ) {
AssDialogue * def = new AssDialogue ;
def - > Start = grid - > GetDialogue ( line_n ) - > End ;
def - > End = grid - > GetDialogue ( line_n ) - > End ;
def - > End . SetMS ( def - > End . GetMS ( ) + 5000 ) ;
def - > Style = grid - > GetDialogue ( line_n ) - > Style ;
grid - > InsertLine ( def , line_n , true ) ;
}
// Go to next
2006-01-16 22:02:54 +01:00
dontReadTimes = true ;
Next ( ) ;
dontReadTimes = false ;
curStartMS = curEndMS ;
curEndMS = curStartMS + Options . AsInt ( _T ( " Timing Default Duration " ) ) ;
}
Update ( ) ;
}
////////////
// Add lead
void AudioDisplay : : AddLead ( bool in , bool out ) {
// Lead in
if ( in ) {
curStartMS - = Options . AsInt ( _T ( " Audio Lead in " ) ) ;
if ( curStartMS < 0 ) curStartMS = 0 ;
}
// Lead out
if ( out ) {
curEndMS + = Options . AsInt ( _T ( " Audio Lead out " ) ) ;
}
// Set changes
NeedCommit = true ;
if ( Options . AsBool ( _T ( " Audio Autocommit " ) ) ) CommitChanges ( ) ;
Update ( ) ;
}
///////////////
// Event table
BEGIN_EVENT_TABLE ( AudioDisplay , wxWindow )
EVT_MOUSE_EVENTS ( AudioDisplay : : OnMouseEvent )
EVT_PAINT ( AudioDisplay : : OnPaint )
EVT_SIZE ( AudioDisplay : : OnSize )
EVT_TIMER ( Audio_Update_Timer , AudioDisplay : : OnUpdateTimer )
EVT_KEY_DOWN ( AudioDisplay : : OnKeyDown )
EVT_SET_FOCUS ( AudioDisplay : : OnGetFocus )
EVT_KILL_FOCUS ( AudioDisplay : : OnLoseFocus )
END_EVENT_TABLE ( )
/////////
// Paint
void AudioDisplay : : OnPaint ( wxPaintEvent & event ) {
if ( w = = 0 | | h = = 0 ) return ;
wxPaintDC dc ( this ) ;
dc . DrawBitmap ( * origImage , 0 , 0 ) ;
}
///////////////
// Mouse event
void AudioDisplay : : OnMouseEvent ( wxMouseEvent & event ) {
// Get x,y
__int64 x = event . GetX ( ) ;
__int64 y = event . GetY ( ) ;
bool karMode = karaoke - > enabled ;
bool shiftDown = event . m_shiftDown ;
2007-01-06 07:14:35 +01:00
int timelineHeight = Options . AsBool ( _T ( " Audio Draw Timeline " ) ) ? 20 : 0 ;
2006-01-16 22:02:54 +01:00
2006-02-24 02:16:27 +01:00
// Leaving event
if ( event . Leaving ( ) ) {
event . Skip ( ) ;
return ;
}
2006-01-16 22:02:54 +01:00
// Is inside?
bool inside = false ;
2006-03-07 01:12:50 +01:00
bool onScale = false ;
if ( x > = 0 & & y > = 0 & & x < w ) {
if ( y < h ) {
inside = true ;
2006-01-16 22:02:54 +01:00
2006-03-07 01:12:50 +01:00
// Get focus
if ( wxWindow : : FindFocus ( ) ! = this & & Options . AsBool ( _T ( " Audio Autofocus " ) ) ) SetFocus ( ) ;
}
2007-01-06 07:14:35 +01:00
else if ( y < h + timelineHeight ) onScale = true ;
2006-01-16 22:02:54 +01:00
}
2007-04-07 05:12:55 +02:00
// Buttons
bool leftIsDown = event . ButtonIsDown ( wxMOUSE_BTN_LEFT ) ;
bool rightIsDown = event . ButtonIsDown ( wxMOUSE_BTN_RIGHT ) ;
bool buttonIsDown = leftIsDown | | rightIsDown ;
bool leftClick = event . ButtonDown ( wxMOUSE_BTN_LEFT ) ;
bool rightClick = event . ButtonDown ( wxMOUSE_BTN_RIGHT ) ;
bool middleClick = event . Button ( wxMOUSE_BTN_MIDDLE ) ;
bool buttonClick = leftClick | | rightClick ;
bool defCursor = true ;
2006-02-21 22:33:15 +01:00
// Click type
2007-04-07 05:12:55 +02:00
if ( buttonClick & & ! holding ) {
2006-02-21 22:33:15 +01:00
holding = true ;
CaptureMouse ( ) ;
}
2007-04-07 05:12:55 +02:00
if ( ! buttonIsDown & & holding ) {
2006-02-21 22:33:15 +01:00
holding = false ;
2006-07-04 08:13:54 +02:00
if ( HasCapture ( ) ) ReleaseMouse ( ) ;
}
2006-01-16 22:02:54 +01:00
// Mouse wheel
if ( event . GetWheelRotation ( ) ! = 0 ) {
// Zoom or scroll?
bool zoom = shiftDown ;
if ( Options . AsBool ( _T ( " Audio Wheel Default To Zoom " ) ) ) zoom = ! zoom ;
// Zoom
if ( zoom ) {
int step = - event . GetWheelRotation ( ) / event . GetWheelDelta ( ) ;
int value = box - > HorizontalZoom - > GetValue ( ) + step ;
box - > HorizontalZoom - > SetValue ( value ) ;
SetSamplesPercent ( value , true , float ( x ) / float ( w ) ) ;
}
// Scroll
else {
int step = event . GetWheelRotation ( ) * w / 360 ;
UpdatePosition ( Position + step , false ) ;
UpdateImage ( ) ;
}
}
// Cursor drawing
2006-02-25 08:41:18 +01:00
if ( ! player - > IsPlaying ( ) ) {
2006-01-16 22:02:54 +01:00
// Draw bg
wxClientDC dc ( this ) ;
dc . DrawBitmap ( * origImage , 0 , 0 ) ;
if ( inside ) {
// Draw cursor
dc . SetLogicalFunction ( wxINVERT ) ;
dc . DrawLine ( x , 0 , x , h ) ;
2007-01-06 07:14:35 +01:00
// Time
if ( Options . AsBool ( _T ( " Audio Draw Cursor Time " ) ) ) {
// Time string
AssTime time ;
time . SetMS ( GetMSAtX ( x ) ) ;
wxString text = time . GetASSFormated ( ) ;
// Calculate metrics
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 ) ;
// Set inversion
bool left = true ;
if ( x > w / 2 ) left = false ;
// Text coordinates
int dx ;
dx = x - tw / 2 ;
if ( dx < 4 ) dx = 4 ;
int max = w - tw - 4 ;
if ( dx > max ) dx = max ;
int dy = 4 ;
// 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 ) ;
}
2006-01-16 22:02:54 +01:00
}
}
2006-03-07 01:12:50 +01:00
// Scale dragging
2006-07-02 00:49:09 +02:00
if ( ( hold = = 0 & & onScale ) | | draggingScale ) {
2006-03-07 01:12:50 +01:00
if ( event . ButtonDown ( wxMOUSE_BTN_LEFT ) ) {
lastDragX = x ;
draggingScale = true ;
}
else if ( holding ) {
int delta = lastDragX - x ;
lastDragX = x ;
UpdatePosition ( Position + delta ) ;
UpdateImage ( ) ;
Refresh ( false ) ;
2006-07-02 00:49:09 +02:00
SetCursor ( wxNullCursor ) ;
return ;
2006-03-07 01:12:50 +01:00
}
else draggingScale = false ;
}
// Outside
2006-07-02 00:49:09 +02:00
if ( ! inside & & hold = = 0 ) return ;
2006-03-06 01:45:24 +01:00
2007-04-07 05:12:55 +02:00
// Left click
if ( leftClick ) {
2006-03-05 05:41:59 +01:00
SetFocus ( ) ;
2006-01-16 22:02:54 +01:00
}
// Right click
2007-04-07 05:12:55 +02:00
if ( rightClick ) {
2006-02-21 22:33:15 +01:00
SetFocus ( ) ;
2006-01-16 22:02:54 +01:00
if ( karaoke - > enabled ) {
int syl = GetSyllableAtX ( x ) ;
if ( syl ! = - 1 ) {
int start = karaoke - > syllables . at ( syl ) . position * 10 + dialogue - > Start . GetMS ( ) ;
int count = karaoke - > syllables . at ( syl ) . length * 10 ;
2006-02-25 08:41:18 +01:00
player - > Play ( GetSampleAtMS ( start ) , GetSampleAtMS ( count ) ) ;
2007-01-13 07:17:14 +01:00
//return;
2006-01-16 22:02:54 +01:00
}
}
}
2007-04-07 05:12:55 +02:00
// Middle click
if ( middleClick ) {
SetFocus ( ) ;
if ( VideoContext : : Get ( ) - > IsLoaded ( ) ) {
VideoContext : : Get ( ) - > JumpToTime ( GetMSAtX ( x ) , true ) ;
}
}
2006-01-16 22:02:54 +01:00
2007-01-06 00:43:24 +01:00
// Timing
if ( hasSel ) {
bool updated = false ;
// Grab start/end
if ( hold = = 0 ) {
bool gotGrab = false ;
2007-01-06 21:11:38 +01:00
bool karTime = karMode & & ! event . ControlDown ( ) ;
2007-01-06 00:43:24 +01:00
2007-01-15 04:50:49 +01:00
// Line timing mode
2007-01-06 21:11:38 +01:00
if ( ! karTime ) {
2007-01-15 04:50:49 +01:00
// Grab start
2007-01-06 00:43:24 +01:00
if ( abs64 ( x - selStart ) < 6 ) {
wxCursor cursor ( wxCURSOR_SIZEWE ) ;
SetCursor ( cursor ) ;
defCursor = false ;
2007-01-15 04:50:49 +01:00
if ( buttonClick ) {
2007-01-06 00:43:24 +01:00
hold = 1 ;
gotGrab = true ;
2006-01-16 22:02:54 +01:00
}
2007-01-06 00:43:24 +01:00
}
2006-01-16 22:02:54 +01:00
2007-01-06 00:43:24 +01:00
// Grab end
else if ( abs64 ( x - selEnd ) < 6 ) {
wxCursor cursor ( wxCURSOR_SIZEWE ) ;
SetCursor ( cursor ) ;
defCursor = false ;
2007-01-15 04:50:49 +01:00
if ( buttonClick ) {
2007-01-06 00:43:24 +01:00
hold = 2 ;
gotGrab = true ;
2006-01-16 22:02:54 +01:00
}
}
2007-01-15 04:50:49 +01:00
// Dragging nothing, time from scratch
else {
if ( buttonClick ) {
if ( leftClick ) hold = 3 ;
else hold = 2 ;
lastX = x ;
gotGrab = true ;
}
}
2007-01-06 00:43:24 +01:00
}
2006-01-16 22:02:54 +01:00
2007-01-15 04:50:49 +01:00
// Karaoke mode
2007-01-06 21:11:38 +01:00
else {
2007-01-15 04:50:49 +01:00
// Look for a syllable
2007-01-06 00:43:24 +01:00
__int64 pos , len , curpos ;
KaraokeSyllable * curSyl ;
size_t karn = karaoke - > syllables . size ( ) ;
for ( size_t i = 0 ; i < karn ; i + + ) {
curSyl = & karaoke - > syllables . at ( i ) ;
len = curSyl - > length * 10 ;
curpos = curSyl - > position * 10 ;
if ( len ! = - 1 ) {
pos = GetXAtMS ( curStartMS + len + curpos ) ;
2007-01-15 04:50:49 +01:00
// Grabbing syllable boundary
2007-01-06 00:43:24 +01:00
if ( abs64 ( x - pos ) < 4 ) {
wxCursor cursor ( wxCURSOR_SIZEWE ) ;
SetCursor ( cursor ) ;
defCursor = false ;
if ( event . LeftIsDown ( ) ) {
hold = 4 ;
holdSyl = ( int ) i ;
gotGrab = true ;
2006-01-16 22:02:54 +01:00
}
2007-01-06 00:43:24 +01:00
break ;
2006-01-16 22:02:54 +01:00
}
}
}
2007-01-15 04:50:49 +01:00
// No syllable found, select if possible
if ( hold = = 0 & & leftClick ) {
int syl = GetSyllableAtX ( x ) ;
if ( syl ! = - 1 ) {
karaoke - > SetSyllable ( syl ) ;
updated = true ;
}
2006-01-16 22:02:54 +01:00
}
}
2007-01-06 00:43:24 +01:00
}
2006-01-16 22:02:54 +01:00
2007-01-06 00:43:24 +01:00
// Drag start/end
if ( hold ! = 0 ) {
// Dragging
if ( buttonIsDown ) {
2007-01-06 04:40:58 +01:00
// Drag from nothing or straight timing
2007-01-06 00:43:24 +01:00
if ( hold = = 3 & & buttonIsDown ) {
if ( ! karMode ) {
if ( leftIsDown ) curStartMS = GetMSAtX ( x ) ;
else curEndMS = GetMSAtX ( x ) ;
updated = true ;
2007-01-06 04:40:58 +01:00
diagUpdated = true ;
2007-01-06 00:43:24 +01:00
2007-01-06 05:19:00 +01:00
if ( leftIsDown & & x ! = lastX ) {
selStart = lastX ;
2007-01-06 00:43:24 +01:00
selEnd = x ;
2007-04-07 04:39:18 +02:00
curStartMS = GetBoundarySnap ( GetMSAtX ( lastX ) , 10 , event . ShiftDown ( ) , true ) ;
2007-01-06 00:43:24 +01:00
curEndMS = GetMSAtX ( x ) ;
hold = 2 ;
2006-01-16 22:02:54 +01:00
}
}
2007-01-06 00:43:24 +01:00
}
2006-01-16 22:02:54 +01:00
2007-01-06 00:43:24 +01:00
// Drag start
if ( hold = = 1 & & buttonIsDown ) {
// Set new value
if ( x ! = selStart ) {
2007-04-07 04:39:18 +02:00
int snapped = GetBoundarySnap ( GetMSAtX ( x ) , 10 , event . ShiftDown ( ) , true ) ;
2007-01-06 23:07:48 +01:00
selStart = GetXAtMS ( snapped ) ;
2007-01-06 00:43:24 +01:00
if ( selStart > selEnd ) {
int temp = selStart ;
selStart = selEnd ;
selEnd = temp ;
hold = 2 ;
2007-01-06 23:13:56 +01:00
curEndMS = snapped ;
snapped = GetMSAtX ( selStart ) ;
2006-01-16 22:02:54 +01:00
}
2007-01-06 23:13:56 +01:00
curStartMS = snapped ;
2007-01-06 00:43:24 +01:00
updated = true ;
diagUpdated = true ;
2006-01-16 22:02:54 +01:00
}
2007-01-06 00:43:24 +01:00
}
2006-01-16 22:02:54 +01:00
2007-01-06 00:43:24 +01:00
// Drag end
if ( hold = = 2 & & buttonIsDown ) {
// Set new value
if ( x ! = selEnd ) {
2007-04-07 04:39:18 +02:00
int snapped = GetBoundarySnap ( GetMSAtX ( x ) , 10 , event . ShiftDown ( ) , false ) ;
2007-01-06 23:07:48 +01:00
selEnd = GetXAtMS ( snapped ) ;
//selEnd = GetBoundarySnap(x,event.ShiftDown()?0:10,false);
2007-01-06 00:43:24 +01:00
if ( selStart > selEnd ) {
int temp = selStart ;
selStart = selEnd ;
selEnd = temp ;
hold = 1 ;
2007-01-06 23:13:56 +01:00
curStartMS = snapped ;
snapped = GetMSAtX ( selEnd ) ;
2006-01-16 22:02:54 +01:00
}
2007-01-06 23:13:56 +01:00
curEndMS = snapped ;
2007-01-06 00:43:24 +01:00
updated = true ;
diagUpdated = true ;
2006-01-16 22:02:54 +01:00
}
2007-01-06 00:43:24 +01:00
}
2006-01-16 22:02:54 +01:00
2007-01-06 00:43:24 +01:00
// Drag karaoke
if ( hold = = 4 & & leftIsDown ) {
// Set new value
int curpos , len , pos , nkar ;
KaraokeSyllable * curSyl = NULL , * nextSyl = NULL ;
curSyl = & karaoke - > syllables . at ( holdSyl ) ;
nkar = ( int ) karaoke - > syllables . size ( ) ;
if ( holdSyl < nkar - 1 ) {
nextSyl = & karaoke - > syllables . at ( holdSyl + 1 ) ;
}
curpos = curSyl - > position ;
len = curSyl - > length ;
pos = GetXAtMS ( curStartMS + ( len + curpos ) * 10 ) ;
if ( x ! = pos ) {
// Calculate delta in centiseconds
int delta = ( ( __int64 ) ( x - pos ) * samples * 100 ) / provider - > GetSampleRate ( ) ;
// Apply delta
int deltaMode = 0 ;
if ( shiftDown ) deltaMode = 1 ;
// else if (ctrlDown) deltaMode = 2;
bool result = karaoke - > SyllableDelta ( holdSyl , delta , deltaMode ) ;
if ( result ) {
updated = true ;
diagUpdated = true ;
}
2006-01-16 22:02:54 +01:00
}
}
2007-01-06 00:43:24 +01:00
}
2006-01-16 22:02:54 +01:00
2007-01-06 00:43:24 +01:00
// Release
else {
// Commit changes
if ( diagUpdated ) {
diagUpdated = false ;
NeedCommit = true ;
2007-01-08 04:05:26 +01:00
if ( curStartMS < = curEndMS ) {
grid - > editBox - > StartTime - > SetTime ( curStartMS , true ) ;
grid - > editBox - > EndTime - > SetTime ( curEndMS , true ) ;
grid - > editBox - > Duration - > SetTime ( curEndMS - curStartMS , true ) ;
if ( Options . AsBool ( _T ( " Audio Autocommit " ) ) ) CommitChanges ( ) ;
}
2007-01-06 00:43:24 +01:00
else UpdateImage ( true ) ;
}
2006-01-16 22:02:54 +01:00
2007-01-06 00:43:24 +01:00
// Update stuff
SetCursor ( wxNullCursor ) ;
hold = 0 ;
2006-01-16 22:02:54 +01:00
}
}
2007-01-06 00:43:24 +01:00
// Update stuff
if ( updated ) {
2007-01-08 04:05:26 +01:00
if ( diagUpdated ) NeedCommit = true ;
2007-01-06 00:43:24 +01:00
player - > SetEndPosition ( GetSampleAtX ( selEnd ) ) ;
2007-01-15 04:50:49 +01:00
if ( hold ! = 0 ) {
wxCursor cursor ( wxCURSOR_SIZEWE ) ;
SetCursor ( cursor ) ;
}
2007-01-06 00:43:24 +01:00
UpdateImage ( true ) ;
2006-01-16 22:02:54 +01:00
}
}
2007-01-06 00:43:24 +01:00
// Not holding
else {
hold = 0 ;
}
2006-01-16 22:02:54 +01:00
// Restore cursor
if ( defCursor ) SetCursor ( wxNullCursor ) ;
}
2007-01-06 05:19:00 +01:00
////////////////////////
// Get snap to boundary
2007-04-07 04:39:18 +02:00
int AudioDisplay : : GetBoundarySnap ( int ms , int rangeX , bool shiftHeld , bool start ) {
2007-01-06 21:11:38 +01:00
// Range?
2007-01-06 23:07:48 +01:00
if ( rangeX < = 0 ) return ms ;
// Convert range into miliseconds
int rangeMS = rangeX * samples * 1000 / provider - > GetSampleRate ( ) ;
2007-01-06 21:11:38 +01:00
2007-04-07 04:39:18 +02:00
// Keyframe boundaries
2007-01-06 05:19:00 +01:00
wxArrayInt boundaries ;
2007-04-07 04:39:18 +02:00
bool snapKey = Options . AsBool ( _T ( " Audio snap to keyframes " ) ) ;
if ( shiftHeld ) snapKey = ! snapKey ;
if ( snapKey & & VideoContext : : Get ( ) - > KeyFramesLoaded ( ) & & Options . AsBool ( _T ( " Audio Draw Keyframes " ) ) ) {
2007-01-06 23:07:48 +01:00
__int64 keyMS ;
2007-01-21 07:30:19 +01:00
wxArrayInt keyFrames = VideoContext : : Get ( ) - > GetKeyFrames ( ) ;
2007-01-06 23:07:48 +01:00
int frame ;
2007-01-06 05:19:00 +01:00
for ( unsigned int i = 0 ; i < keyFrames . Count ( ) ; i + + ) {
2007-01-06 23:07:48 +01:00
frame = keyFrames [ i ] ;
if ( ! start ) frame - - ;
if ( frame < 0 ) frame = 0 ;
keyMS = VFR_Output . GetTimeAtFrame ( frame , start ) ;
//if (start) keyX++;
if ( GetXAtMS ( keyMS ) > = 0 & & GetXAtMS ( keyMS ) < w ) boundaries . Add ( keyMS ) ;
2007-01-06 05:19:00 +01:00
}
}
// Other subtitles' boundaries
int inactiveType = Options . AsInt ( _T ( " Audio Inactive Lines Display Mode " ) ) ;
2007-04-07 04:39:18 +02:00
bool snapLines = Options . AsBool ( _T ( " Audio snap to other lines " ) ) ;
if ( shiftHeld ) snapLines = ! snapLines ;
if ( snapLines & & ( inactiveType = = 1 | | inactiveType = = 2 ) ) {
2007-01-06 05:19:00 +01:00
AssDialogue * shade ;
int shadeX1 , shadeX2 ;
int shadeFrom , shadeTo ;
// Get range
if ( inactiveType = = 1 ) {
shadeFrom = this - > line_n - 1 ;
shadeTo = shadeFrom + 1 ;
}
else {
shadeFrom = 0 ;
shadeTo = grid - > GetRows ( ) ;
}
for ( int j = shadeFrom ; j < shadeTo ; j + + ) {
if ( j = = line_n ) continue ;
shade = grid - > GetDialogue ( j ) ;
if ( shade ) {
// Get coordinates
shadeX1 = GetXAtMS ( shade - > Start . GetMS ( ) ) ;
shadeX2 = GetXAtMS ( shade - > End . GetMS ( ) ) ;
2007-01-06 23:07:48 +01:00
if ( shadeX1 > = 0 & & shadeX1 < w ) boundaries . Add ( shade - > Start . GetMS ( ) ) ;
if ( shadeX2 > = 0 & & shadeX2 < w ) boundaries . Add ( shade - > End . GetMS ( ) ) ;
2007-01-06 05:19:00 +01:00
}
}
}
2007-01-06 23:07:48 +01:00
// See if ms falls within range of any of them
int minDist = rangeMS + 1 ;
int bestMS = ms ;
2007-01-06 05:19:00 +01:00
for ( unsigned int i = 0 ; i < boundaries . Count ( ) ; i + + ) {
2007-01-06 23:07:48 +01:00
if ( abs ( ms - boundaries [ i ] ) < minDist ) {
bestMS = boundaries [ i ] ;
minDist = abs ( ms - boundaries [ i ] ) ;
2007-01-06 05:19:00 +01:00
}
}
// Return best match
2007-01-06 23:07:48 +01:00
return bestMS ;
2007-01-06 05:19:00 +01:00
}
//
// SCRUBBING CODE, REMOVED FROM THE FUNCTION ABOVE
/*
// Stop scrubbing
bool scrubButton = false & & event . ButtonIsDown ( wxMOUSE_BTN_MIDDLE ) ;
if ( scrubbing & & ! scrubButton ) {
// Release mouse
scrubbing = false ;
if ( HasCapture ( ) ) ReleaseMouse ( ) ;
// Stop player
player - > Stop ( ) ;
player - > SetProvider ( provider ) ;
delete scrubProvider ;
}
// Start scrubbing
if ( ! scrubbing & & scrubButton & & provider - > GetChannels ( ) = = 1 ) {
// Get mouse
CaptureMouse ( ) ;
scrubbing = true ;
// Initialize provider
player - > Stop ( ) ;
scrubProvider = new StreamAudioProvider ( ) ;
scrubProvider - > SetParams ( provider - > GetChannels ( ) , provider - > GetSampleRate ( ) , provider - > GetBytesPerSample ( ) ) ;
player - > SetProvider ( scrubProvider ) ;
// Set variables
scrubLastPos = GetSampleAtX ( x ) ;
scrubTime = clock ( ) ;
scrubLastRate = provider - > GetSampleRate ( ) ;
}
// Scrub
if ( scrubbing & & scrubButton ) {
// Get current data
__int64 exactPos = MAX ( 0 , GetSampleAtX ( x ) ) ;
int curScrubTime = clock ( ) ;
int scrubDeltaTime = curScrubTime - scrubTime ;
bool invert = exactPos < scrubLastPos ;
__int64 curScrubPos = exactPos ;
if ( scrubDeltaTime > 0 ) {
// Get derived data
int rateChange = provider - > GetSampleRate ( ) / 20 ;
int curRate = MID ( int ( scrubLastRate - rateChange ) , abs ( int ( exactPos - scrubLastPos ) ) * CLOCKS_PER_SEC / scrubDeltaTime , int ( scrubLastRate + rateChange ) ) ;
if ( abs ( curRate - scrubLastRate ) < rateChange ) curRate = scrubLastRate ;
curScrubPos = scrubLastPos + ( curRate * scrubDeltaTime / CLOCKS_PER_SEC * ( invert ? - 1 : 1 ) ) ;
__int64 scrubDelta = curScrubPos - scrubLastPos ;
scrubLastRate = curRate ;
// Copy data to buffer
if ( scrubDelta ! = 0 ) {
// Create buffer
int bufSize = scrubDeltaTime * scrubProvider - > GetSampleRate ( ) / CLOCKS_PER_SEC ;
short * buf = new short [ bufSize ] ;
// Flag as inverted, if necessary
if ( invert ) scrubDelta = - scrubDelta ;
// Copy data from original provider to temp buffer
short * temp = new short [ scrubDelta ] ;
provider - > GetAudio ( temp , MIN ( curScrubPos , scrubLastPos ) , scrubDelta ) ;
// Scale
float scale = float ( double ( scrubDelta ) / double ( bufSize ) ) ;
float start , end ;
int istart , iend ;
float tempfinal ;
for ( int i = 0 ; i < bufSize ; i + + ) {
start = i * scale ;
end = ( i + 1 ) * scale ;
istart = ( int ) start ;
iend = MIN ( ( int ) end , scrubDelta - 1 ) ;
if ( istart = = iend ) tempfinal = temp [ istart ] * ( end - start ) ;
else {
tempfinal = temp [ istart ] * ( 1 + istart - start ) + temp [ iend ] * ( end - iend ) ;
for ( int j = istart + 1 ; j < iend ; j + + ) tempfinal + = temp [ i ] ;
}
buf [ i ] = tempfinal / scale ;
}
//int len = MIN(bufSize,scrubDelta);
//for (int i=0;i<len;i++) buf[i] = temp[i];
//for (int i=len;i<bufSize;i++) buf[i] = 0;
delete temp ;
// Invert
if ( invert ) {
short aux ;
for ( int i = 0 ; i < bufSize / 2 ; i + + ) {
aux = buf [ i ] ;
buf [ i ] = buf [ bufSize - i - 1 ] ;
buf [ bufSize - i - 1 ] = aux ;
}
}
// Send data to provider
scrubProvider - > Append ( buf , bufSize ) ;
if ( ! player - > IsPlaying ( ) ) player - > Play ( 0 , ~ 0ULL ) ;
delete buf ;
}
}
// Update last pos and time
scrubLastPos = curScrubPos ;
scrubTime = curScrubTime ;
// Return
return ;
}
*/
2006-01-16 22:02:54 +01:00
//////////////
// Size event
void AudioDisplay : : OnSize ( wxSizeEvent & event ) {
// Set size
GetClientSize ( & w , & h ) ;
2007-01-06 07:14:35 +01:00
h - = Options . AsBool ( _T ( " Audio Draw Timeline " ) ) ? 20 : 0 ;
2006-01-16 22:02:54 +01:00
// Update image
UpdateImage ( ) ;
// Update scrollbar
UpdateScrollbar ( ) ;
}
///////////////
// Timer event
void AudioDisplay : : OnUpdateTimer ( wxTimerEvent & event ) {
// Get lock and check if it's OK
2006-02-25 08:41:18 +01:00
if ( player - > GetMutex ( ) ) {
wxMutexLocker locker ( * player - > GetMutex ( ) ) ;
2006-02-25 07:04:46 +01:00
if ( ! locker . IsOk ( ) ) return ;
}
2006-02-25 08:41:18 +01:00
if ( ! player - > IsPlaying ( ) ) return ;
2006-01-16 22:02:54 +01:00
// Get DCs
//wxMutexGuiEnter();
wxClientDC dc ( this ) ;
// Draw cursor
int curpos = - 1 ;
2006-02-25 08:41:18 +01:00
if ( player - > IsPlaying ( ) ) {
2006-03-06 00:01:02 +01:00
__int64 curPos = player - > GetCurrentPosition ( ) ;
if ( curPos > player - > GetStartPosition ( ) & & curPos < player - > GetEndPosition ( ) ) {
// Scroll if needed
int posX = GetXAtSample ( curPos ) ;
2006-03-06 00:41:00 +01:00
bool fullDraw = false ;
2006-03-20 22:48:01 +01:00
bool centerLock = false ;
bool scrollToCursor = Options . AsBool ( _T ( " Audio lock scroll on cursor " ) ) ;
2006-03-06 00:41:00 +01:00
if ( centerLock ) {
int goTo = MAX ( 0 , curPos - w * samples / 2 ) ;
if ( goTo > = 0 ) {
UpdatePosition ( goTo , true ) ;
UpdateImage ( ) ;
fullDraw = true ;
}
}
else {
2006-03-20 22:48:01 +01:00
if ( scrollToCursor ) {
if ( posX < 80 | | posX > w - 80 ) {
int goTo = MAX ( 0 , curPos - 80 * samples ) ;
if ( goTo > = 0 ) {
UpdatePosition ( goTo , true ) ;
UpdateImage ( ) ;
fullDraw = true ;
}
2006-03-06 00:41:00 +01:00
}
}
2006-03-06 00:01:02 +01:00
}
// Draw cursor
wxMemoryDC src ;
curpos = GetXAtSample ( curPos ) ;
2006-03-06 00:41:00 +01:00
dc . SetPen ( wxPen ( Options . AsColour ( _T ( " Audio Play cursor " ) ) ) ) ;
src . SelectObject ( * origImage ) ;
if ( fullDraw ) {
//dc.Blit(0,0,w,h,&src,0,0);
dc . DrawLine ( curpos , 0 , curpos , h ) ;
//dc.Blit(0,0,curpos-10,h,&src,0,0);
//dc.Blit(curpos+10,0,w-curpos-10,h,&src,curpos+10,0);
}
else {
dc . Blit ( oldCurPos , 0 , 1 , h , & src , oldCurPos , 0 ) ;
dc . DrawLine ( curpos , 0 , curpos , h ) ;
}
2006-01-16 22:02:54 +01:00
}
2006-03-06 00:01:02 +01:00
else {
if ( curPos > player - > GetEndPosition ( ) + 8192 ) {
player - > Stop ( ) ;
}
wxMemoryDC src ;
src . SelectObject ( * origImage ) ;
dc . Blit ( oldCurPos , 0 , 1 , h , & src , oldCurPos , 0 ) ;
2006-01-16 22:02:54 +01:00
}
}
2006-03-06 00:01:02 +01:00
// Restore background
else {
wxMemoryDC src ;
src . SelectObject ( * origImage ) ;
dc . Blit ( oldCurPos , 0 , 1 , h , & src , oldCurPos , 0 ) ;
}
2006-01-16 22:02:54 +01:00
oldCurPos = curpos ;
}
////////////
// Key down
void AudioDisplay : : OnKeyDown ( wxKeyEvent & event ) {
int key = event . GetKeyCode ( ) ;
Hotkeys . SetPressed ( key , event . m_controlDown , event . m_altDown , event . m_shiftDown ) ;
// Accept
if ( Hotkeys . IsPressed ( _T ( " Audio Commit " ) ) ) {
2007-01-06 04:40:58 +01:00
CommitChanges ( true ) ;
//ChangeLine(1);
2006-01-16 22:02:54 +01:00
}
// Accept (SSA's "Grab times")
if ( Hotkeys . IsPressed ( _T ( " Audio Commit Alt " ) ) ) {
2007-01-06 04:40:58 +01:00
CommitChanges ( true ) ;
2006-01-16 22:02:54 +01:00
}
// Accept (stay)
if ( Hotkeys . IsPressed ( _T ( " Audio Commit (Stay) " ) ) ) {
CommitChanges ( ) ;
}
// Previous
if ( Hotkeys . IsPressed ( _T ( " Audio Prev Line " ) ) | | Hotkeys . IsPressed ( _T ( " Audio Prev Line Alt " ) ) ) {
Prev ( ) ;
}
// Next
if ( Hotkeys . IsPressed ( _T ( " Audio Next Line " ) ) | | Hotkeys . IsPressed ( _T ( " Audio Next Line Alt " ) ) ) {
Next ( ) ;
}
// Play
if ( Hotkeys . IsPressed ( _T ( " Audio Play " ) ) | | Hotkeys . IsPressed ( _T ( " Audio Play Alt " ) ) ) {
2007-01-06 00:43:24 +01:00
int start = 0 , end = 0 ;
GetTimesSelection ( start , end ) ;
Play ( start , end ) ;
2006-01-16 22:02:54 +01:00
}
2007-01-06 05:27:09 +01:00
// Play/Stop
if ( Hotkeys . IsPressed ( _T ( " Audio Play or Stop " ) ) ) {
if ( player - > IsPlaying ( ) ) Stop ( ) ;
else {
int start = 0 , end = 0 ;
GetTimesSelection ( start , end ) ;
Play ( start , end ) ;
}
}
// Stop
if ( Hotkeys . IsPressed ( _T ( " Audio Stop " ) ) ) {
Stop ( ) ;
}
2006-01-16 22:02:54 +01:00
// Increase length
if ( Hotkeys . IsPressed ( _T ( " Audio Karaoke Increase Len " ) ) ) {
if ( karaoke - > enabled ) {
bool result = karaoke - > SyllableDelta ( karaoke - > curSyllable , 1 , 0 ) ;
if ( result ) diagUpdated = true ;
}
}
// Increase length (shift)
if ( Hotkeys . IsPressed ( _T ( " Audio Karaoke Increase Len Shift " ) ) ) {
if ( karaoke - > enabled ) {
bool result = karaoke - > SyllableDelta ( karaoke - > curSyllable , 1 , 1 ) ;
if ( result ) diagUpdated = true ;
}
}
// Decrease length
if ( Hotkeys . IsPressed ( _T ( " Audio Karaoke Decrease Len " ) ) ) {
if ( karaoke - > enabled ) {
bool result = karaoke - > SyllableDelta ( karaoke - > curSyllable , - 1 , 0 ) ;
if ( result ) diagUpdated = true ;
}
}
// Decrease length (shift)
if ( Hotkeys . IsPressed ( _T ( " Audio Karaoke Decrease Len Shift " ) ) ) {
if ( karaoke - > enabled ) {
bool result = karaoke - > SyllableDelta ( karaoke - > curSyllable , - 1 , 1 ) ;
if ( result ) diagUpdated = true ;
}
}
// Move backwards
if ( Hotkeys . IsPressed ( _T ( " Audio Scroll Left " ) ) ) {
UpdatePosition ( Position - 128 , false ) ;
UpdateImage ( ) ;
}
// Move forward
if ( Hotkeys . IsPressed ( _T ( " Audio Scroll Right " ) ) ) {
UpdatePosition ( Position + 128 , false ) ;
UpdateImage ( ) ;
}
// Play first 500 ms
if ( Hotkeys . IsPressed ( _T ( " Audio Play First 500ms " ) ) ) {
int start = 0 , end = 0 ;
GetTimesSelection ( start , end ) ;
int e = start + 500 ;
if ( e > end ) e = end ;
Play ( start , e ) ;
}
// Play last 500 ms
if ( Hotkeys . IsPressed ( _T ( " Audio Play Last 500ms " ) ) ) {
int start = 0 , end = 0 ;
GetTimesSelection ( start , end ) ;
int s = end - 500 ;
if ( s < start ) s = start ;
Play ( s , end ) ;
}
// Play 500 ms before
if ( Hotkeys . IsPressed ( _T ( " Audio Play 500ms Before " ) ) ) {
int start = 0 , end = 0 ;
GetTimesSelection ( start , end ) ;
Play ( start - 500 , start ) ;
}
// Play 500 ms after
if ( Hotkeys . IsPressed ( _T ( " Audio Play 500ms After " ) ) ) {
int start = 0 , end = 0 ;
GetTimesSelection ( start , end ) ;
Play ( end , end + 500 ) ;
}
2006-07-01 08:37:46 +02:00
// Play to end of file
if ( Hotkeys . IsPressed ( _T ( " Audio Play To End " ) ) ) {
int start = 0 , end = 0 ;
GetTimesSelection ( start , end ) ;
Play ( start , - 1 ) ;
}
2006-01-16 22:02:54 +01:00
// Play original line
if ( Hotkeys . IsPressed ( _T ( " Audio Play Original Line " ) ) ) {
int start = 0 , end = 0 ;
GetTimesDialogue ( start , end ) ;
2007-01-06 00:43:24 +01:00
SetSelection ( start , end ) ;
2006-01-16 22:02:54 +01:00
Play ( start , end ) ;
}
// Lead in
if ( Hotkeys . IsPressed ( _T ( " Audio Add Lead In " ) ) ) {
AddLead ( true , false ) ;
}
// Lead out
if ( Hotkeys . IsPressed ( _T ( " Audio Add Lead Out " ) ) ) {
AddLead ( false , true ) ;
}
// Update
if ( diagUpdated ) {
diagUpdated = false ;
NeedCommit = true ;
2007-01-06 00:43:24 +01:00
if ( Options . AsBool ( _T ( " Audio Autocommit " ) ) & & curStartMS < = curEndMS ) CommitChanges ( ) ;
else UpdateImage ( true ) ;
2006-01-16 22:02:54 +01:00
}
}
///////////////
// Change line
void AudioDisplay : : ChangeLine ( int delta ) {
if ( dialogue ) {
// Get next line number and make sure it's within bounds
int next = line_n + delta ;
2006-02-20 08:12:01 +01:00
if ( next = = - 1 ) next = 0 ;
if ( next = = grid - > GetRows ( ) ) next = grid - > GetRows ( ) - 1 ;
2006-01-16 22:02:54 +01:00
// Set stuff
NeedCommit = false ;
dialogue = NULL ;
grid - > editBox - > SetToLine ( next ) ;
grid - > SelectRow ( next ) ;
2006-12-18 21:13:23 +01:00
grid - > MakeCellVisible ( next , 0 , true ) ;
2006-02-20 08:12:01 +01:00
if ( ! dialogue ) UpdateImage ( true ) ;
else UpdateImage ( false ) ;
2006-01-16 22:02:54 +01:00
line_n = next ;
}
}
////////
// Next
void AudioDisplay : : Next ( ) {
// Karaoke
if ( karaoke - > enabled ) {
2006-02-20 08:12:01 +01:00
int nextSyl = karaoke - > curSyllable + 1 ;
bool needsUpdate = true ;
2006-01-16 22:02:54 +01:00
// Last syllable; jump to next
2006-02-20 08:12:01 +01:00
if ( nextSyl > = ( signed int ) karaoke - > syllables . size ( ) ) {
// Already last?
if ( line_n = = grid - > GetRows ( ) - 1 ) return ;
2006-01-16 22:02:54 +01:00
if ( NeedCommit ) {
int result = wxMessageBox ( _ ( " Do you want to commit your changes? If you choose No, they will be discarded. " ) , _ ( " Commit? " ) , wxYES_NO | wxCANCEL | wxICON_QUESTION ) ;
//int result = wxNO;
if ( result = = wxYES ) {
CommitChanges ( ) ;
}
else if ( result = = wxCANCEL ) {
2006-08-28 00:29:14 +02:00
karaoke - > curSyllable = ( int ) karaoke - > syllables . size ( ) - 1 ;
2006-01-16 22:02:54 +01:00
return ;
}
}
2006-02-20 08:12:01 +01:00
nextSyl = 0 ;
2006-01-16 22:02:54 +01:00
karaoke - > curSyllable = 0 ;
ChangeLine ( 1 ) ;
2006-02-20 08:12:01 +01:00
needsUpdate = false ;
2006-01-16 22:02:54 +01:00
}
// Set syllable
2006-02-20 08:12:01 +01:00
karaoke - > SetSyllable ( nextSyl ) ;
if ( needsUpdate ) Update ( ) ;
2006-01-16 22:02:54 +01:00
int start = 0 , end = 0 ;
GetTimesSelection ( start , end ) ;
Play ( start , end ) ;
}
// Plain mode
else {
ChangeLine ( 1 ) ;
}
}
////////////
// Previous
void AudioDisplay : : Prev ( ) {
// Karaoke
if ( karaoke - > enabled ) {
2006-02-20 08:12:01 +01:00
int nextSyl = karaoke - > curSyllable - 1 ;
bool needsUpdate = true ;
2006-01-16 22:02:54 +01:00
// First syllable; jump line
2006-02-20 08:12:01 +01:00
if ( nextSyl < 0 ) {
// Already first?
if ( line_n = = 0 ) return ;
2006-01-16 22:02:54 +01:00
if ( NeedCommit ) {
int result = wxMessageBox ( _ ( " Do you want to commit your changes? If you choose No, they will be discarded. " ) , _ ( " Commit? " ) , wxYES_NO | wxCANCEL ) ;
if ( result = = wxYES ) {
CommitChanges ( ) ;
}
else if ( result = = wxCANCEL ) {
2006-02-19 07:05:15 +01:00
karaoke - > curSyllable = 0 ;
2006-01-16 22:02:54 +01:00
return ;
}
}
2006-02-20 08:12:01 +01:00
karaoke - > curSyllable = - 1 ;
2006-01-16 22:02:54 +01:00
ChangeLine ( - 1 ) ;
2006-02-20 08:12:01 +01:00
needsUpdate = false ;
2006-01-16 22:02:54 +01:00
}
// Set syllable
2006-02-20 08:12:01 +01:00
karaoke - > SetSyllable ( nextSyl ) ;
if ( needsUpdate ) Update ( ) ;
2006-01-16 22:02:54 +01:00
int start = 0 , end = 0 ;
GetTimesSelection ( start , end ) ;
Play ( start , end ) ;
}
// Plain mode
else {
ChangeLine ( - 1 ) ;
}
}
///////////////////////////////
// Gets syllable at x position
int AudioDisplay : : GetSyllableAtX ( int x ) {
if ( ! karaoke - > enabled ) return - 1 ;
int ms = GetMSAtX ( x ) ;
size_t syllables = karaoke - > syllables . size ( ) ; ;
int sylstart , sylend ;
// Find a matching syllable
for ( size_t i = 0 ; i < syllables ; i + + ) {
sylstart = karaoke - > syllables . at ( i ) . position * 10 + curStartMS ;
sylend = karaoke - > syllables . at ( i ) . length * 10 + sylstart ;
if ( ms > = sylstart & & ms < sylend ) {
2006-08-28 00:29:14 +02:00
return ( int ) i ;
2006-01-16 22:02:54 +01:00
}
}
return - 1 ;
}
////////////////
// Focus events
void AudioDisplay : : OnGetFocus ( wxFocusEvent & event ) {
if ( ! hasFocus ) {
hasFocus = true ;
UpdateImage ( true ) ;
}
}
void AudioDisplay : : OnLoseFocus ( wxFocusEvent & event ) {
2006-03-16 00:53:44 +01:00
if ( hasFocus & & loaded ) {
2006-01-16 22:02:54 +01:00
hasFocus = false ;
UpdateImage ( true ) ;
Refresh ( false ) ;
}
}