package com.soundlooper.system;
import java.io.File;
import java.io.IOException;
import java.util.Optional;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.ButtonType;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.kohsuke.github.GHIssue;
import com.soundlooper.exception.AlreadyLockedException;
import com.soundlooper.exception.PlayerException;
import com.soundlooper.exception.SoundLooperRuntimeException;
import com.soundlooper.model.SoundLooperPlayer;
import com.soundlooper.model.database.ConnectionFactory;
import com.soundlooper.system.preferences.Preferences;
import com.soundlooper.system.util.IssueSender;
import com.soundlooper.system.util.Lock;
import com.soundlooper.system.util.MessagingUtil;
public class SoundLooper extends Application {
private static final String LOCK_NAME = ".lock";
private static Stage primaryStage;
private BorderPane rootLayout;
private static SoundLooper instance;
private SystemController controller;
private static Logger logger = LogManager.getLogger(SoundLooper.class);
@Override
public void start(Stage primaryStage) throws Exception {
logger.info("----- Application start -------");
Thread.setDefaultUncaughtExceptionHandler(SoundLooper::onException);
primaryStage.getIcons().add(ImageGetter.getSoundLooper64().getImage());
primaryStage.setMinWidth(750);
primaryStage.setMinHeight(375);
instance = this;
SoundLooper.primaryStage = primaryStage;
SoundLooper.primaryStage.setTitle("Sound Looper");
primaryStage.setOnCloseRequest(e -> {
logger.info("On close request");
onWindowClose();
logger.info("After window close");
Platform.exit();
logger.info("After platform exit");
try {
Lock.unlock(SoundLooper.LOCK_NAME);
} catch (IOException e1) {
logger.error("Unable to remove lock '" + SoundLooper.LOCK_NAME + "'", e);
}
logger.info("After unlock");
System.exit(0);
logger.info("After system exit");
});
SoundLooperPlayer.getInstance().initialize();
SoundLooper.initializePreference();
SoundLooper.initializeDatabase();
initRootLayout();
}
private static void onException(Thread t, Throwable e) {
logger.error("An uncauch exception is detected on the thread " + t.getName() + " : " + e, e);
Alert alert = new Alert(AlertType.ERROR, "Souhaitez-vous envoyer un rapport d'erreur ?", ButtonType.OK,
ButtonType.CANCEL);
alert.initOwner(primaryStage);
alert.setTitle("Erreur critique");
alert.setHeaderText("Une erreur inattendue est survenue");
Optional<ButtonType> result = alert.showAndWait();
if (result.get() == ButtonType.OK) {
logger.info("User want to create a github issue");
GHIssue issue = IssueSender.sendIssue(e);
logger.info("Issue " + issue.getNumber() + " created");
Alert issueConfirmationAlert = new Alert(AlertType.INFORMATION, "Le ticket de bug num�ro '"
+ issue.getNumber() + "' a bien �t� cr��");
issueConfirmationAlert.setTitle("Cr�ation du rapport d'erreur");
issueConfirmationAlert.setHeaderText("Le rapport d'erreur a �t� envoy� avec succ�s");
issueConfirmationAlert.initOwner(primaryStage);
issueConfirmationAlert.showAndWait();
} else {
logger.info("User doesn't want to create a github issue");
}
}
public void onWindowClose() {
primaryStage.hide();
try {
SoundLooperPlayer.getInstance().desallocate();
} catch (PlayerException e) {
logger.error("Unable to desallocate player", e);
}
Preferences.getInstance().save();
SoundLooperPlayer.getInstance().purgeSong();
}
public void initRootLayout() {
try {
logger.info("Init the root layout");
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setResources(MessageReader.getInstance().getBundle());
loader.setLocation(SoundLooper.class.getResource("/gui/RootLayout.fxml"));
rootLayout = (BorderPane) loader.load();
controller = (SystemController) loader.getController();
controller.init();
File lastFile = new File(Preferences.getInstance().getLastPathUsed());
if (lastFile.exists()) {
try {
SoundLooperPlayer.getInstance().loadSong(lastFile);
MessagingUtil.displayMessage("Fichier '" + lastFile.getAbsolutePath() + " charg�");
} catch (PlayerException e) {
MessagingUtil.displayError("Impossible de charger la chanson " + lastFile, e);
}
}
// Show the scene containing the root layout.
Scene scene = new Scene(rootLayout);
scene.getStylesheets().add("/style/application.css");
// Light light = new Light.Point(, 40, 300, Color.WHITE);
// Lighting lighting = new Lighting();
// lighting.setLight(light);
// scene.getRoot().setEffect(lighting);
primaryStage.setScene(scene);
primaryStage.setAlwaysOnTop(Preferences.getInstance().getAlwaysOnTop());
controller.initShortcut();
primaryStage.show();
} catch (IOException e) {
throw new SoundLooperRuntimeException("Unable to load the root layout", e);
}
}
public static void main(String[] args) throws AlreadyLockedException, IOException {
logger.info("Launch with arguments : " + StringUtils.join(args));
if (containsArg(args, "-uninstall")) {
logger.info("Uninstall, nothing to do");
return;
}
Lock.lock(SoundLooper.LOCK_NAME);
launch(args);
}
private static boolean containsArg(String[] args, String string) {
for (String arg : args) {
if (StringUtils.equals(arg, string)) {
return true;
}
}
return false;
}
public Stage getPrimaryStage() {
return primaryStage;
}
public static SoundLooper getInstance() {
return instance;
}
/**
* Initialize the database
*/
private static void initializeDatabase() {
SoundLooper.logger.info("Start database initialisation");
ConnectionFactory.updateDB();
ConnectionFactory.getNewStatement();
SoundLooper.logger.info("End database initialisation");
}
/**
* Initialize the preference
*/
private static void initializePreference() {
// init the properties
SoundLooper.logger.info("Start properties initialisation");
Preferences.getInstance();
SoundLooper.logger.info("End properties initialisation");
}
public SystemController getController() {
return controller;
}
}