001 ///////////////////////////////////////////////// 002 // This file is part of Sears project. 003 // Subtitle Editor And Re-Synch 004 // A tool to easily modify and resynch movies subtitles. 005 ///////////////////////////////////////////////// 006 //This program is free software; 007 //you can redistribute it and/or modify it under the terms 008 //of the GNU General Public License 009 //as published by the Free Software Foundation; 010 //either version 2 of the License, or (at your option) any later version. 011 ///////////////////////////////////////////////// 012 //Sears project is available under sourceforge 013 // at adress: http://sourceforge.net/projects/sears/ 014 //Copyright (C) 2005 Booba Skaya 015 //Mail: booba.skaya@gmail.com 016 // 017 // $Id: Main.java,v 1.6 2007/02/20 19:45:35 booba_skaya Exp $ 018 //////////////////////////////////////////////// 019 020 package sears.main; 021 import java.io.File; 022 import java.util.ArrayList; 023 import sears.file.SrtFile; 024 import sears.file.Subtitle; 025 import sears.file.SubtitleFile; 026 import sears.gui.MainWindow; 027 import sears.tools.Trace; 028 029 /** 030 * Class Main. 031 * <br><b>Summary:</b><br> 032 * This is the main class. 033 * It contains the main method that launches the Sears GUI or the inline commands. 034 */ 035 public class Main { 036 /**The delay action*/ 037 private static String KEY_DELAY = "delay"; 038 /**The resynch action*/ 039 private static String KEY_RESYNCHRO = "resyn"; 040 /**The split action*/ 041 private static String KEY_SPLIT = "split"; 042 /**The append action*/ 043 private static String KEY_APPEND = "appen"; 044 045 /** The NEWLINE String, for this OS. */ 046 private static final String NEWL = System.getProperty("line.separator"); 047 048 /** The usage, that will displayed if user fails to enter correct parameters.*/ 049 private static String USAGE = "Sears"+NEWL 050 +"DESCRIPTION:"+NEWL 051 +"SEARS is a Subtitle Editor And Re-Synchroniser."+NEWL 052 +"USAGE:"+NEWL 053 +"java -jar sears.jar [action ActionParameters]"+NEWL 054 +"ACTIONS:"+NEWL 055 +"-delay:"+NEWL 056 +" java -jar sears.jar "+KEY_DELAY+" d input_file [output_file]"+NEWL 057 +" will delay the input's file subtitle using the given integer delay d."+NEWL 058 +" result will be write in the input_file, or in output_file, if output_file is given."+NEWL 059 +"-resyn:"+NEWL 060 +" java -jar sears.jar "+KEY_RESYNCHRO+" src1 dest1 src2 dest2 input_file [output_file]"+NEWL 061 +" will apply a resynchro to given input file."+NEWL 062 +" src and dest must be precised under format HH:MM:SS.MMM"+NEWL 063 +" result will be write in the input_file, or in output_file, if output_file is given."+NEWL 064 +"-split:"+NEWL 065 +" java -jar sears.jar "+KEY_SPLIT+" index input_file output_file1 output_file2"+NEWL 066 +" will apply a split to given input file."+NEWL 067 +" It will cut the input file at subtitle which index is given."+NEWL 068 +" result will be write in the 2 output files output_file1 and output_file2."+NEWL 069 +"-append:"+NEWL 070 +" java -jar sears.jar "+KEY_APPEND+" d input_file1 input_file2 [output_file]"+NEWL 071 +" will apply a append to given input file."+NEWL 072 +" It will append the subtitle of input_file2 with a delay of d."+NEWL 073 +" result will be write in the input_file, or in output_file, if output_file is given."+NEWL 074 +""+NEWL 075 +""+NEWL; 076 077 /**The inputSubtitleFile.*/ 078 private static SubtitleFile inputSubtitleFile; 079 /**The outputFile.*/ 080 private static File outputFile; 081 082 083 /** 084 * Method main. 085 * <br><b>Summary:</b><br> 086 * This is the method that launches the Sears main GUI. 087 * @param args Arguments. Sears can take arguments to make inline operations. 088 * arguments syntax is: 089 * java.Main.main [actionKey] [action's parameters] 090 * 091 */ 092 public static void main(String[] args) { 093 if(args.length == 0){ 094 launchMainWindow(null); 095 }else{ 096 String actionKey = args[0]; 097 //Check for an action key word. 098 if(actionKey.equals(KEY_DELAY)){ 099 delayAction(args); 100 System.out.println("Delay performed."); 101 }else if(actionKey.equals(KEY_RESYNCHRO)){ 102 resynchroAction(args); 103 System.out.println("Resynchro performed."); 104 }else if(actionKey.equals(KEY_SPLIT)){ 105 splitAction(args); 106 System.out.println("Split performed."); 107 }else if(actionKey.equals(KEY_APPEND)){ 108 appendAction(args); 109 System.out.println("Append performed."); 110 }else if(args[0].endsWith(".srt")){ 111 launchMainWindow(args[0]); 112 }else{ 113 //If not action key word has benn recognized, displayUsage. 114 displayUsage(); 115 } 116 } 117 } 118 119 120 /** 121 * Method launchMainWindow. 122 * <br><b>Summary:</b><br> 123 * This method permits to launch a Sears mainWindows, with an opened file. 124 * @param file The file to open, or null if no file is to be opened. 125 */ 126 private static void launchMainWindow(String file) { 127 //if Sears are launched on Mac OS: 128 if(System.getProperty("mrj.version") != null){ 129 // set the menu bar on the top of the screen, 130 // if default style "apple.laf.AquaLookAndFeel" has changed by user, 131 // the menu bar returns on the top of the main JFrame. 132 System.setProperty( "apple.laf.useScreenMenuBar", "true" ); 133 // others properties: 134 System.setProperty( "apple.awt.showGrowBox", "true" ); 135 System.setProperty("apple.awt.textantialiasing" , "true"); 136 } 137 Trace.trace("Constructing main window", Trace.ALGO_PRIORITY); 138 MainWindow mainWindow = new MainWindow(); 139 mainWindow.setVisible(true); 140 //If a file has been given open it. 141 if(file != null){ 142 mainWindow.openFile(new File(file)); 143 } 144 } 145 146 147 /** 148 * Method <b>displayUsage</b> 149 * <br><b>Summary:</b><br> 150 * This method display the Searc command line usage. 151 */ 152 private static void displayUsage() { 153 System.out.println(USAGE); 154 } 155 156 157 /** 158 * Method <b>appendAction</b> 159 * <br><b>Summary:</b><br> 160 * This method is called to perform an append action. 161 * Must have at least 4 parameters. 162 * appen d input_file1 input_file2 [output_file] 163 * will apply a append to given input file. 164 * It will append the subtitle of input_file2 with a delay of d. 165 * result will be write in the input_file, or in output_file, if output_file is given. 166 * Parameters: 167 * @param args The command line arguments. 168 * 169 */ 170 private static void appendAction(String[] args) { 171 Trace.trace("Append action.", Trace.MESSAGE_PRIORITY); 172 //Split must have at least 4 parameters 173 String errorMessage = ""; 174 if(args.length >= 4){ 175 double delay =0; 176 SubtitleFile fileToAppend = null; 177 try{ 178 //get the delay. 179 delay = Double.parseDouble(args[1]); 180 //open the file to append, it will be save temporally in inputSubtitleFile. 181 errorMessage += openInputFile(args[3]); 182 //save it. 183 fileToAppend = inputSubtitleFile; 184 //open the src file. 185 errorMessage += openInputFile(args[2]); 186 //If outputfile is precised, read it. 187 if(args.length >= 5){ 188 errorMessage += openOutputFile(args[4]); 189 } 190 }catch (NumberFormatException e){ 191 errorMessage += "Delay must be a number."+NEWL; 192 } 193 //If there is no error, proceed to resynchro. 194 if(errorMessage != null && errorMessage.equals("")){ 195 Trace.trace("Proceed to Append: with delay "+ delay +" on file : "+inputSubtitleFile.getFile(), Trace.MESSAGE_PRIORITY); 196 //delay * 1000 because delay is in seconds, with milliseconds. 197 inputSubtitleFile.append(fileToAppend, (int) (delay*1000)); 198 if(outputFile != null){ 199 Trace.trace("Write result to: "+outputFile, Trace.MESSAGE_PRIORITY); 200 inputSubtitleFile.writeToFile(outputFile); 201 }else{ 202 Trace.trace("Write result to: "+inputSubtitleFile.getFile(), Trace.MESSAGE_PRIORITY); 203 inputSubtitleFile.writeToFile(inputSubtitleFile.getFile()); 204 } 205 } 206 }else{ 207 errorMessage += "Append action command must have at least 4 arguments."+NEWL+"appen d input_file1 input_file2 [output_file]"; 208 } 209 if(errorMessage != null && !errorMessage.equals("")){ 210 displayErrorMessage(errorMessage); 211 } 212 213 } 214 215 216 /** 217 * Method <b>splitAction</b> 218 * <br><b>Summary:</b><br> 219 * java -jar sears.jar split index input_file output_file1 output_file2 220 * will apply a split to given input file. 221 * It must have at least 5 parameters. 222 * Parameters: 223 * @param args The command line arguments. 224 * 225 */ 226 private static void splitAction(String[] args) { 227 Trace.trace("Split action.", Trace.MESSAGE_PRIORITY); 228 //Split must have at least 5 parameters 229 String errorMessage = ""; 230 if(args.length >= 5){ 231 int index =0; 232 File[] destinationFiles = new File[2]; 233 try{ 234 //get the index. 235 index = Integer.parseInt(args[1]); 236 //open the input file. 237 errorMessage += openInputFile(args[2]); 238 //open first output file 239 errorMessage += openOutputFile(args[3]); 240 //save it. 241 destinationFiles[0] = outputFile; 242 //open second outputFile 243 errorMessage += openOutputFile(args[4]); 244 destinationFiles[1] = outputFile; 245 }catch (NumberFormatException e){ 246 errorMessage += "Index must be a number."+NEWL; 247 } 248 //If there is no error, proceed to resynchro. 249 if(errorMessage != null && errorMessage.equals("")){ 250 Trace.trace("Proceed to Split: At index "+ index +" on file : "+inputSubtitleFile.getFile(), Trace.MESSAGE_PRIORITY); 251 SubtitleFile[] resultFiles = inputSubtitleFile.split(destinationFiles, (index-1), 1); 252 //save result files. 253 resultFiles[0].writeToFile(resultFiles[0].getFile()); 254 resultFiles[1].writeToFile(resultFiles[1].getFile()); 255 } 256 }else{ 257 errorMessage += "Split action command must have at least 5 arguments."+NEWL+"split index input_file output_file1 output_file2"; 258 } 259 if(errorMessage != null && !errorMessage.equals("")){ 260 displayErrorMessage(errorMessage); 261 } 262 } 263 264 265 /** 266 * Method <b>resynchroAction</b> 267 * <br><b>Summary:</b><br> 268 * This method is called to perform a resynchro action. 269 * Must have at least 6 parameters: 270 * resynch src1 dest1 src2 dest2 input_file [output_file] 271 * src and dest must be precised under format HH:MM:SS. 272 * result will be write in the input_file, or in output_file, if output_file is given. 273 * Parameters: 274 * @param args The command line arguments. 275 * 276 */ 277 private static void resynchroAction(String[] args) { 278 Trace.trace("Resynchro action.", Trace.MESSAGE_PRIORITY); 279 //Resynch must have at least 6 parameters. 280 String errorMessage = ""; 281 if(args.length >= 6){ 282 int[] resynchParameters = new int[4]; 283 try{ 284 //get source and destinations. 285 resynchParameters[0] = SubtitleFile.stringToTime(args[1]); 286 resynchParameters[1] = SubtitleFile.stringToTime(args[2]); 287 resynchParameters[2] = SubtitleFile.stringToTime(args[3]); 288 resynchParameters[3] = SubtitleFile.stringToTime(args[4]); 289 //open the input file. 290 errorMessage += openInputFile(args[5]); 291 //If outputfile is precised, read it. 292 if(args.length >= 7){ 293 errorMessage += openOutputFile(args[6]); 294 } 295 }catch (NumberFormatException e){ 296 errorMessage += "Source and destination times must be under HH:MM:SS.MMM format."+NEWL; 297 } 298 //If there is no error, proceed to resynchro. 299 if(errorMessage != null && errorMessage.equals("")){ 300 Trace.trace("Proceed to Resynch: on file : "+inputSubtitleFile.getFile(), Trace.MESSAGE_PRIORITY); 301 inputSubtitleFile.resynchro(resynchParameters); 302 if(outputFile != null){ 303 Trace.trace("Write result to: "+outputFile, Trace.MESSAGE_PRIORITY); 304 inputSubtitleFile.writeToFile(outputFile); 305 }else{ 306 Trace.trace("Write result to: "+inputSubtitleFile.getFile(), Trace.MESSAGE_PRIORITY); 307 inputSubtitleFile.writeToFile(inputSubtitleFile.getFile()); 308 } 309 } 310 311 312 }else{ 313 errorMessage += "Resynchro action command must have at least 6 arguments."+NEWL+"resyn src1 dest1 src2 dest2 input_file [output_file]"; 314 } 315 if(errorMessage != null && !errorMessage.equals("")){ 316 displayErrorMessage(errorMessage); 317 } 318 } 319 320 321 /** 322 * Method <b>delayAction</b> 323 * <br><b>Summary:</b><br> 324 * This method is called to perform a delay action. 325 * Delay action command must have at least 3 arguments. 326 * delay d input_file [output_file] 327 * d is the delay to apply, an integer. 328 * input_file is the file to perform the delay. 329 * [output_file] optionnal, if precised, action will be saved here. 330 * Parameters: 331 * @param args The command line arguments. 332 * 333 */ 334 private static void delayAction(String[] args) { 335 Trace.trace("Delay action.", Trace.MESSAGE_PRIORITY); 336 //Delay action command must have at least 3 arguments. 337 //if not display message error. 338 String errorMessage = ""; 339 //must have at least 3 parameter for a delay. 340 if(args.length >= 3){ 341 try{ 342 //Get the delay to apply. 343 double delay = Double.parseDouble(args[1]); 344 //open the input file. 345 errorMessage += openInputFile(args[2]); 346 //If outputfile is precised, read it. 347 if(args.length >= 4){ 348 errorMessage += openOutputFile(args[3]); 349 } 350 if(errorMessage != null && errorMessage.equals("")){ 351 Trace.trace("Proceed to Delay: delay "+delay+ " on file : "+inputSubtitleFile.getFile(), Trace.MESSAGE_PRIORITY); 352 //delay * 1000 because delay is in seconds, with milliseconds. 353 inputSubtitleFile.delay((int)(delay*1000)); 354 if(outputFile != null){ 355 Trace.trace("Write result to: "+outputFile, Trace.MESSAGE_PRIORITY); 356 inputSubtitleFile.writeToFile(outputFile); 357 }else{ 358 Trace.trace("Write result to: "+inputSubtitleFile.getFile(), Trace.MESSAGE_PRIORITY); 359 inputSubtitleFile.writeToFile(inputSubtitleFile.getFile()); 360 } 361 } 362 }catch(NumberFormatException e){ 363 errorMessage += "Must enter an integer delay"; 364 } 365 366 }else{ 367 errorMessage += "Delay action command must have at least 3 arguments."+NEWL+"delay d input_file [output_file]"; 368 } 369 if(errorMessage != null && !errorMessage.equals("")){ 370 displayErrorMessage(errorMessage); 371 } 372 } 373 374 375 /** 376 * Method <b>openOutputFile</b> 377 * <br><b>Summary:</b><br> 378 * This method open the given file. 379 * Store it in output file. 380 * Parameters: 381 * @param file The file to open. 382 * @return <b>String</b> The error message, or "" if no error has been found. 383 */ 384 private static String openOutputFile(String file) { 385 //The result of the Method 386 String message =""; 387 //Construct file 388 File output = new File(file); 389 //check that file could be opened. 390 if(output.exists() && !output.canWrite()){ 391 message += "File "+file+" can not be written."+NEWL; 392 }else{ 393 outputFile = output; 394 } 395 //return the error message. 396 return message; 397 } 398 399 400 /** 401 * Method <b>openInputFile</b> 402 * <br><b>Summary:</b><br> 403 * This method open the given file. 404 * Store it in input file. 405 * Parameters: 406 * @param file The file to open. 407 * @return <b>String</b> The error message, or "" if no error has been found. 408 * 409 */ 410 private static String openInputFile(String file) { 411 //The result of the Method 412 String message =""; 413 //Construct file 414 File inputFile = new File(file); 415 //check that file could be opened. 416 if(!inputFile.canRead()){ 417 message += "File "+file+" can not be read."+NEWL; 418 } 419 //Construct subtitleFile 420 inputSubtitleFile = new SrtFile(inputFile, new ArrayList<Subtitle>()); 421 //return the error message. 422 return message; 423 } 424 425 426 /** 427 * Method <b>displayErrorMessage</b> 428 * <br><b>Summary:</b><br> 429 * This method display an error. 430 * Parameters: 431 * @param error The error to display. 432 * 433 */ 434 private static void displayErrorMessage(String error) { 435 System.out.println("Error : "+NEWL+error+NEWL); 436 } 437 } 438