Merge branch 'bugfix/spine-from-jar'
This commit is contained in:
commit
a3a64d8b5d
|
@ -1,5 +1,11 @@
|
|||
# Version history
|
||||
|
||||
## Unreleased
|
||||
|
||||
* Fixed [issue #34](https://github.com/DanielSWolf/rhubarb-lip-sync/issues/34): Generic error message in Rhubarb for Spine
|
||||
* More helpful error dialogs for internal errors in Rhubarb Lip Sync for Spine
|
||||
* Internal errors in Rhubarb Lip Sync for Spine are logged to stderr
|
||||
|
||||
## Version 1.7.0
|
||||
|
||||
* Integration with Spine animation software
|
||||
|
|
|
@ -162,10 +162,16 @@ class AudioFileModel(
|
|||
}
|
||||
} catch (e: InterruptedException) {
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace(System.err);
|
||||
|
||||
Platform.runLater {
|
||||
Alert(Alert.AlertType.ERROR).apply {
|
||||
headerText = "Error performing lip sync for event '$eventName'."
|
||||
contentText = e.message
|
||||
contentText = if (e.message.isNullOrEmpty())
|
||||
// Some exceptions don't have a message
|
||||
"An internal error of type ${e.javaClass.name} occurred."
|
||||
else
|
||||
e.message
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,8 +10,6 @@ import java.io.*
|
|||
import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import java.time.Duration
|
||||
import java.util.concurrent.Callable
|
||||
|
||||
class RhubarbTask(
|
||||
|
@ -106,12 +104,8 @@ class RhubarbTask(
|
|||
}
|
||||
|
||||
private val guiBinDirectory: Path by lazy {
|
||||
var path: String = ClassLoader.getSystemClassLoader().getResource(".")!!.path
|
||||
if (path.length >= 3 && path[2] == ':') {
|
||||
// Workaround for https://stackoverflow.com/questions/9834776/java-nio-file-path-issue
|
||||
path = path.substring(1)
|
||||
}
|
||||
return@lazy Paths.get(path)
|
||||
val path = urlToPath(getLocation(RhubarbTask::class.java))
|
||||
return@lazy if (Files.isDirectory(path)) path.parent else path
|
||||
}
|
||||
|
||||
private val rhubarbBinFilePath: Path by lazy {
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
package com.rhubarb_lip_sync.rhubarb_for_spine
|
||||
|
||||
import java.io.FileInputStream
|
||||
import java.net.MalformedURLException
|
||||
import java.net.URISyntaxException
|
||||
import java.net.URL
|
||||
import org.apache.commons.lang3.SystemUtils.IS_OS_WINDOWS
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
|
||||
// The following code is adapted from https://stackoverflow.com/a/12733172/52041
|
||||
|
||||
/**
|
||||
* Gets the base location of the given class.
|
||||
*
|
||||
* If the class is directly on the file system (e.g.,
|
||||
* "/path/to/my/package/MyClass.class") then it will return the base directory
|
||||
* (e.g., "file:/path/to").
|
||||
*
|
||||
* If the class is within a JAR file (e.g.,
|
||||
* "/path/to/my-jar.jar!/my/package/MyClass.class") then it will return the
|
||||
* path to the JAR (e.g., "file:/path/to/my-jar.jar").
|
||||
*
|
||||
* @param c The class whose location is desired.
|
||||
*/
|
||||
fun getLocation(c: Class<*>): URL {
|
||||
// Try the easy way first
|
||||
try {
|
||||
val codeSourceLocation = c.protectionDomain.codeSource.location
|
||||
if (codeSourceLocation != null) return codeSourceLocation
|
||||
} catch (e: SecurityException) {
|
||||
// Cannot access protection domain
|
||||
} catch (e: NullPointerException) {
|
||||
// Protection domain or code source is null
|
||||
}
|
||||
|
||||
// The easy way failed, so we try the hard way. We ask for the class
|
||||
// itself as a resource, then strip the class's path from the URL string,
|
||||
// leaving the base path.
|
||||
|
||||
// Get the class's raw resource path
|
||||
val classResource = c.getResource(c.simpleName + ".class")
|
||||
?: throw Exception("Cannot find class resource.")
|
||||
|
||||
val url = classResource.toString()
|
||||
val suffix = c.canonicalName.replace('.', '/') + ".class"
|
||||
if (!url.endsWith(suffix)) throw Exception("Malformed URL.")
|
||||
|
||||
// strip the class's path from the URL string
|
||||
val base = url.substring(0, url.length - suffix.length)
|
||||
|
||||
var path = base
|
||||
|
||||
// remove the "jar:" prefix and "!/" suffix, if present
|
||||
if (path.startsWith("jar:")) path = path.substring(4, path.length - 2)
|
||||
|
||||
return URL(path)
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given URL to its corresponding [Path].
|
||||
*
|
||||
* @param url The URL to convert.
|
||||
* @return A file path suitable for use with e.g. [FileInputStream]
|
||||
*/
|
||||
fun urlToPath(url: URL): Path {
|
||||
var pathString = url.toString()
|
||||
|
||||
if (pathString.startsWith("jar:")) {
|
||||
// Remove "jar:" prefix and "!/" suffix
|
||||
val index = pathString.indexOf("!/")
|
||||
pathString = pathString.substring(4, index)
|
||||
}
|
||||
|
||||
try {
|
||||
if (IS_OS_WINDOWS && pathString.matches("file:[A-Za-z]:.*".toRegex())) {
|
||||
pathString = "file:/" + pathString.substring(5)
|
||||
}
|
||||
return Paths.get(URL(pathString).toURI())
|
||||
} catch (e: MalformedURLException) {
|
||||
// URL is not completely well-formed.
|
||||
} catch (e: URISyntaxException) {
|
||||
// URL is not completely well-formed.
|
||||
}
|
||||
|
||||
if (pathString.startsWith("file:")) {
|
||||
// Pass through the URL as-is, minus "file:" prefix
|
||||
pathString = pathString.substring(5)
|
||||
return Paths.get(pathString)
|
||||
}
|
||||
throw IllegalArgumentException("Invalid URL: $url")
|
||||
}
|
Loading…
Reference in New Issue