diff --git a/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/MerLTLReader.kt b/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/MerLTLReader.kt index 0e38330..0761bb0 100644 --- a/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/MerLTLReader.kt +++ b/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/MerLTLReader.kt @@ -1,37 +1,75 @@ package jp.zero_x_d.workaholic.merltlreader -import jp.zero_x_d.workaholic.merltlreader.app.CLIApp -import jp.zero_x_d.workaholic.merltlreader.app.ILTLReaderApp +import com.sys1yagi.mastodon4j.api.entity.Status +import javafx.application.Application import jp.zero_x_d.workaholic.merltlreader.app.guifallback.GUIApp +import jp.zero_x_d.workaholic.merltlreader.engine.ITTSEngine +import jp.zero_x_d.workaholic.merltlreader.status.readContent +import jp.zero_x_d.workaholic.merltlreader.status.readName import net.harawata.appdirs.AppDirsFactory +import org.luaj.vm2.LuaError import java.io.File object MerLTLReader { val appName = "MerLTLReader" private val appVersion = "alpha" - private val appAuthor = "called.0xd" + private val appAuthor = "called_D" - private var instance: ILTLReaderApp? = null - val appInstance: ILTLReaderApp - get() = requireNotNull(instance) + val appDir by lazy { + AppDirsFactory + .getInstance() + .getUserConfigDir(appName, appVersion, appAuthor) + .let { + File(it).apply { if (!exists()) mkdirs() } + } + } - val preferences: Preferences - get() = requireNotNull(appInstance?.preferences) + var preferences: Preferences? = null + val onStatus = mutableListOf<(Status) -> Unit>({ status -> + println(status.readContent) + }) - val appDir by lazy { - AppDirsFactory.getInstance().getUserConfigDir(appName, appVersion, appAuthor).let { - File(it).apply { if (!exists()) mkdirs() } + @JvmStatic fun main(args: Array) { + preferences = Preferences.fromArgs(*args) + if (System.console() == null) { + Application.launch(GUIApp::class.java, *args) + } else { + launch(*args) } } - @JvmStatic fun main(arg: Array) { - instance = if (System.console() != null) { - CLIApp() - } else { // Fallback code - GUIApp() + private fun launch(vararg arg: String) { + val credentials = + Credentials.Builder(preferences!!) + .loadOrAppRegister().loadOrLogin { + mailPass = login(preferences) + } + val tl = Timeline(credentials) + val tts = ITTSEngine.getEngineFromPreferences(preferences!!) + + runWithTTS(tl, tts) + } + + fun runWithTTS(tl: Timeline, tts: ITTSEngine) { + for (status in tl) { + try { + onStatus.forEach { it(status) } + status.readName?.let { tts.say_username(it) } + status.readContent?.let { tts.say_content(it) } + } catch (e: LuaError) { + e.printStackTrace() + tts.say("るあえらーが発生しました") + } } - instance!!.launch(*arg) + } + + private fun login(preferences: Preferences): LoginData { + print("login for " + preferences.instance_url) + val console = requireNotNull(System.console()) + val mail = console.readLine("mail: ")?.toString() + val pass = console.readPassword("password for %s: ", mail)?.toString() + return LoginData(requireNotNull(mail), requireNotNull(pass)) } } diff --git a/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/Preferences.kt b/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/Preferences.kt index 6c901a1..bcfaa84 100644 --- a/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/Preferences.kt +++ b/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/Preferences.kt @@ -3,13 +3,25 @@ package jp.zero_x_d.workaholic.merltlreader import com.sys1yagi.mastodon4j.api.Scope import java.io.File import jp.zero_x_d.workaholic.merltlreader.MerLTLReader.appDir +import jp.zero_x_d.workaholic.merltlreader.engine.ITTSEngine.Engines data class Preferences( val instance_url: String, - val scope: Scope = Scope(Scope.Name.ALL) + val scope: Scope = Scope(Scope.Name.ALL), + val tts_engine: Engines = Engines.AUTO ) { val dir: File get() = File(appDir, instance_url).apply { if (!exists()) mkdir() } + + companion object { + fun fromArgs(vararg args: String): Preferences { + // TODO process args for preferences + + return Preferences( + "mstdn-workers.com" + ) + } + } } \ No newline at end of file diff --git a/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/app/CLIApp.kt b/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/app/CLIApp.kt deleted file mode 100644 index 312e067..0000000 --- a/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/app/CLIApp.kt +++ /dev/null @@ -1,26 +0,0 @@ -package jp.zero_x_d.workaholic.merltlreader.app - -import com.sys1yagi.mastodon4j.api.entity.Status -import jp.zero_x_d.workaholic.merltlreader.LoginData -import jp.zero_x_d.workaholic.merltlreader.Preferences -import jp.zero_x_d.workaholic.merltlreader.status.readContent - -class CLIApp: ILTLReaderApp { - override var preferences: Preferences? = null - - - override fun launch(vararg args: String) { - run(*args) - } - - override fun login(): LoginData { - val console = requireNotNull(System.console()) - val mail = console.readLine("mail: ")?.toString() - val pass = console.readPassword("password for %s: ", mail)?.toString() - return LoginData(requireNotNull(mail), requireNotNull(pass)) - } - - override fun onStatus(stats: Status) { - println(stats.readContent) - } -} \ No newline at end of file diff --git a/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/app/ILTLReaderApp.kt b/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/app/ILTLReaderApp.kt deleted file mode 100644 index ea32254..0000000 --- a/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/app/ILTLReaderApp.kt +++ /dev/null @@ -1,41 +0,0 @@ -package jp.zero_x_d.workaholic.merltlreader.app - -import com.sys1yagi.mastodon4j.api.entity.Status -import jp.zero_x_d.workaholic.merltlreader.* -import jp.zero_x_d.workaholic.merltlreader.engine.ITTSEngine -import jp.zero_x_d.workaholic.merltlreader.engine.JTalkConnecter -import jp.zero_x_d.workaholic.merltlreader.status.readContent -import jp.zero_x_d.workaholic.merltlreader.status.readName -import org.luaj.vm2.LuaError - - -interface ILTLReaderApp { - var preferences: Preferences? - - fun login(): LoginData - fun launch(vararg args: String): Unit - - fun onStatus(stats: Status) {} - - fun run(vararg args: String) { - preferences = Preferences("mstdn-workers.com") - val credentials = - Credentials.Builder(preferences!!) - .loadOrAppRegister().loadOrLogin { - mailPass = login() - } - - val tl = Timeline(credentials) - val tts_engine: ITTSEngine = JTalkConnecter(emptyMap()) - for (status in tl) { - try { - onStatus(stats = status) - status.readName?.let { tts_engine.say_username(it) } - status.readContent?.let { tts_engine.say_content(it) } - } catch (e: LuaError) { - e.printStackTrace() - tts_engine.say("るあえらーが発生しました") - } - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/app/guifallback/GUIApp.kt b/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/app/guifallback/GUIApp.kt index ac19a24..eb632a3 100644 --- a/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/app/guifallback/GUIApp.kt +++ b/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/app/guifallback/GUIApp.kt @@ -1,61 +1,53 @@ package jp.zero_x_d.workaholic.merltlreader.app.guifallback -import com.sys1yagi.mastodon4j.api.entity.Status import javafx.application.Application import javafx.application.Platform import javafx.scene.Scene import javafx.scene.control.TextArea import javafx.scene.layout.StackPane import javafx.stage.Stage -import jp.zero_x_d.workaholic.merltlreader.LoginData -import jp.zero_x_d.workaholic.merltlreader.MerLTLReader -import jp.zero_x_d.workaholic.merltlreader.Preferences -import jp.zero_x_d.workaholic.merltlreader.app.ILTLReaderApp +import jp.zero_x_d.workaholic.merltlreader.* +import jp.zero_x_d.workaholic.merltlreader.engine.ITTSEngine import jp.zero_x_d.workaholic.merltlreader.status.readContent import kotlin.concurrent.thread +class GUIApp: Application() { + override fun start(primaryStage: Stage) { + Platform.setImplicitExit(true) + val root = StackPane() + val scene = Scene(root, 640.0, 480.0) + var logArea = TextArea().apply { + textProperty().addListener { _ -> + scrollTop = Double.MAX_VALUE + } + } -private var logArea: TextArea? = null + MerLTLReader.onStatus += { status -> + logArea?.appendText(status.readContent + "\n") + } -class GUIApp: ILTLReaderApp { - override var preferences: Preferences? = null + root.children.add(logArea) + primaryStage.scene = scene - override fun login(): LoginData { - val dialog = LoginDialog(MerLTLReader.preferences) - val result = dialog.showAndWait() - return requireNotNull(result) - } - - override fun launch(vararg args: String) { - Application.launch(FXApp::class.java, *args) - } + primaryStage.setOnCloseRequest { e -> + Platform.exit() + println("close") + // TODO あとできちんとInterruptする + System.exit(0) + } + primaryStage.show() - class FXApp: Application() { - override fun start(primaryStage: Stage) { - val root = StackPane() - val scene = Scene(root, 640.0, 480.0) - logArea = TextArea().apply { - textProperty().addListener { _ -> - scrollTop = Double.MAX_VALUE + val credentials = + Credentials.Builder(MerLTLReader.preferences!!) + .loadOrAppRegister().loadOrLogin { + val dialog = LoginDialog(preferences) + mailPass = requireNotNull(dialog.showAndWait()) } - } - root.children.add(logArea) - primaryStage.scene = scene - thread { - MerLTLReader.appInstance.run(*parameters.raw.toTypedArray()) - } - primaryStage.setOnCloseRequest { e -> - Platform.exit() - println("close") - // TODO あとできちんとInterruptする - System.exit(0) - } - primaryStage.show() - } - } - override fun onStatus(stats: Status) { - logArea?.appendText(stats.readContent + "\n") - println(stats.readContent) + thread { + val tl = Timeline(credentials) + val tts = ITTSEngine.getEngineFromPreferences(MerLTLReader.preferences!!) + MerLTLReader.runWithTTS(tl, tts) + } } } \ No newline at end of file diff --git a/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/engine/BouyomiConnecter.kt b/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/engine/BouyomiConnecter.kt index 6c05b01..8275938 100644 --- a/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/engine/BouyomiConnecter.kt +++ b/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/engine/BouyomiConnecter.kt @@ -1,11 +1,26 @@ package jp.zero_x_d.workaholic.merltlreader.engine import org.snowink.bouyomichan.BouyomiChan4J +import java.net.ConnectException +import java.net.Socket /** * Created by jun on 2017/07/01. */ class BouyomiConnecter(val engine_params: Map): ITTSEngine { + override fun test(): Boolean { + var socket: Socket? = null + try { + socket = Socket( + BouyomiChan4J.DEFAULT_BOUYOMI_HOST, + BouyomiChan4J.DEFAULT_BOUYOMI_PORT) + } catch (_: ConnectException) { + return false + } finally { + socket?.close() + } + return true + } private val b4j = BouyomiChan4J() diff --git a/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/engine/ITTSEngine.kt b/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/engine/ITTSEngine.kt index 02ccc56..9fc5c27 100644 --- a/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/engine/ITTSEngine.kt +++ b/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/engine/ITTSEngine.kt @@ -1,10 +1,44 @@ package jp.zero_x_d.workaholic.merltlreader.engine +import jp.zero_x_d.workaholic.merltlreader.Preferences + /** * Created by D on 17/06/20. */ interface ITTSEngine { + fun test(): Boolean fun say(readtext: String) fun say_username(username: String) fun say_content(content: String) + + enum class Engines { + JTALK, + BOUYOMI, + AUTO + } + + private object SilentEngine: ITTSEngine { + override fun test(): Boolean = true + override fun say(readtext: String) {} + override fun say_username(username: String) {} + override fun say_content(content: String) {} + } + + companion object { + fun getEngineFromPreferences(preferences: Preferences): ITTSEngine { + return when(preferences.tts_engine) { + ITTSEngine.Engines.JTALK -> JTalkConnecter(emptyMap()) + ITTSEngine.Engines.BOUYOMI -> BouyomiConnecter(emptyMap()) + Engines.AUTO -> autoSelect() + } + } + + private fun autoSelect(): ITTSEngine { + return listOf( + JTalkConnecter(emptyMap()), + BouyomiConnecter(emptyMap()), + SilentEngine + ).filter { it.test() }.first() + } + } } \ No newline at end of file diff --git a/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/engine/JTalkConnecter.kt b/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/engine/JTalkConnecter.kt index 5c8c607..1b207be 100644 --- a/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/engine/JTalkConnecter.kt +++ b/src/main/kotlin/jp/zero_x_d/workaholic/merltlreader/engine/JTalkConnecter.kt @@ -1,7 +1,9 @@ package jp.zero_x_d.workaholic.merltlreader.engine +import org.snowink.bouyomichan.BouyomiChan4J import java.io.OutputStreamWriter import java.io.PrintWriter +import java.net.ConnectException import java.net.Socket /** @@ -15,9 +17,25 @@ class JTalkConnecter(val engine_params: Map): ITTSEngine { val content_voice_params = mapOf( "Voice" to "mei", "Speed" to 1.9) + val DEFAULT_JTALK_HOST = "localhost" + val DEFAULT_JTALK_PORT = 8000 + + override fun test(): Boolean { + var socket: Socket? = null + try { + socket = Socket( + DEFAULT_JTALK_HOST, + DEFAULT_JTALK_PORT) + } catch (_: ConnectException) { + return false + } finally { + socket?.close() + } + return true + } private fun say(readtext: String, params: Map) { - val socket = Socket("localhost", 8000); + val socket = Socket(DEFAULT_JTALK_HOST, DEFAULT_JTALK_PORT) val output = socket.getOutputStream() val input = socket.getInputStream() diff --git a/src/main/kotlin/org/snowink/bouyomichan/BouyomiChan4J.kt b/src/main/kotlin/org/snowink/bouyomichan/BouyomiChan4J.kt index 9dc6c08..4247717 100644 --- a/src/main/kotlin/org/snowink/bouyomichan/BouyomiChan4J.kt +++ b/src/main/kotlin/org/snowink/bouyomichan/BouyomiChan4J.kt @@ -140,8 +140,8 @@ class BouyomiChan4J( } companion object { - private val DEFAULT_BOUYOMI_HOST = "localhost" - private val DEFAULT_BOUYOMI_PORT = 50001 + val DEFAULT_BOUYOMI_HOST = "localhost" + val DEFAULT_BOUYOMI_PORT = 50001 } } \ No newline at end of file