Show stack trace for internal exceptions
This commit is contained in:
parent
f7cca4c789
commit
7a70ab32c9
|
@ -162,21 +162,21 @@ class AudioFileModel(
|
|||
}
|
||||
} catch (e: InterruptedException) {
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace(System.err);
|
||||
e.printStackTrace(System.err)
|
||||
|
||||
Platform.runLater {
|
||||
Alert(Alert.AlertType.ERROR).apply {
|
||||
headerText = "Error performing lip sync for event '$eventName'."
|
||||
contentText = if (e.message.isNullOrEmpty())
|
||||
// Some exceptions don't have a message
|
||||
"An internal error of type ${e.javaClass.name} occurred."
|
||||
else
|
||||
contentText = if (e is EndUserException)
|
||||
e.message
|
||||
else
|
||||
("An internal error occurred.\n"
|
||||
+ "Please report an issue, including the following information.\n"
|
||||
+ getStackTrace(e))
|
||||
show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
future = executor.submit(wrapperTask)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
package com.rhubarb_lip_sync.rhubarb_for_spine
|
||||
|
||||
// An exception with a human-readable message that can be shown to the end user
|
||||
class EndUserException(message: String): Exception(message)
|
|
@ -15,18 +15,18 @@ class MainModel(private val executor: ExecutorService) {
|
|||
filePathError = getExceptionMessage {
|
||||
animationFileModel = null
|
||||
if (value.isNullOrBlank()) {
|
||||
throw Exception("No input file specified.")
|
||||
throw EndUserException("No input file specified.")
|
||||
}
|
||||
|
||||
val path = try {
|
||||
val trimmed = value.removeSurrounding("\"")
|
||||
Paths.get(trimmed)
|
||||
} catch (e: InvalidPathException) {
|
||||
throw Exception("Not a valid file path.")
|
||||
throw EndUserException("Not a valid file path.")
|
||||
}
|
||||
|
||||
if (!Files.exists(path)) {
|
||||
throw Exception("File does not exist.")
|
||||
throw EndUserException("File does not exist.")
|
||||
}
|
||||
|
||||
animationFileModel = AnimationFileModel(this, path, executor)
|
||||
|
|
|
@ -24,7 +24,7 @@ class RhubarbTask(
|
|||
throw InterruptedException()
|
||||
}
|
||||
if (!Files.exists(audioFilePath)) {
|
||||
throw IllegalArgumentException("File '$audioFilePath' does not exist.");
|
||||
throw EndUserException("File '$audioFilePath' does not exist.");
|
||||
}
|
||||
|
||||
val dialogFile = if (dialog != null) TemporaryTextFile(dialog) else null
|
||||
|
@ -50,7 +50,7 @@ class RhubarbTask(
|
|||
return parseRhubarbResult(resultString)
|
||||
}
|
||||
"failure" -> {
|
||||
throw Exception(message.string("reason"))
|
||||
throw EndUserException(message.string("reason") ?: "Rhubarb failed without reason.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,13 +58,13 @@ class RhubarbTask(
|
|||
process.destroyForcibly()
|
||||
throw e
|
||||
} catch (e: EOFException) {
|
||||
throw Exception("Rhubarb terminated unexpectedly.")
|
||||
throw EndUserException("Rhubarb terminated unexpectedly.")
|
||||
} finally {
|
||||
process.waitFor();
|
||||
}
|
||||
}}
|
||||
|
||||
throw Exception("An unexpected error occurred.")
|
||||
throw EndUserException("Audio file processing terminated in an unexpected way.")
|
||||
}
|
||||
|
||||
private fun parseRhubarbResult(jsonString: String): List<MouthCue> {
|
||||
|
@ -118,7 +118,7 @@ class RhubarbTask(
|
|||
}
|
||||
currentDirectory = currentDirectory.parent
|
||||
}
|
||||
throw Exception("Could not find Rhubarb Lip Sync executable '$rhubarbBinName'."
|
||||
throw EndUserException("Could not find Rhubarb Lip Sync executable '$rhubarbBinName'."
|
||||
+ " Expected to find it in '$guiBinDirectory' or any directory above.")
|
||||
}
|
||||
|
||||
|
|
|
@ -14,16 +14,16 @@ class SpineJson(val filePath: Path) {
|
|||
|
||||
init {
|
||||
if (!Files.exists(filePath)) {
|
||||
throw Exception("File '$filePath' does not exist.")
|
||||
throw EndUserException("File '$filePath' does not exist.")
|
||||
}
|
||||
try {
|
||||
json = Parser().parse(filePath.toString()) as JsonObject
|
||||
} catch (e: Exception) {
|
||||
throw Exception("Wrong file format. This is not a valid JSON file.")
|
||||
throw EndUserException("Wrong file format. This is not a valid JSON file.")
|
||||
}
|
||||
skeleton = json.obj("skeleton") ?: throw Exception("JSON file is corrupted.")
|
||||
val skins = json.obj("skins") ?: throw Exception("JSON file doesn't contain skins.")
|
||||
defaultSkin = skins.obj("default") ?: throw Exception("JSON file doesn't have a default skin.")
|
||||
skeleton = json.obj("skeleton") ?: throw EndUserException("JSON file is corrupted.")
|
||||
val skins = json.obj("skins") ?: throw EndUserException("JSON file doesn't contain skins.")
|
||||
defaultSkin = skins.obj("default") ?: throw EndUserException("JSON file doesn't have a default skin.")
|
||||
validateProperties()
|
||||
}
|
||||
|
||||
|
@ -34,12 +34,12 @@ class SpineJson(val filePath: Path) {
|
|||
|
||||
val imagesDirectoryPath: Path get() {
|
||||
val relativeImagesDirectory = skeleton.string("images")
|
||||
?: throw Exception("JSON file is incomplete: Images path is missing."
|
||||
?: throw EndUserException("JSON file is incomplete: Images path is missing."
|
||||
+ "Make sure to check 'Nonessential data' when exporting.")
|
||||
|
||||
val imagesDirectoryPath = fileDirectoryPath.resolve(relativeImagesDirectory).normalize()
|
||||
if (!Files.exists(imagesDirectoryPath)) {
|
||||
throw Exception("Could not find images directory relative to the JSON file."
|
||||
throw EndUserException("Could not find images directory relative to the JSON file."
|
||||
+ " Make sure the JSON file is in the same directory as the original Spine file.")
|
||||
}
|
||||
|
||||
|
@ -48,12 +48,12 @@ class SpineJson(val filePath: Path) {
|
|||
|
||||
val audioDirectoryPath: Path get() {
|
||||
val relativeAudioDirectory = skeleton.string("audio")
|
||||
?: throw Exception("JSON file is incomplete: Audio path is missing."
|
||||
?: throw EndUserException("JSON file is incomplete: Audio path is missing."
|
||||
+ "Make sure to check 'Nonessential data' when exporting.")
|
||||
|
||||
val audioDirectoryPath = fileDirectoryPath.resolve(relativeAudioDirectory).normalize()
|
||||
if (!Files.exists(audioDirectoryPath)) {
|
||||
throw Exception("Could not find audio directory relative to the JSON file."
|
||||
throw EndUserException("Could not find audio directory relative to the JSON file."
|
||||
+ " Make sure the JSON file is in the same directory as the original Spine file.")
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,7 @@ class SpineJson(val filePath: Path) {
|
|||
val events = json.obj("events") ?: JsonObject()
|
||||
val result = mutableListOf<AudioEvent>()
|
||||
for ((name, value) in events) {
|
||||
if (value !is JsonObject) throw Exception("Invalid event found.")
|
||||
if (value !is JsonObject) throw EndUserException("Invalid event found.")
|
||||
|
||||
val relativeAudioFilePath = value.string("audio") ?: continue
|
||||
|
||||
|
|
|
@ -2,11 +2,10 @@ package com.rhubarb_lip_sync.rhubarb_for_spine
|
|||
|
||||
import javafx.application.Platform
|
||||
import javafx.beans.property.Property
|
||||
import java.util.concurrent.ExecutionException
|
||||
import java.util.concurrent.locks.Condition
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
import kotlin.concurrent.withLock
|
||||
|
||||
import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
|
||||
val List<String>.commonPrefix: String get() {
|
||||
return if (isEmpty()) "" else this.reduce { result, string -> result.commonPrefixWith(string) }
|
||||
|
@ -36,7 +35,6 @@ fun getExceptionMessage(action: () -> Unit): String? {
|
|||
return null
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Invokes a Runnable on the JFX thread and waits until it's finished.
|
||||
* Similar to SwingUtilities.invokeAndWait.
|
||||
|
@ -69,3 +67,9 @@ fun runAndWait(action: () -> Unit) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getStackTrace(e: Exception): String {
|
||||
val stringWriter = StringWriter()
|
||||
e.printStackTrace(PrintWriter(stringWriter))
|
||||
return stringWriter.toString()
|
||||
}
|
Loading…
Reference in New Issue