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 <wx/wxprec.h>
# include <wx/config.h>
# include <wx/filename.h>
# include <wx/msgdlg.h>
2007-01-07 23:54:04 +01:00
# include <wx/mimetype.h>
2006-01-16 22:02:54 +01:00
# include "main.h"
# include "frame_main.h"
# include "options.h"
# include "hotkeys.h"
# include "dialog_associations.h"
# include "ass_file.h"
# include "audio_box.h"
# include "audio_display.h"
# include "export_framerate.h"
# include "ass_export_filter.h"
# include "ass_time.h"
2006-02-27 05:18:00 +01:00
# include "ass_dialogue.h"
2006-02-18 22:55:58 +01:00
# include "subs_grid.h"
2006-12-28 23:31:33 +01:00
# include "auto4_base.h"
2007-01-15 07:56:35 +01:00
# include "subtitle_format.h"
2007-01-21 07:30:19 +01:00
# include "video_context.h"
2006-01-16 22:02:54 +01:00
///////////////////
// wxWidgets macro
IMPLEMENT_APP ( AegisubApp )
///////////////////////////
// Initialization function
// -----------------------
// Gets called when application starts, creates MainFrame
bool AegisubApp : : OnInit ( ) {
try {
// Initialize randomizer
srand ( time ( NULL ) ) ;
2007-04-03 06:34:56 +02:00
// locale for loading options
setlocale ( LC_NUMERIC , " C " ) ;
setlocale ( LC_CTYPE , " C " ) ;
2006-01-16 22:02:54 +01:00
// App name
SetAppName ( _T ( " Aegisub " ) ) ;
2006-02-26 23:45:34 +01:00
# ifndef _DEBUG
2006-01-16 22:02:54 +01:00
wxHandleFatalExceptions ( true ) ;
2006-02-26 23:45:34 +01:00
# endif
2006-01-16 22:02:54 +01:00
// Set config file
GetFullPath ( argv [ 0 ] ) ;
GetFolderName ( ) ;
Options . SetFile ( folderName + _T ( " /config.dat " ) ) ;
Options . Load ( ) ;
AssTime : : UseMSPrecision = Options . AsBool ( _T ( " Use nonstandard Milisecond Times " ) ) ;
// Set hotkeys file
Hotkeys . SetFile ( folderName + _T ( " /hotkeys.dat " ) ) ;
Hotkeys . Load ( ) ;
2006-05-10 02:33:44 +02:00
# ifdef __WINDOWS__
2006-01-16 22:02:54 +01:00
// Set locale
int lang = Options . AsInt ( _T ( " Locale Code " ) ) ;
if ( lang = = - 1 ) {
lang = locale . PickLanguage ( ) ;
Options . SetInt ( _T ( " Locale Code " ) , lang ) ;
Options . Save ( ) ;
}
locale . Init ( lang ) ;
2006-05-06 16:38:53 +02:00
# else
2007-04-03 06:34:56 +02:00
locale . Init ( wxLANGUAGE_DEFAULT ) ;
2006-05-06 16:38:53 +02:00
# endif
2006-01-16 22:02:54 +01:00
2006-12-28 23:31:33 +01:00
// Load Automation scripts
global_scripts = new Automation4 : : AutoloadScriptManager ( Options . AsText ( _T ( " Automation Autoload Path " ) ) ) ;
2006-01-16 22:02:54 +01:00
// Load export filters
AssExportFilterChain : : PrepareFilters ( ) ;
// Set association
2007-04-02 20:28:09 +02:00
# ifndef DEBUG
2006-01-16 22:02:54 +01:00
RegistryAssociate ( ) ;
2007-04-02 20:28:09 +02:00
# endif
2006-01-16 22:02:54 +01:00
// Get parameter subs
wxArrayString subs ;
for ( int i = 1 ; i < argc ; i + + ) {
subs . Add ( argv [ i ] ) ;
}
// Open main frame
frame = new FrameMain ( subs ) ;
SetTopWindow ( frame ) ;
}
2006-04-14 18:46:38 +02:00
catch ( const wchar_t * err ) {
2006-01-16 22:02:54 +01:00
wxMessageBox ( err , _T ( " Fatal error while initializing " ) ) ;
return false ;
}
catch ( . . . ) {
wxMessageBox ( _T ( " Unhandled exception " ) , _T ( " Fatal error while initializing " ) ) ;
return false ;
}
return true ;
}
2007-01-15 06:38:32 +01:00
////////
// Exit
int AegisubApp : : OnExit ( ) {
2007-01-15 07:56:35 +01:00
SubtitleFormat : : DestroyFormats ( ) ;
2007-01-21 07:30:19 +01:00
VideoContext : : Clear ( ) ;
2007-01-15 06:38:32 +01:00
Options . Clear ( ) ;
2007-01-15 07:56:35 +01:00
delete global_scripts ;
2007-01-15 06:38:32 +01:00
return wxApp : : OnExit ( ) ;
}
2006-02-26 23:45:34 +01:00
# ifndef _DEBUG
2006-01-16 22:02:54 +01:00
///////////////////////
// Unhandled exception
void AegisubApp : : OnUnhandledException ( ) {
2006-02-21 06:26:13 +01:00
// Attempt to recover file
2006-07-07 01:20:30 +02:00
wxFileName origfile ( AssFile : : top - > filename ) ;
wxString path = Options . AsText ( _T ( " Auto recovery path " ) ) ;
if ( path . IsEmpty ( ) ) path = folderName ;
wxFileName dstpath ( path ) ;
if ( ! dstpath . IsAbsolute ( ) ) path = AegisubApp : : folderName + path ;
path + = _T ( " / " ) ;
dstpath . Assign ( path ) ;
if ( ! dstpath . DirExists ( ) ) wxMkdir ( path ) ;
wxString filename = folderName + origfile . GetName ( ) + _T ( " .RECOVER.ass " ) ;
2006-01-16 22:02:54 +01:00
AssFile : : top - > Save ( filename , false , false ) ;
2006-02-21 06:26:13 +01:00
// Inform user of crash
2006-01-16 22:02:54 +01:00
wxMessageBox ( _T ( " Aegisub has encountered an unhandled exception error and will terminate now. The subtitles you were working on were saved to \" " ) + filename + _T ( " \" , but they might be corrupt. " ) , _T ( " Unhandled exception " ) , wxOK | wxICON_ERROR , NULL ) ;
}
///////////////////
// Fatal exception
void AegisubApp : : OnFatalException ( ) {
2006-02-21 06:26:13 +01:00
// Attempt to recover file
2006-07-07 01:20:30 +02:00
wxFileName origfile ( AssFile : : top - > filename ) ;
wxString path = Options . AsText ( _T ( " Auto recovery path " ) ) ;
if ( path . IsEmpty ( ) ) path = folderName ;
wxFileName dstpath ( path ) ;
if ( ! dstpath . IsAbsolute ( ) ) path = AegisubApp : : folderName + path ;
path + = _T ( " / " ) ;
dstpath . Assign ( path ) ;
if ( ! dstpath . DirExists ( ) ) wxMkdir ( path ) ;
wxString filename = path + origfile . GetName ( ) + _T ( " .RECOVER.ass " ) ;
2006-01-16 22:02:54 +01:00
AssFile : : top - > Save ( filename , false , false ) ;
2006-02-21 06:26:13 +01:00
// Stack walk
2006-04-13 09:09:27 +02:00
# if wxUSE_STACKWALKER == 1
2006-02-21 06:26:13 +01:00
StackWalker walker ;
walker . WalkFromException ( ) ;
2006-04-13 09:09:27 +02:00
# endif
2006-02-21 06:26:13 +01:00
// Inform user of crash
wxMessageBox ( _T ( " Aegisub has encountered a fatal error and will terminate now. The subtitles you were working on were saved to \" " ) + filename + _T ( " \" , but they might be corrupt. " ) , _T ( " Fatal error " ) , wxOK | wxICON_ERROR , NULL ) ;
}
2006-02-26 23:45:34 +01:00
# endif
2006-02-21 06:26:13 +01:00
////////////////
// Stack walker
2006-04-13 09:09:27 +02:00
# if wxUSE_STACKWALKER == 1
2006-02-21 06:26:13 +01:00
void StackWalker : : OnStackFrame ( const wxStackFrame & frame ) {
wxString dst = wxString : : Format ( _T ( " %03i - 0x%08X: " ) , frame . GetLevel ( ) , frame . GetAddress ( ) ) + frame . GetName ( ) + _T ( " on " ) + frame . GetFileName ( ) + wxString : : Format ( _T ( " :%i " ) , frame . GetLine ( ) ) ;
char temp [ 2048 ] ;
if ( file . is_open ( ) ) {
strcpy ( temp , dst . mb_str ( ) ) ;
file < < temp < < std : : endl ;
}
else wxLogMessage ( dst ) ;
}
StackWalker : : StackWalker ( ) {
file . open ( wxString ( AegisubApp : : folderName + _T ( " /stack.txt " ) ) . mb_str ( ) , std : : ios : : out | std : : ios : : app ) ;
if ( file . is_open ( ) ) {
file < < std : : endl < < " Begining stack dump: \n " ;
}
}
StackWalker : : ~ StackWalker ( ) {
if ( file . is_open ( ) ) {
file < < " End of stack dump. \n \n " ;
file . close ( ) ;
}
2006-01-16 22:02:54 +01:00
}
2006-04-13 09:09:27 +02:00
# endif
2006-01-16 22:02:54 +01:00
//////////////////
// Call main loop
int AegisubApp : : OnRun ( ) {
try {
if ( m_exitOnFrameDelete = = Later ) m_exitOnFrameDelete = Yes ;
return MainLoop ( ) ;
}
catch ( wxString err ) {
wxMessageBox ( err , _T ( " Unhandled exception " ) , wxOK | wxICON_ERROR , NULL ) ;
}
2006-02-20 08:12:01 +01:00
catch ( wxChar * error ) {
wxMessageBox ( error , _T ( " Unhandled exception " ) , wxOK | wxICON_ERROR , NULL ) ;
}
catch ( std : : exception e ) {
wxMessageBox ( wxString ( _T ( " std::exception: " ) ) + wxString ( e . what ( ) , wxConvUTF8 ) , _T ( " Unhandled exception " ) , wxOK | wxICON_ERROR , NULL ) ;
2006-01-16 22:02:54 +01:00
}
catch ( . . . ) {
wxMessageBox ( _T ( " Program terminated in error. " ) , _T ( " Unhandled exception " ) , wxOK | wxICON_ERROR , NULL ) ;
}
ExitMainLoop ( ) ;
return 1 ;
}
/////////////////////////////////
// Registry program to filetypes
void AegisubApp : : RegistryAssociate ( ) {
2006-05-10 02:33:44 +02:00
# ifdef __WINDOWS__
2006-01-16 22:02:54 +01:00
// Command to open with this
wxString command ;
command < < _T ( " \" " ) < < fullPath < < _T ( " \" \" %1 \" " ) ;
// Main program association
2007-01-19 13:52:02 +01:00
# ifndef DEBUG
wxRegKey * key = new wxRegKey ( _T ( " HKEY_CURRENT_USER \\ Software \\ Classes \\ Aegisub " ) ) ;
2006-01-16 22:02:54 +01:00
if ( ! key - > Exists ( ) ) key - > Create ( ) ;
key - > SetValue ( _T ( " " ) , _T ( " Aegisub Subtitle Script " ) ) ;
delete key ;
2007-01-19 13:52:02 +01:00
key = new wxRegKey ( _T ( " HKEY_CURRENT_USER \\ Software \\ Classes \\ Aegisub \\ DefaultIcon " ) ) ;
2006-01-16 22:02:54 +01:00
if ( ! key - > Exists ( ) ) key - > Create ( ) ;
2007-01-19 13:52:02 +01:00
key - > SetValue ( _T ( " " ) , fullPath ) ;
2006-01-16 22:02:54 +01:00
delete key ;
2007-01-19 13:52:02 +01:00
key = new wxRegKey ( _T ( " HKEY_CURRENT_USER \\ Software \\ Classes \\ Aegisub \\ Shell " ) ) ;
2006-01-16 22:02:54 +01:00
if ( ! key - > Exists ( ) ) key - > Create ( ) ;
2007-01-19 13:52:02 +01:00
key - > SetValue ( _T ( " " ) , _T ( " open " ) ) ;
2006-01-16 22:02:54 +01:00
delete key ;
2007-01-19 13:52:02 +01:00
key = new wxRegKey ( _T ( " HKEY_CURRENT_USER \\ Software \\ Classes \\ Aegisub \\ Shell \\ Open " ) ) ;
2006-01-16 22:02:54 +01:00
if ( ! key - > Exists ( ) ) key - > Create ( ) ;
2007-01-19 13:52:02 +01:00
key - > SetValue ( _T ( " " ) , _T ( " &Open with Aegisub " ) ) ;
2006-01-16 22:02:54 +01:00
delete key ;
2007-01-19 13:52:02 +01:00
key = new wxRegKey ( _T ( " HKEY_CURRENT_USER \\ Software \\ Classes \\ Aegisub \\ Shell \\ Open \\ Command " ) ) ;
2006-01-16 22:02:54 +01:00
if ( ! key - > Exists ( ) ) key - > Create ( ) ;
2007-01-19 13:52:02 +01:00
key - > SetValue ( _T ( " " ) , command ) ;
2006-01-16 22:02:54 +01:00
delete key ;
2007-01-19 13:52:02 +01:00
# endif
2006-01-16 22:02:54 +01:00
// Check associations
if ( Options . AsBool ( _T ( " Show associations " ) ) ) {
bool gotAll = DialogAssociations : : CheckAssociation ( _T ( " ass " ) ) & & DialogAssociations : : CheckAssociation ( _T ( " ssa " ) ) & & DialogAssociations : : CheckAssociation ( _T ( " srt " ) ) ;
if ( ! gotAll ) {
DialogAssociations diag ( NULL ) ;
diag . ShowModal ( ) ;
Options . SetBool ( _T ( " Show associations " ) , false ) ;
Options . Save ( ) ;
}
}
# endif
}
/////////////////////////////
// Gets and stores full path
void AegisubApp : : GetFullPath ( wxString arg ) {
if ( wxIsAbsolutePath ( arg ) ) {
fullPath = arg ;
return ;
}
// Is it a relative path?
wxString currentDir ( wxFileName : : GetCwd ( ) ) ;
if ( currentDir . Last ( ) ! = wxFILE_SEP_PATH ) currentDir + = wxFILE_SEP_PATH ;
wxString str = currentDir + arg ;
if ( wxFileExists ( str ) ) {
fullPath = str ;
return ;
}
// OK, it's neither an absolute path nor a relative path.
// Search PATH.
wxPathList pathList ;
pathList . AddEnvList ( _T ( " PATH " ) ) ;
str = pathList . FindAbsoluteValidPath ( arg ) ;
if ( ! str . IsEmpty ( ) ) {
fullPath = str ;
return ;
}
fullPath = _T ( " " ) ;
return ;
}
///////////////////////////////////
// Gets folder name from full path
void AegisubApp : : GetFolderName ( ) {
2006-06-19 04:57:27 +02:00
# if defined(__WINDOWS__)
2006-01-16 22:02:54 +01:00
folderName = _T ( " " ) ;
wxFileName path ( fullPath ) ;
2006-06-19 04:57:27 +02:00
# elif defined(__APPLE__)
wxFileName path ;
path . AssignHomeDir ( ) ;
path . AppendDir ( _T ( " Library " ) ) ;
path . AppendDir ( _T ( " Application Support " ) ) ;
if ( ! path . DirExists ( ) )
path . Mkdir ( ) ;
path . AppendDir ( _T ( " Aegisub " ) ) ;
if ( ! path . DirExists ( ) )
path . Mkdir ( ) ;
2006-01-16 22:02:54 +01:00
# else
wxFileName path ;
path . AssignHomeDir ( ) ;
path . AppendDir ( _T ( " .aegisub " ) ) ;
if ( ! path . DirExists ( ) )
path . Mkdir ( ) ;
# endif
folderName + = path . GetPath ( wxPATH_GET_VOLUME ) ;
folderName + = _T ( " / " ) ;
}
2007-01-07 23:54:04 +01:00
////////////
// Open URL
void AegisubApp : : OpenURL ( wxString url ) {
wxFileType * type = wxTheMimeTypesManager - > GetFileTypeFromExtension ( _T ( " html " ) ) ;
if ( type ) {
wxString command = type - > GetOpenCommand ( url ) ;
if ( ! command . empty ( ) ) wxExecute ( command ) ;
}
}
2006-06-19 04:57:27 +02:00
////////////////
// Apple events
# ifdef __WXMAC__
void AegisubApp : : MacOpenFile ( const wxString & filename ) {
if ( frame ! = NULL & & ! filename . empty ( ) ) {
frame - > LoadSubtitles ( filename ) ;
wxFileName filepath ( filename ) ;
Options . SetText ( _T ( " Last open subtitles path " ) , filepath . GetPath ( ) ) ;
}
}
# endif
2006-01-16 22:02:54 +01:00
///////////
// Statics
wxString AegisubApp : : fullPath ;
wxString AegisubApp : : folderName ;
///////////////
// Event table
BEGIN_EVENT_TABLE ( AegisubApp , wxApp )
EVT_MOUSEWHEEL ( AegisubApp : : OnMouseWheel )
EVT_KEY_DOWN ( AegisubApp : : OnKey )
END_EVENT_TABLE ( )
/////////////////////
// Mouse wheel moved
void AegisubApp : : OnMouseWheel ( wxMouseEvent & event ) {
wxPoint pt ;
wxWindow * target = wxFindWindowAtPointer ( pt ) ;
2006-02-18 22:55:58 +01:00
if ( target = = frame - > audioBox - > audioDisplay | | target = = frame - > SubsBox ) {
2006-01-16 22:02:54 +01:00
target - > AddPendingEvent ( event ) ;
}
else event . Skip ( ) ;
}
///////////////
// Key pressed
void AegisubApp : : OnKey ( wxKeyEvent & event ) {
2006-03-05 05:31:09 +01:00
//frame->audioBox->audioDisplay->AddPendingEvent(event);
2006-01-16 22:02:54 +01:00
if ( ! event . GetSkipped ( ) ) {
event . Skip ( ) ;
}
}