import jp.sfjp.gokigen.a01c.thetacamerawrapper.connection.ThetaCameraConnection
import jp.sfjp.gokigen.a01c.thetacamerawrapper.liveview.ThetaLiveViewControl
import jp.sfjp.gokigen.a01c.thetacamerawrapper.operation.ThetaDummyOperation
+import jp.sfjp.gokigen.a01c.thetacamerawrapper.operation.ThetaMovieRecordingControl
+import jp.sfjp.gokigen.a01c.thetacamerawrapper.operation.ThetaOptionUpdateControl
import jp.sfjp.gokigen.a01c.thetacamerawrapper.operation.ThetaSingleShotControl
+import java.util.*
class ThetaCameraController(val context: AppCompatActivity, private val focusFrameDisplay: IAutoFocusFrameDisplay, private val showInformation: IShowInformation, private val receiver: ICameraStatusReceiver, private val preferences: PreferenceAccessWrapper) : ICameraController, IIndicatorControl
{
private val sessionIdHolder = ThetaSessionHolder()
private val cameraConnection = ThetaCameraConnection(context, receiver, sessionIdHolder)
private val singleShot = ThetaSingleShotControl(sessionIdHolder, this, this)
+ private val movieShot = ThetaMovieRecordingControl(context, sessionIdHolder, this, showInformation, this)
+ private val optionSet = ThetaOptionUpdateControl(sessionIdHolder, this, this)
override fun setLiveViewListener(listener: CameraLiveViewListenerImpl)
{
- this.liveViewControl = ThetaLiveViewControl(sessionIdHolder, listener)
+ Log.v(TAG, " setLiveViewListener() : ${sessionIdHolder.isApiLevelV21()} ")
+ this.liveViewControl = ThetaLiveViewControl(listener)
}
override fun changeLiveViewSize(size: String?)
override fun startLiveView()
{
- if (::liveViewControl.isInitialized)
+ try
+ {
+ // スチルモードに切り替える
+ changeCaptureImageMode(sessionIdHolder.isApiLevelV21())
+
+ // ライブビューの表示...
+ if (::liveViewControl.isInitialized)
+ {
+ liveViewControl.startLiveView(sessionIdHolder)
+ }
+ }
+ catch (e : Exception)
{
- liveViewControl.startLiveView()
+ e.printStackTrace()
}
}
override fun updateTakeMode()
{
- // なにもしない
+ if (::featureDispatcher.isInitialized)
+ {
+ when (featureDispatcher.takeMode)
+ {
+ "P" -> changeCaptureImageMode(sessionIdHolder.isApiLevelV21())
+ "Movie" -> changeCaptureVideoMode(sessionIdHolder.isApiLevelV21())
+ }
+ }
+ }
+
+ private fun changeCaptureImageMode(apiV21 : Boolean)
+ {
+ try
+ {
+ optionSet.setOptions("\"captureMode\" : \"image\"", apiV21)
+ }
+ catch (e : Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+ private fun changeCaptureVideoMode(apiV21 : Boolean)
+ {
+ try
+ {
+ if (apiV21)
+ {
+ optionSet.setOptions("\"captureMode\" : \"video\"", apiV21)
+ }
+ else
+ {
+ optionSet.setOptions("\"captureMode\" : \"_video\"", apiV21)
+ }
+ }
+ catch (e : Exception)
+ {
+ e.printStackTrace()
+ }
}
override fun driveAutoFocus(event: MotionEvent?): Boolean
override fun movieControl()
{
- // TODO("Not yet implemented")
+ movieShot.movieControl(sessionIdHolder.isApiLevelV21())
}
override fun bracketingShot(bracketingStyle: Int, bracketingCount: Int, durationSeconds: Int)
{
//TODO("Not yet implemented")
}
+
+ private fun waitMs(waitMs: Int)
+ {
+ try
+ {
+ Thread.sleep(waitMs.toLong())
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+ companion object
+ {
+ private val TAG = ThetaCameraController::class.java.simpleName
+ }
}
package jp.sfjp.gokigen.a01c.thetacamerawrapper
+import android.graphics.Color
import android.util.Log
import android.view.MotionEvent
import androidx.appcompat.app.AppCompatActivity
class ThetaFeatureDispatcher(val context: AppCompatActivity, val statusDrawer: IShowInformation, val camera: ICameraController, private val preferences: PreferenceDataStore, val liveImageView: ILiveImageStatusNotify): ICameraFeatureDispatcher
{
+ private var takeMode : String = "P"
/**
* 指定した機能を実行する
// 機能実行の割り当て...
var duration = IShowInformation.VIBRATE_PATTERN_SIMPLE_SHORT
when (featureNumber) {
- ICameraFeatureDispatcher.FEATURE_TOGGLE_SHOW_GRID -> // グリッド標示ON/OFF
+ ICameraFeatureDispatcher.FEATURE_TOGGLE_SHOW_GRID -> // グリッド標示ON/OFF
changeShowGrid(objectId)
- ICameraFeatureDispatcher.FEATURE_SHUTTER_SINGLESHOT -> // シャッター
+ ICameraFeatureDispatcher.FEATURE_SHUTTER_SINGLESHOT -> // シャッター(一枚撮影)
pushShutterButton()
ICameraFeatureDispatcher.FEATURE_SETTINGS -> {
- showSettingsScreen() // 設定画面を開く
+ showSettingsScreen() // 設定画面を開く
duration = IShowInformation.VIBRATE_PATTERN_NONE
}
-/*
+ ICameraFeatureDispatcher.FEATURE_CONTROL_MOVIE -> // 動画の撮影・撮影終了
+ movieControl()
ICameraFeatureDispatcher.FEATURE_CHANGE_TAKEMODE -> // 撮影モードの変更
changeTakeMode()
+ ICameraFeatureDispatcher.FEATURE_CHANGE_TAKEMODE_REVERSE -> // 撮影モードの変更(逆順)
+ changeTakeModeReverse()
+/*
ICameraFeatureDispatcher.FEATURE_CHAGE_AE_LOCK_MODE -> // AE LOCKのON/OFF切り替え
changeAeLockMode()
ICameraFeatureDispatcher.FEATURE_EXPOSURE_BIAS_DOWN -> // 露出補正を1段階下げる
changeArtFilterUp()
ICameraFeatureDispatcher.FEATURE_TOGGLE_SHOW_LEVEL_GAUGE -> // デジタル水準器の表示・非表示
changeShowLevelGauge()
- ICameraFeatureDispatcher.FEATURE_CHANGE_TAKEMODE_REVERSE -> // 撮影モードの変更(逆順)
- changeTakeModeReverse()
- ICameraFeatureDispatcher.FEATURE_CONTROL_MOVIE -> // 動画の撮影・撮影終了
- movieControl()
ICameraFeatureDispatcher.FEATURE_AE_DOWN -> // AE(測光方式)を選択
changeAEModeDown()
ICameraFeatureDispatcher.FEATURE_AE_UP -> // AE(測光方式)を選択
*/
override fun getTakeMode(): String?
{
- return ("P") // 暫定でプログラムモード
+ return (takeMode) // 暫定でプログラムモード
//val propertyProxy = camera.cameraPropertyProvider
//return propertyProxy.getCameraPropertyValueTitle(propertyProxy.getCameraPropertyValue(IOlyCameraProperty.TAKE_MODE))
*/
private fun changeTakeMode()
{
+ if (takeMode.contains("P"))
+ {
+ takeMode = "Movie"
+ }
+ else
+ {
+ takeMode = "P"
+ }
+ statusDrawer.setMessage(IShowInformation.AREA_1, Color.WHITE, takeMode)
+
+ // 撮影モードの更新
+ camera.updateTakeMode();
+
+/*
val propertyProxy = camera.cameraPropertyProvider
val propetyValue = propertyProxy.getCameraPropertyValueTitle(propertyProxy.getCameraPropertyValue(IOlyCameraProperty.TAKE_MODE))
?: // データ取得失敗
"iAuto" -> "$targetMode/P>"
else -> "$targetMode/P>"
}
+
Log.v(TAG, "changeTakeMode() $targetMode")
propertyProxy.setCameraPropertyValue(IOlyCameraProperty.TAKE_MODE, targetMode)
camera.unlockAutoFocus()
-
- // 撮影モードの更新
- //camera.updateTakeMode();
+*/
}
/**
*/
private fun changeTakeModeReverse()
{
+ changeTakeMode()
+/*
val propertyProxy = camera.cameraPropertyProvider
val propetyValue = propertyProxy.getCameraPropertyValueTitle(propertyProxy.getCameraPropertyValue(IOlyCameraProperty.TAKE_MODE))
?: // データ取得失敗
// 撮影モードの更新
//camera.updateTakeMode();
+*/
}
/**
package jp.sfjp.gokigen.a01c.thetacamerawrapper
+import android.util.Log
+
class ThetaSessionHolder : IThetaSessionIdProvider, IThetaSessionIdNotifier
{
private var sessionId : String = ""
override fun receivedSessionId(sessionId: String?)
{
- if (sessionId != null)
+ if (!(sessionId.isNullOrEmpty()))
{
+ Log.v(TAG, " SESSION ID : $sessionId")
this.sessionId = sessionId
}
}
fun isApiLevelV21() : Boolean
{
- return (!(sessionId.isNotEmpty()))
+ return (sessionId.isEmpty())
}
+
+ companion object
+ {
+ private val TAG = ThetaSessionHolder::class.java.simpleName
+ }
+
}
for (index in 0 until size)
{
val api = apiLevelArray.getInt(index)
+ if (api == 1) //if (api == 1 && useThetaV21)
+ {
+ apiLevelIsV21 = false
+ break
+ }
if (api == 2) //if (api == 2 && useThetaV21)
{
apiLevelIsV21 = true
+ break
}
}
}
}
}
- private fun connectApiV21() {
+ private fun connectApiV21()
+ {
val commandsExecuteUrl = "http://192.168.1.1/osc/commands/execute"
val startSessionData = "{\"name\":\"camera.startSession\",\"parameters\":{\"timeout\":0}}"
val getStateUrl = "http://192.168.1.1/osc/state"
val timeoutMs = 5000
- try {
+ try
+ {
val responseS: String? = httpClient.httpPostWithHeader(commandsExecuteUrl, startSessionData, null, "application/json;charset=utf-8", timeoutMs)
Log.v(TAG, " [ $httpClient ] $startSessionData ::: $responseS")
val response: String? = httpClient.httpPostWithHeader(getStateUrl, "", null, null, timeoutMs)
{
var apiLevel = 1
var sessionId: String? = null
- val `object` = JSONObject(response)
- try {
- apiLevel = `object`.getJSONObject("state").getInt("_apiVersion")
- } catch (e: Exception) {
+ val jsonObject = JSONObject(response)
+ try
+ {
+ apiLevel = jsonObject.getJSONObject("state").getInt("_apiVersion")
+ }
+ catch (e: Exception)
+ {
e.printStackTrace()
}
- try {
- sessionId = `object`.getJSONObject("state").getString("sessionId")
+ try
+ {
+ sessionId = jsonObject.getJSONObject("state").getString("sessionId")
sessionIdNotifier.receivedSessionId(sessionId)
- } catch (e: Exception) {
+ }
+ catch (e: Exception)
+ {
e.printStackTrace()
}
- if (apiLevel != 2) {
+ if (apiLevel != 2)
+ {
val setApiLevelData = "{\"name\":\"camera.setOptions\",\"parameters\":{\"sessionId\" : \"$sessionId\", \"options\":{ \"clientVersion\":2}}}"
val response3: String? = httpClient.httpPostWithHeader(commandsExecuteUrl, setApiLevelData, null, "application/json;charset=utf-8", timeoutMs)
Log.v(TAG, " $commandsExecuteUrl $setApiLevelData $response3")
import jp.sfjp.gokigen.a01c.thetacamerawrapper.IThetaSessionIdProvider
import jp.sfjp.gokigen.a01c.utils.SimpleLiveviewSlicer
-class ThetaLiveViewControl(private val sessionIdProvider: IThetaSessionIdProvider, private val liveViewListener: CameraLiveViewListenerImpl)
+class ThetaLiveViewControl(private val liveViewListener: CameraLiveViewListenerImpl)
{
private var whileFetching = false
- fun startLiveView()
+ fun startLiveView(sessionIdProvider: IThetaSessionIdProvider)
{
Log.v(TAG, " startLiveView()")
try
try
{
- start(!(sessionIdProvider.sessionId.isEmpty()))
+ start(sessionIdProvider.sessionId)
}
catch (e: Exception)
{
whileFetching = false
}
- private fun start(useOscV2 : Boolean)
+ private fun start(sessionId : String)
{
if (whileFetching)
{
try
{
val streamUrl = "http://192.168.1.1/osc/commands/execute"
- val paramData = if (useOscV2) "{\"name\":\"camera.getLivePreview\",\"parameters\":{\"timeout\":0}}" else "{\"name\":\"camera._getLivePreview\",\"parameters\":{\"sessionId\": \"" + sessionIdProvider.getSessionId().toString() + "\"}}"
- Log.v(TAG, " >>>>> START THETA PREVIEW : $streamUrl $paramData")
+ val paramData = if (sessionId.isEmpty()) "{\"name\":\"camera.getLivePreview\",\"parameters\":{\"timeout\":0}}" else "{\"name\":\"camera._getLivePreview\",\"parameters\":{\"sessionId\": \"$sessionId\"}}"
+ Log.v(TAG, " >>>>> START THETA PREVIEW($sessionId) : $streamUrl $paramData")
// Create Slicer to open the stream and parse it.
slicer.open(streamUrl, paramData, "application/json;charset=utf-8")
- while (whileFetching) {
+ while (whileFetching)
+ {
val payload: SimpleLiveviewSlicer.Payload? = slicer.nextPayloadForMotionJpeg()
if (payload == null)
{
{
// 再度ライブビューのスタートをやってみる。
whileFetching = false
- start(useOscV2)
+ start(sessionId)
}
}
}
--- /dev/null
+package jp.sfjp.gokigen.a01c.thetacamerawrapper.operation
+
+import android.content.Context
+import android.graphics.Color
+import android.util.Log
+import jp.sfjp.gokigen.a01c.ICameraController
+import jp.sfjp.gokigen.a01c.IShowInformation
+import jp.sfjp.gokigen.a01c.R
+import jp.sfjp.gokigen.a01c.olycamerawrapper.IIndicatorControl
+import jp.sfjp.gokigen.a01c.thetacamerawrapper.IThetaSessionIdProvider
+import jp.sfjp.gokigen.a01c.utils.SimpleHttpClient
+import org.json.JSONObject
+
+class ThetaBracketingControl(val context: Context, private val sessionIdProvider: IThetaSessionIdProvider, private val indicator: IIndicatorControl, private val statusDrawer: IShowInformation, private val liveViewControl: ICameraController)
+{
+ private val httpClient = SimpleHttpClient()
+ private var isCapturing = false
+
+ fun bracketingControl(useOSCv2 : Boolean)
+ {
+ try
+ {
+ if (!(isCapturing))
+ {
+ startCapture(useOSCv2)
+ statusDrawer.setMessage(IShowInformation.AREA_9, Color.RED, context.getString(R.string.video_recording))
+ }
+ else
+ {
+ stopCapture(useOSCv2)
+ statusDrawer.setMessage(IShowInformation.AREA_9, Color.WHITE, "")
+ }
+ isCapturing = !isCapturing
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+ private fun startCapture(useOSCv2 : Boolean)
+ {
+ Log.v(TAG, "startCapture() (API v2.1 : $useOSCv2)")
+ try
+ {
+ val thread = Thread {
+ try
+ {
+ val shootUrl = "http://192.168.1.1/osc/commands/execute"
+ // val postData = if (useOSCv2) "{\"name\":\"camera.startCapture\",\"parameters\":{\"timeout\":0}}" else "{\"name\":\"camera.startCapture\",\"parameters\":{\"sessionId\": \"" + sessionIdProvider.sessionId + "\"}}"
+ val postData = if (useOSCv2) "{\"name\":\"camera.startCapture\",\"parameters\":{\"timeout\":0, \"_mode\": \"bracket\"}}" else "{\"name\":\"camera._startCapture\",\"parameters\":{\"sessionId\": \"" + sessionIdProvider.sessionId + "\", \"mode\": \"bracket\"}}}"
+
+ Log.v(TAG, " start Capture : $postData")
+
+ val result: String? = httpClient.httpPostWithHeader(shootUrl, postData, null, "application/json;charset=utf-8", timeoutMs)
+ if ((result != null)&&(result.isNotEmpty()))
+ {
+ Log.v(TAG, " startCapture() : $result")
+ indicator.onShootingStatusUpdate(IIndicatorControl.shootingStatus.Starting)
+
+ // 画像処理が終わるまで待つ
+ //waitChangeStatus()
+
+ // ライブビューのの再実行を指示する
+ //indicator.onShootingStatusUpdate(IIndicatorControl.shootingStatus.Stopping)
+ //liveViewControl.stopLiveView()
+ //waitMs(300) // ちょっと待つ...
+ //liveViewControl.startLiveView()
+ }
+ else
+ {
+ Log.v(TAG, "startCapture() reply is null.")
+ }
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+ thread.start()
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+ private fun stopCapture(useOSCv2 : Boolean)
+ {
+ Log.v(TAG, "stopCapture() (API v2.1 : $useOSCv2)")
+ try
+ {
+ val thread = Thread {
+ try
+ {
+ val shootUrl = "http://192.168.1.1/osc/commands/execute"
+ val postData = if (useOSCv2) "{\"name\":\"camera.stopCapture\",\"parameters\":{\"timeout\":0}}" else "{\"name\":\"camera._stopCapture\",\"parameters\":{\"sessionId\": \"" + sessionIdProvider.sessionId + "\"}}"
+
+ Log.v(TAG, " stop Capture : $postData")
+
+ val result: String? = httpClient.httpPostWithHeader(shootUrl, postData, null, "application/json;charset=utf-8", timeoutMs)
+ if ((result != null)&&(result.isNotEmpty()))
+ {
+ Log.v(TAG, " stopCapture() : $result")
+ indicator.onShootingStatusUpdate(IIndicatorControl.shootingStatus.Starting)
+
+ // 画像処理が終わるまで待つ
+ waitChangeStatus()
+
+ // ライブビューのの再実行を指示する
+ indicator.onShootingStatusUpdate(IIndicatorControl.shootingStatus.Stopping)
+ liveViewControl.stopLiveView()
+ waitMs(300) // ちょっと待つ...
+ liveViewControl.startLiveView()
+ }
+ else
+ {
+ Log.v(TAG, "stopCapture() reply is null.")
+ }
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+ thread.start()
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+ /**
+ * 撮影状態が変わるまで待つ。
+ * (ただし、タイムアウト時間を超えたらライブビューを再開させる)
+ */
+ private fun waitChangeStatus()
+ {
+ val getStateUrl = "http://192.168.1.1/osc/state"
+ val maxWaitTimeoutMs = 9900 // 最大待ち時間 (単位: ms)
+ var fingerprint = ""
+ try
+ {
+ val result: String? = httpClient.httpPost(getStateUrl, "", timeoutMs)
+ if ((result != null)&&(result.isNotEmpty()))
+ {
+ val jsonObject = JSONObject(result)
+ fingerprint = jsonObject.getString("fingerprint")
+
+ // 現在の状態(ログを出す)
+ Log.v(TAG, " $getStateUrl $result ($fingerprint)")
+ }
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+
+ try
+ {
+ val firstTime = System.currentTimeMillis()
+ var currentTime = firstTime
+ while (currentTime - firstTime < maxWaitTimeoutMs)
+ {
+ // ... 状態を見て次に進める
+ val result: String? = httpClient.httpPost(getStateUrl, "", timeoutMs)
+ if ((result != null)&&(result.isNotEmpty()))
+ {
+ val jsonObject = JSONObject(result)
+ val currentFingerprint = jsonObject.getString("fingerprint")
+
+ // ログを出してみる
+ // Log.v(TAG, " " + getStateUrl + " ( " + result + " ) " + "(" + fingerprint + " " + current_fingerprint + ")");
+ if (fingerprint != currentFingerprint)
+ {
+ // fingerprintが更新された!
+ break
+ }
+ Log.v(TAG, " ----- NOW PROCESSING ----- : $fingerprint")
+ }
+ waitMs(1000)
+ currentTime = System.currentTimeMillis()
+ }
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+ /**
+ *
+ *
+ */
+ private fun waitMs(waitMs: Int)
+ {
+ try
+ {
+ Thread.sleep(waitMs.toLong())
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+ companion object
+ {
+ private val TAG = ThetaBracketingControl::class.java.simpleName
+ private const val timeoutMs = 6000
+ }
+
+}
\ No newline at end of file
--- /dev/null
+package jp.sfjp.gokigen.a01c.thetacamerawrapper.operation
+
+import android.content.Context
+import android.graphics.Color
+import android.util.Log
+import jp.sfjp.gokigen.a01c.ICameraController
+import jp.sfjp.gokigen.a01c.IShowInformation
+import jp.sfjp.gokigen.a01c.R
+import jp.sfjp.gokigen.a01c.olycamerawrapper.IIndicatorControl
+import jp.sfjp.gokigen.a01c.thetacamerawrapper.IThetaSessionIdProvider
+import jp.sfjp.gokigen.a01c.utils.SimpleHttpClient
+import org.json.JSONObject
+
+class ThetaMovieRecordingControl(val context: Context, private val sessionIdProvider: IThetaSessionIdProvider, private val indicator: IIndicatorControl, private val statusDrawer: IShowInformation, private val liveViewControl: ICameraController)
+{
+ private val httpClient = SimpleHttpClient()
+ private var isCapturing = false
+
+ fun movieControl(useOSCv2 : Boolean)
+ {
+ try
+ {
+ if (!(isCapturing))
+ {
+ startCapture(useOSCv2)
+ statusDrawer.setMessage(IShowInformation.AREA_9, Color.RED, context.getString(R.string.video_recording))
+ }
+ else
+ {
+ stopCapture(useOSCv2)
+ statusDrawer.setMessage(IShowInformation.AREA_9, Color.WHITE, "")
+ }
+ isCapturing = !isCapturing
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+ private fun startCapture(useOSCv2 : Boolean)
+ {
+ Log.v(TAG, "startCapture() (API v2.1 : $useOSCv2)")
+ try
+ {
+ val thread = Thread {
+ try
+ {
+ val shootUrl = "http://192.168.1.1/osc/commands/execute"
+ // val postData = if (useOSCv2) "{\"name\":\"camera.startCapture\",\"parameters\":{\"timeout\":0}}" else "{\"name\":\"camera.startCapture\",\"parameters\":{\"sessionId\": \"" + sessionIdProvider.sessionId + "\"}}"
+ val postData = if (useOSCv2) "{\"name\":\"camera.startCapture\",\"parameters\":{\"timeout\":0}}" else "{\"name\":\"camera._startCapture\",\"parameters\":{\"sessionId\": \"" + sessionIdProvider.sessionId + "\"}}"
+
+ Log.v(TAG, " start Capture : $postData")
+
+ val result: String? = httpClient.httpPostWithHeader(shootUrl, postData, null, "application/json;charset=utf-8", timeoutMs)
+ if ((result != null)&&(result.isNotEmpty()))
+ {
+ Log.v(TAG, " startCapture() : $result")
+ indicator.onShootingStatusUpdate(IIndicatorControl.shootingStatus.Starting)
+
+ // 画像処理が終わるまで待つ
+ //waitChangeStatus()
+
+ // ライブビューのの再実行を指示する
+ //indicator.onShootingStatusUpdate(IIndicatorControl.shootingStatus.Stopping)
+ //liveViewControl.stopLiveView()
+ //waitMs(300) // ちょっと待つ...
+ //liveViewControl.startLiveView()
+ }
+ else
+ {
+ Log.v(TAG, "startCapture() reply is null.")
+ }
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+ thread.start()
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+ private fun stopCapture(useOSCv2 : Boolean)
+ {
+ Log.v(TAG, "stopCapture() (API v2.1 : $useOSCv2)")
+ try
+ {
+ val thread = Thread {
+ try
+ {
+ val shootUrl = "http://192.168.1.1/osc/commands/execute"
+ val postData = if (useOSCv2) "{\"name\":\"camera.stopCapture\",\"parameters\":{\"timeout\":0}}" else "{\"name\":\"camera._stopCapture\",\"parameters\":{\"sessionId\": \"" + sessionIdProvider.sessionId + "\"}}"
+
+ Log.v(TAG, " stop Capture : $postData")
+
+ val result: String? = httpClient.httpPostWithHeader(shootUrl, postData, null, "application/json;charset=utf-8", timeoutMs)
+ if ((result != null)&&(result.isNotEmpty()))
+ {
+ Log.v(TAG, " stopCapture() : $result")
+ indicator.onShootingStatusUpdate(IIndicatorControl.shootingStatus.Starting)
+
+ //// 画像処理が終わるまで待つ
+ //waitChangeStatus()
+
+ // ライブビューのの再実行を指示する
+ indicator.onShootingStatusUpdate(IIndicatorControl.shootingStatus.Stopping)
+ liveViewControl.stopLiveView()
+ waitMs(300) // ちょっと待つ...
+ liveViewControl.startLiveView()
+ }
+ else
+ {
+ Log.v(TAG, "stopCapture() reply is null.")
+ }
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+ thread.start()
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+ /**
+ * 撮影状態が変わるまで待つ。
+ * (ただし、タイムアウト時間を超えたらライブビューを再開させる)
+ */
+ private fun waitChangeStatus()
+ {
+ val getStateUrl = "http://192.168.1.1/osc/state"
+ val maxWaitTimeoutMs = 9900 // 最大待ち時間 (単位: ms)
+ var fingerprint = ""
+ try
+ {
+ val result: String? = httpClient.httpPost(getStateUrl, "", timeoutMs)
+ if ((result != null)&&(result.isNotEmpty()))
+ {
+ val jsonObject = JSONObject(result)
+ fingerprint = jsonObject.getString("fingerprint")
+
+ // 現在の状態(ログを出す)
+ Log.v(TAG, " $getStateUrl $result ($fingerprint)")
+ }
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+
+ try
+ {
+ val firstTime = System.currentTimeMillis()
+ var currentTime = firstTime
+ while (currentTime - firstTime < maxWaitTimeoutMs)
+ {
+ // ... 状態を見て次に進める
+ val result: String? = httpClient.httpPost(getStateUrl, "", timeoutMs)
+ if ((result != null)&&(result.isNotEmpty()))
+ {
+ val jsonObject = JSONObject(result)
+ val currentFingerprint = jsonObject.getString("fingerprint")
+
+ // ログを出してみる
+ // Log.v(TAG, " " + getStateUrl + " ( " + result + " ) " + "(" + fingerprint + " " + current_fingerprint + ")");
+ if (fingerprint != currentFingerprint)
+ {
+ // fingerprintが更新された!
+ break
+ }
+ Log.v(TAG, " ----- NOW PROCESSING ----- : $fingerprint")
+ }
+ waitMs(1000)
+ currentTime = System.currentTimeMillis()
+ }
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+ /**
+ *
+ *
+ */
+ private fun waitMs(waitMs: Int)
+ {
+ try
+ {
+ Thread.sleep(waitMs.toLong())
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+ companion object
+ {
+ private val TAG = ThetaMovieRecordingControl::class.java.simpleName
+ private const val timeoutMs = 6000
+ }
+}
\ No newline at end of file
--- /dev/null
+package jp.sfjp.gokigen.a01c.thetacamerawrapper.operation
+
+import android.util.Log
+import jp.sfjp.gokigen.a01c.ICameraController
+import jp.sfjp.gokigen.a01c.olycamerawrapper.IIndicatorControl
+import jp.sfjp.gokigen.a01c.thetacamerawrapper.IThetaSessionIdProvider
+import jp.sfjp.gokigen.a01c.utils.SimpleHttpClient
+
+class ThetaOptionUpdateControl(private val sessionIdProvider: IThetaSessionIdProvider, private val indicator: IIndicatorControl, private val liveViewControl: ICameraController)
+{
+ private val httpClient = SimpleHttpClient()
+
+ /**
+ *
+ *
+ */
+ fun setOptions(options: String, useOSCv2 : Boolean)
+ {
+ Log.v(TAG, "setOptions() useOSCv2 : $useOSCv2 MSG : $options")
+ try
+ {
+ val thread = Thread {
+ try
+ {
+ val setOptionsUrl = "http://192.168.1.1/osc/commands/execute"
+ val postData = if (useOSCv2) "{\"name\":\"camera.setOptions\",\"parameters\":{\"timeout\":0, \"options\": {\"$options\"}}}" else "{\"name\":\"camera.setOptions\",\"parameters\":{\"sessionId\": \"" + sessionIdProvider.sessionId + "\", \"options\": { $options }}}"
+
+ Log.v(TAG, " OPTIONS : $postData")
+
+ val result: String? = httpClient.httpPostWithHeader(setOptionsUrl, postData, null, "application/json;charset=utf-8", timeoutMs)
+ if ((result != null)&&(result.isNotEmpty()))
+ {
+ Log.v(TAG, " setOptions() : $result")
+ }
+ else
+ {
+ Log.v(TAG, "setOptions() reply is null or empty.")
+ }
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+ thread.start()
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+ companion object
+ {
+ private val TAG = ThetaOptionUpdateControl::class.java.simpleName
+ private const val timeoutMs = 3000
+ }
+
+}
\ No newline at end of file
*
*
*/
- fun singleShot(useThetaV21 : Boolean)
+ fun singleShot(useOSCv2 : Boolean)
{
Log.v(TAG, "singleShot()")
try
try
{
val shootUrl = "http://192.168.1.1/osc/commands/execute"
- val postData = if (useThetaV21) "{\"name\":\"camera.takePicture\",\"parameters\":{\"timeout\":0}}" else "{\"name\":\"camera.takePicture\",\"parameters\":{\"sessionId\": \"" + sessionIdProvider.sessionId + "\"}}"
+ val postData = if (useOSCv2) "{\"name\":\"camera.takePicture\",\"parameters\":{\"timeout\":0}}" else "{\"name\":\"camera.takePicture\",\"parameters\":{\"sessionId\": \"" + sessionIdProvider.sessionId + "\"}}"
val result: String? = httpClient.httpPostWithHeader(shootUrl, postData, null, "application/json;charset=utf-8", timeoutMs)
if ((result != null)&&(result.isNotEmpty()))
{
{
mInputStream = mHttpConn.getInputStream();
}
+ else
+ {
+ Log.v(TAG, " RESPONSE NG : " + mHttpConn.getResponseCode() + " " + mHttpConn.getResponseMessage());
+ }
}
catch (Exception e)
{
public @Nullable Payload nextPayloadForMotionJpeg()
{
int searchIndex = 0;
- int[] endmarker = { 0xff, 0xd9 };
+ int[] endMarker = { 0xff, 0xd9 };
Payload payload = null;
try
{
// 1byteづつの読み込み... 本当は複数バイト読み出しで処理したい
int data = mInputStream.read();
tmpByteArray.write(data);
- if (data == endmarker[searchIndex])
+ if (data == endMarker[searchIndex])
{
searchIndex++;
- if (searchIndex >= endmarker.length)
+ if (searchIndex >= endMarker.length)
{
break;
}