diff --git a/codio-intellij/src/main/kotlin/com/wix/codio/Extensions.kt b/codio-intellij/src/main/kotlin/com/wix/codio/Extensions.kt new file mode 100644 index 0000000..fbdd444 --- /dev/null +++ b/codio-intellij/src/main/kotlin/com/wix/codio/Extensions.kt @@ -0,0 +1,20 @@ +package com.wix.codio + +import java.io.IOException +import java.util.concurrent.TimeUnit + + +fun String.runAsCommand(): String? { + try { + val parts = this.split("\\s".toRegex()) + val proc = ProcessBuilder(*parts.toTypedArray()) + .redirectOutput(ProcessBuilder.Redirect.PIPE) + .redirectError(ProcessBuilder.Redirect.PIPE) + .start() + proc.waitFor(60, TimeUnit.MINUTES) + return proc.inputStream.bufferedReader().readText() + } catch (e: IOException) { + e.printStackTrace() + return null + } +} \ No newline at end of file diff --git a/codio-intellij/src/main/kotlin/com/wix/codio/Player.kt b/codio-intellij/src/main/kotlin/com/wix/codio/Player.kt index d4a555d..2fe39f8 100644 --- a/codio-intellij/src/main/kotlin/com/wix/codio/Player.kt +++ b/codio-intellij/src/main/kotlin/com/wix/codio/Player.kt @@ -2,17 +2,11 @@ package com.wix.codio import com.intellij.openapi.project.Project import com.intellij.openapi.wm.ToolWindowManager -import com.sun.org.apache.xpath.internal.operations.Bool -import com.wix.codio.CodioProgressTimer -import com.wix.codio.CodioProgressTimerOnFinishObserver -import com.wix.codio.CodioTimeline -import com.wix.codio.actions.CodioNotifier import com.wix.codio.codioEvents.CodioEvent import com.wix.codio.codioEvents.CodioEventsDispatcher import com.wix.codio.fileSystem.CodioProjectFileSystemHandler import com.wix.codio.fileSystem.FileSystemManager import com.wix.codio.toolwindow.CodioToolWindowPanel -import com.wix.codio.userInterface.Messages import frame.CodioFrame import frame.CodioFrameDocument import userInterface.SelectionRenderer @@ -75,18 +69,8 @@ open class Player { return milis / 1000 } - fun checkIfFfmpegExist() : Boolean{ - try { - Runtime.getRuntime().exec("/usr/local/bin/ffmpeg -version") - return true; - } catch(ex: Exception) { - return false; - } - } - private fun play(timeline: ArrayList, relativeTimeToStart: Long) { - val isFfmpegExist = checkIfFfmpegExist(); - if (isFfmpegExist) { + Utils.checkFFMPEGAvailability(null, Runnable { isPlaying = true absoluteStartTime = Instant.now().toEpochMilli() val timeline = CodioTimeline.createTimelineWithAbsoluteTime(timeline, absoluteStartTime) @@ -94,7 +78,7 @@ open class Player { val timeInSeconds = timeInSeconds(relativeTimeToStart).toInt() Audio.instance.play(audioPath!!, timeInSeconds) progressTimer?.run(timeInSeconds) - } else CodioNotifier(project).showTempBaloon(Messages.ffmpegNotInstalled, 8000) + }) } fun pause() { @@ -153,6 +137,7 @@ open class Player { codioRelativeActiveTime = relativeTimeToStart val relevantRelativeTimeline = codioTimeline!!.getTimelineFrom(relativeTimeToStart) play(relevantRelativeTimeline, relativeTimeToStart) + } fun moveToframe(milis: Long) { diff --git a/codio-intellij/src/main/kotlin/com/wix/codio/Utils.kt b/codio-intellij/src/main/kotlin/com/wix/codio/Utils.kt index 000514b..12c1be9 100644 --- a/codio-intellij/src/main/kotlin/com/wix/codio/Utils.kt +++ b/codio-intellij/src/main/kotlin/com/wix/codio/Utils.kt @@ -10,8 +10,11 @@ import com.intellij.openapi.fileEditor.FileEditorManager import com.intellij.openapi.project.Project import com.intellij.openapi.vfs.LocalFileSystem import com.intellij.openapi.vfs.VirtualFile -import com.wix.codio.codioEvents.CodioEvent +import com.wix.codio.actions.CodioNotifier import com.wix.codio.codioEvents.CodioPosition +import com.wix.codio.toolwindow.CodioFFMpegAlert +import com.wix.codio.userInterface.Messages +import java.util.* class Utils { companion object { @@ -40,10 +43,10 @@ class Utils { currentEditor = EditorUtil.getEditorEx(fileEditor) } - return currentEditor + return currentEditor } - fun findOffsetFromPosition(position: CodioPosition, text: String) :Int { + fun findOffsetFromPosition(position: CodioPosition, text: String): Int { val lines = text.lines() val contentTillLine = lines.subList(0, position.line).joinToString("\n") var lineOffset = contentTillLine.length @@ -51,5 +54,30 @@ class Utils { return lineOffset + position.character } + + fun checkFFMPEGAvailability(project: Project?, runIsSuccess: Runnable? = null): Boolean { + val exist = "ffmpeg -version".runAsCommand() + if (exist == null) { + val isOk = CodioFFMpegAlert(project).showAndGet() + if (isOk) { + installFFMPEG(project, runIsSuccess) + } + return false + } + runIsSuccess?.run() + return true + } + + private fun installFFMPEG(project: Project?, runIsSuccess: Runnable?) { + CodioNotifier(project).showTempBaloon(Messages.ffmpegStart) + // todo dirty trick in order not to block UI + Timer().schedule(object : TimerTask() { + override fun run() { + "brew install ffmpeg".runAsCommand() + CodioNotifier(project).showTempBaloon(Messages.ffmpegFinish) + runIsSuccess?.run() + } + }, 50) + } } } \ No newline at end of file diff --git a/codio-intellij/src/main/kotlin/com/wix/codio/actions/CodioRecordOrSaveAction.kt b/codio-intellij/src/main/kotlin/com/wix/codio/actions/CodioRecordOrSaveAction.kt index 6371aff..5cfa6d5 100644 --- a/codio-intellij/src/main/kotlin/com/wix/codio/actions/CodioRecordOrSaveAction.kt +++ b/codio-intellij/src/main/kotlin/com/wix/codio/actions/CodioRecordOrSaveAction.kt @@ -7,10 +7,10 @@ import com.intellij.openapi.editor.Document import com.intellij.openapi.fileEditor.FileEditorManager import com.intellij.openapi.project.Project import com.intellij.openapi.util.IconLoader -import com.wix.codio.Audio import com.wix.codio.Player -import com.wix.codio.recorder.Recorder +import com.wix.codio.Utils import com.wix.codio.fileSystem.FileSystemManager +import com.wix.codio.recorder.Recorder import com.wix.codio.recorder.RecorderException import com.wix.codio.toolwindow.CodioNameDialog import com.wix.codio.userInterface.Messages @@ -30,18 +30,20 @@ class CodioRecordOrSaveAction : AnAction() { CodioNotifier(project).showTempBaloon(Messages.recordingSaved, 2000) } else if (!Recorder.instance.isRecording) { try { - val doc = getOpenDoc(e, project) - val codioName = CodioNameDialog(project).selectCodioName() ?: return + Utils.checkFFMPEGAvailability(project, Runnable { + val doc = getOpenDoc(e, project) + val codioName = CodioNameDialog(project).selectCodioName() ?: return@Runnable - if (Player.instance.isPlaying) { - CodioNotifier(project).showTempBaloon(Messages.cantRecordWhilePlaying, 2000) - return - } - val codioId = UUID.randomUUID().toString() - val fileSystemHandler = FileSystemManager.getProjectFileSystemHandler(project) - fileSystemHandler.createCodioProjectFolderInHomeDirIfNeeded(codioId) - Recorder.instance.record(e, fileSystemHandler, codioId, codioName, doc) - CodioNotifier(project).showRecording() + if (Player.instance.isPlaying) { + CodioNotifier(project).showTempBaloon(Messages.cantRecordWhilePlaying, 2000) + return@Runnable + } + val codioId = UUID.randomUUID().toString() + val fileSystemHandler = FileSystemManager.getProjectFileSystemHandler(project) + fileSystemHandler.createCodioProjectFolderInHomeDirIfNeeded(codioId) + Recorder.instance.record(e, fileSystemHandler, codioId, codioName, doc) + CodioNotifier(project).showRecording() + }) } catch (ex: Exception) { CodioNotifier(project).showTempBaloon("Failure: ${ex.message}", 2000) return @@ -51,13 +53,13 @@ class CodioRecordOrSaveAction : AnAction() { override fun update(e: AnActionEvent) { - e.presentation.setEnabled(!Player.instance.isPlaying) + e.presentation.isEnabled = !Player.instance.isPlaying if (Recorder.instance.isRecording) { - e.presentation.setIcon(IconLoader.getIcon("/ui/save.svg")) + e.presentation.icon = IconLoader.getIcon("/ui/save.svg") e.presentation.text = "Save Current Recording" } else { - e.presentation.setIcon(IconLoader.getIcon("/ui/record.svg")) + e.presentation.icon = IconLoader.getIcon("/ui/record.svg") e.presentation.text = "Record Codio" } } @@ -70,7 +72,7 @@ class CodioRecordOrSaveAction : AnAction() { doc != null -> doc else -> editor!!.document } - } catch (ex: Exception){ + } catch (ex: Exception) { throw RecorderException("No open files found!\nClick record after you open a file") } } diff --git a/codio-intellij/src/main/kotlin/com/wix/codio/toolwindow/CodioFFMpegAlert.kt b/codio-intellij/src/main/kotlin/com/wix/codio/toolwindow/CodioFFMpegAlert.kt new file mode 100644 index 0000000..c458bf0 --- /dev/null +++ b/codio-intellij/src/main/kotlin/com/wix/codio/toolwindow/CodioFFMpegAlert.kt @@ -0,0 +1,19 @@ +package com.wix.codio.toolwindow + +import com.intellij.openapi.project.Project +import com.intellij.openapi.ui.DialogWrapper +import com.intellij.ui.components.JBLabel +import com.wix.codio.userInterface.Messages +import javax.swing.JComponent + +class CodioFFMpegAlert(project: Project?) : DialogWrapper(project) { + + init { + title = Messages.ffmpegIsNeededTitle + init() + } + + override fun createCenterPanel(): JComponent { + return JBLabel(Messages.ffmpegIsNeededMessage) + } +} \ No newline at end of file diff --git a/codio-intellij/src/main/kotlin/com/wix/codio/userInterface/Messages.kt b/codio-intellij/src/main/kotlin/com/wix/codio/userInterface/Messages.kt index 0700a86..94b56d6 100644 --- a/codio-intellij/src/main/kotlin/com/wix/codio/userInterface/Messages.kt +++ b/codio-intellij/src/main/kotlin/com/wix/codio/userInterface/Messages.kt @@ -14,5 +14,9 @@ class Messages { val stopTutorial = "Stopping current codio.." val tutorialPause = "Paused codio." val ffmpegNotInstalled = "Seems like you don't have ffmpeg. run `brew install ffmpeg` from your terminal and try again" + val ffmpegIsNeededTitle = "FFMPEG is needed" + val ffmpegIsNeededMessage = "Do you agree to install FFMPEG? It may take a couple of minutes." + val ffmpegStart = "FFMPEG started loading" + val ffmpegFinish = "FFMPEG is downloaded success" } } \ No newline at end of file