public interface ICameraStatusUpdateNotify
{
void updateCameraStatus(final String message);
+ void updatedExposureCompensation(String xv);
void updateRemainBattery(final double percentage);
+ void updateCaptureMode(final String message);
/*
void updateDriveMode(String driveMode);
void updatedTakeMode(String mode);
void updatedShutterSpeed(String tv);
void updatedAperture(String av);
- void updatedExposureCompensation(String xv);
void updatedMeteringMode(String meteringMode);
void updatedWBMode(String wbMode);
void updateFocusedStatus(boolean focused, boolean focusLocked);
public interface ICameraStatusWatcher
{
+ void prepareStatusWatch();
void startStatusWatch(@NonNull ICameraStatusUpdateNotify notifier);
void stopStatusWatch();
}
ICameraStatusWatcher watcher = currentCoordinator.getStatusWatcher();
if (watcher != null)
{
+ watcher.prepareStatusWatch();
watcher.startStatusWatch(this);
}
}
}
@Override
+ public void updateCaptureMode(String message)
+ {
+ try
+ {
+ setMessage(IShowInformation.AREA_1, Color.WHITE, message);
+ }
+ catch (Exception ee)
+ {
+ ee.printStackTrace();
+ }
+ }
+
+ @Override
public void updateCameraStatus(String message)
{
try
{
- setMessage(IShowInformation.AREA_8, Color.WHITE, message);
+ setMessage(IShowInformation.AREA_5, Color.WHITE, message);
+ }
+ catch (Exception ee)
+ {
+ ee.printStackTrace();
+ }
+ }
+
+ @Override
+ public void updatedExposureCompensation(String xv)
+ {
+ try
+ {
+ setMessage(IShowInformation.AREA_6, Color.WHITE, xv);
}
catch (Exception ee)
{
--- /dev/null
+package jp.sfjp.gokigen.a01c.thetacamerawrapper;
+
+import androidx.annotation.NonNull;
+
+public interface IThetaStatusHolder
+{
+ void setCaptureMode(@NonNull String captureMode);
+ @NonNull String getCaptureMode();
+}
import jp.sfjp.gokigen.a01c.thetacamerawrapper.operation.ThetaSingleShotControl
import jp.sfjp.gokigen.a01c.thetacamerawrapper.status.ThetaCameraStatusWatcher
-class ThetaCameraController(val context: AppCompatActivity, private val focusFrameDisplay: IAutoFocusFrameDisplay, private val showInformation: IShowInformation, private val receiver: ICameraStatusReceiver, private val preferences: PreferenceAccessWrapper) : ICameraController, IIndicatorControl
+class ThetaCameraController(val context: AppCompatActivity, private val focusFrameDisplay: IAutoFocusFrameDisplay, private val showInformation: IShowInformation, private val receiver: ICameraStatusReceiver, private val preferences: PreferenceAccessWrapper) : ICameraController, IIndicatorControl, IThetaSessionIdProvider, IThetaStatusHolder
{
private lateinit var featureDispatcher : ThetaFeatureDispatcher
private lateinit var liveViewControl : ThetaLiveViewControl
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)
- private val statusWatcher = ThetaCameraStatusWatcher()
+ private val optionSet = ThetaOptionUpdateControl(sessionIdHolder)
+ private val statusWatcher = ThetaCameraStatusWatcher(this, this)
+ private var takeMode = "P"
override fun connectFinished()
{
{
if (::featureDispatcher.isInitialized)
{
- when (featureDispatcher.takeMode)
+ Log.v(TAG, " MODE CHANGE FROM $takeMode")
+ when (takeMode)
{
- "P" -> changeCaptureImageMode(sessionIdHolder.isApiLevelV21())
- "Movie" -> changeCaptureVideoMode(sessionIdHolder.isApiLevelV21())
+ "Movie" -> changeCaptureImageMode(sessionIdHolder.isApiLevelV21())
+ "P" -> changeCaptureVideoMode(sessionIdHolder.isApiLevelV21())
}
}
}
+ override fun getCaptureMode() : String
+ {
+ return (takeMode)
+ }
+
+ override fun setCaptureMode(captureMode : String)
+ {
+ when (captureMode) {
+ "image" -> takeMode = "P"
+ "video" -> takeMode = "Movie"
+ "_video" -> takeMode = "Movie"
+ }
+ }
+
private fun changeCaptureImageMode(apiV21 : Boolean)
{
try
{
optionSet.setOptions("\"captureMode\" : \"image\"", apiV21)
- waitMs(200);
+ waitMs(200)
startLiveView()
}
catch (e : Exception)
{
if (!(::featureDispatcher.isInitialized))
{
- featureDispatcher = ThetaFeatureDispatcher(context, statusDrawer, camera, accessWrapper, liveImageView)
+ featureDispatcher = ThetaFeatureDispatcher(context, statusDrawer, camera, accessWrapper, liveImageView, optionSet, sessionIdHolder.isApiLevelV21(), this)
}
return (featureDispatcher)
}
{
private val TAG = ThetaCameraController::class.java.simpleName
}
+
+ override fun getSessionId(): String
+ {
+ return (sessionIdHolder.sessionId)
+ }
}
package jp.sfjp.gokigen.a01c.thetacamerawrapper
-import android.graphics.Color
import android.util.Log
import android.view.MotionEvent
import androidx.appcompat.app.AppCompatActivity
import jp.sfjp.gokigen.a01c.liveview.ILiveImageStatusNotify
import jp.sfjp.gokigen.a01c.olycamerawrapper.property.IOlyCameraProperty
import jp.sfjp.gokigen.a01c.olycamerawrapper.takepicture.IBracketingShotStyle
+import jp.sfjp.gokigen.a01c.thetacamerawrapper.operation.ThetaOptionUpdateControl
-class ThetaFeatureDispatcher(val context: AppCompatActivity, val statusDrawer: IShowInformation, val camera: ICameraController, private val preferences: PreferenceDataStore, val liveImageView: ILiveImageStatusNotify): ICameraFeatureDispatcher
+class ThetaFeatureDispatcher(val context: AppCompatActivity, val statusDrawer: IShowInformation, val camera: ICameraController, private val preferences: PreferenceDataStore, val liveImageView: ILiveImageStatusNotify, val optionSet : ThetaOptionUpdateControl, val useOSCv2 : Boolean, val statusHolder : IThetaStatusHolder): ICameraFeatureDispatcher
{
- private var takeMode : String = "P"
+ private var exposureCompensation : Int = 6
/**
* 指定した機能を実行する
changeTakeMode()
ICameraFeatureDispatcher.FEATURE_CHANGE_TAKEMODE_REVERSE -> // 撮影モードの変更(逆順)
changeTakeModeReverse()
-/*
- ICameraFeatureDispatcher.FEATURE_CHAGE_AE_LOCK_MODE -> // AE LOCKのON/OFF切り替え
- changeAeLockMode()
ICameraFeatureDispatcher.FEATURE_EXPOSURE_BIAS_DOWN -> // 露出補正を1段階下げる
changeExposureBiasValueDown()
ICameraFeatureDispatcher.FEATURE_EXPOSURE_BIAS_UP -> // 露出補正を1段階上げる
changeExposureBiasValueUp()
+/*
+ ICameraFeatureDispatcher.FEATURE_CHAGE_AE_LOCK_MODE -> // AE LOCKのON/OFF切り替え
+ changeAeLockMode()
ICameraFeatureDispatcher.FEATURE_APERTURE_DOWN -> // 絞り値を1段階下げる
changeApertureValueDown()
ICameraFeatureDispatcher.FEATURE_APERTURE_UP -> // 絞り値を1段階上げる
* 撮影モードの取得
*
*/
- override fun getTakeMode(): String?
+ override fun getTakeMode(): String
{
- return (takeMode) // 暫定でプログラムモード
-
- //val propertyProxy = camera.cameraPropertyProvider
- //return propertyProxy.getCameraPropertyValueTitle(propertyProxy.getCameraPropertyValue(IOlyCameraProperty.TAKE_MODE))
+ return (statusHolder.captureMode)
}
/**
* 撮影モードの変更指示
- * (P > A > S > M > ART > movie > iAuto > ...)
*/
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))
- ?: // データ取得失敗
- return
- var targetMode = "<" + IOlyCameraProperty.TAKE_MODE // 変更先モード
- targetMode = when (propetyValue) {
- "P" -> "$targetMode/A>"
- "A" -> "$targetMode/S>"
- "S" -> "$targetMode/M>"
- "M" -> "$targetMode/ART>"
- "ART" -> "$targetMode/movie>"
- "Movie" -> "$targetMode/iAuto>"
- "iAuto" -> "$targetMode/P>"
- else -> "$targetMode/P>"
- }
-
- Log.v(TAG, "changeTakeMode() $targetMode")
- propertyProxy.setCameraPropertyValue(IOlyCameraProperty.TAKE_MODE, targetMode)
- camera.unlockAutoFocus()
-*/
}
/**
private fun changeTakeModeReverse()
{
changeTakeMode()
-/*
- val propertyProxy = camera.cameraPropertyProvider
- val propetyValue = propertyProxy.getCameraPropertyValueTitle(propertyProxy.getCameraPropertyValue(IOlyCameraProperty.TAKE_MODE))
- ?: // データ取得失敗
- return
- var targetMode = "<" + IOlyCameraProperty.TAKE_MODE // 変更先モード
- targetMode = when (propetyValue) {
- "P" -> "$targetMode/iAuto>"
- "A" -> "$targetMode/P>"
- "S" -> "$targetMode/A>"
- "M" -> "$targetMode/S>"
- "ART" -> "$targetMode/M>"
- "Movie" -> "$targetMode/ART>"
- "iAuto" -> "$targetMode/movie>"
- else -> "$targetMode/movie>"
- }
- Log.v(TAG, "changeTakeMode() $targetMode")
- propertyProxy.setCameraPropertyValue(IOlyCameraProperty.TAKE_MODE, targetMode)
- camera.unlockAutoFocus()
-
- // 撮影モードの更新
- //camera.updateTakeMode();
-*/
}
/**
*/
private fun changeExposureBiasValueDown()
{
- val propertyProxy = camera.cameraPropertyProvider
- propertyProxy.updateCameraPropertyDown(IOlyCameraProperty.EXPOSURE_COMPENSATION)
+ try
+ {
+ if (exposureCompensation > 0)
+ {
+ exposureCompensation--
+
+ val optionStr = context.resources.getStringArray(R.array.exposure_compensation_value)[exposureCompensation]
+ optionSet.setOptions(optionStr, useOSCv2)
+ }
+ }
+ catch (e : Exception)
+ {
+ e.printStackTrace()
+ }
}
/**
*/
private fun changeExposureBiasValueUp()
{
- val propertyProxy = camera.cameraPropertyProvider
- propertyProxy.updateCameraPropertyUp(IOlyCameraProperty.EXPOSURE_COMPENSATION)
+ try
+ {
+ if (exposureCompensation < MAX_EXPOSURE_COMPENSATION)
+ {
+ exposureCompensation++
+
+ val optionStr = context.resources.getStringArray(R.array.exposure_compensation_value)[exposureCompensation]
+ optionSet.setOptions(optionStr, useOSCv2)
+ }
+ }
+ catch (e : Exception)
+ {
+ e.printStackTrace()
+ }
}
/**
companion object
{
private val TAG = ThetaFeatureDispatcher::class.java.simpleName
+
+ private const val MAX_EXPOSURE_COMPENSATION = 12 // exposureCompensation
}
}
--- /dev/null
+package jp.sfjp.gokigen.a01c.thetacamerawrapper.operation;
+
+import androidx.annotation.Nullable;
+
+public interface IOperationCallback
+{
+ void operationExecuted(int result, @Nullable String resultStr);
+}
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)
+class ThetaOptionUpdateControl(private val sessionIdProvider: IThetaSessionIdProvider)
{
private val httpClient = SimpleHttpClient()
*
*
*/
- fun setOptions(options: String, useOSCv2 : Boolean)
+ fun setOptions(options: String, useOSCv2: Boolean, callBack: IOperationCallback? = null)
{
Log.v(TAG, "setOptions() useOSCv2 : $useOSCv2 MSG : $options")
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()))
+ if ((result != null) && (result.isNotEmpty()))
{
Log.v(TAG, " setOptions() : $result")
+ callBack?.operationExecuted(0, result)
}
else
{
Log.v(TAG, "setOptions() reply is null or empty.")
+ callBack?.operationExecuted(-1, "")
}
}
catch (e: Exception)
{
e.printStackTrace()
+ callBack?.operationExecuted(-1, e.localizedMessage)
}
}
thread.start()
catch (e: Exception)
{
e.printStackTrace()
+ callBack?.operationExecuted(-1, e.localizedMessage)
}
}
companion object
{
private val TAG = ThetaOptionUpdateControl::class.java.simpleName
- private const val timeoutMs = 3000
+ private const val timeoutMs = 1500
}
-}
\ No newline at end of file
+}
String THETA_SHOOTING_FUNCTION = "_function";
String THETA_CAMERA_ERROR = "_cameraError";
-/*
+ String THETA_APERTURE = "aperture";
+ String THETA_CAPTURE_MODE = "captureMode";
+ String THETA_EXPOSURE_COMPENSATION = "exposureCompensation";
+ String THETA_EXPOSURE_PROGRAM = "exposureProgram";
+ String THETA_ISO_SENSITIVITY = "iso";
+ String THETA_SHUTTER_SPEED = "shutterSpeed";
+ String THETA_WHITE_BALANCE = "whiteBalance";
+
+ /*
String BATTERY = "battery";
String STATE = "state";
String FOCUS_MODE = "focusMode";
import android.util.Log
import jp.sfjp.gokigen.a01c.ICameraStatusUpdateNotify
import jp.sfjp.gokigen.a01c.ICameraStatusWatcher
+import jp.sfjp.gokigen.a01c.thetacamerawrapper.IThetaStatusHolder
+import jp.sfjp.gokigen.a01c.thetacamerawrapper.IThetaSessionIdProvider
import jp.sfjp.gokigen.a01c.thetacamerawrapper.status.ICameraStatus.*
import jp.sfjp.gokigen.a01c.utils.SimpleHttpClient
import org.json.JSONObject
-class ThetaCameraStatusWatcher : ICameraStatus, ICameraStatusWatcher
+class ThetaCameraStatusWatcher(private val sessionIdProvider: IThetaSessionIdProvider, private val statusHolder : IThetaStatusHolder) : ICameraStatus, ICameraStatusWatcher
{
private val httpClient = SimpleHttpClient()
private var whileFetching = false
private var currentBatteryLevel : Double = 0.0
+ private var currentExposureCompensation : Double = 0.0
+ private var currentCaptureMode : String = ""
private var currentCaptureStatus : String = ""
private var currentBatteryStatus : String = ""
+ private var currentWhiteBalance : String = ""
override fun getStatusList(key: String): List<String>
{
- return (ArrayList<String>())
+ return (ArrayList())
}
override fun getStatus(key: String): String
override fun startStatusWatch(notifier: ICameraStatusUpdateNotify)
{
+ startStatusWatch1(notifier)
+ }
+
+ private fun startStatusWatch1(notifier: ICameraStatusUpdateNotify)
+ {
+ if (whileFetching)
+ {
+ Log.v(TAG, "startStatusWatch() already starting.")
+ return
+ }
+ whileFetching = true
+ try
+ {
+ val thread = Thread {
+ try
+ {
+ val getOptionsUrl = "http://192.168.1.1/osc/commands/execute"
+ val postData = if (sessionIdProvider.sessionId.isEmpty()) "{\"name\":\"camera.getOptions\",\"parameters\":{\"timeout\":0, \"optionNames\" : [ \"aperture\",\"captureMode\",\"exposureCompensation\",\"exposureProgram\",\"iso\",\"shutterSpeed\",\"whiteBalance\"] }" else "{\"name\":\"camera.getOptions\",\"parameters\":{\"sessionId\": \"" + sessionIdProvider.sessionId + "\", \"optionNames\" : [ \"aperture\",\"captureMode\",\"exposureCompensation\",\"exposureProgram\",\"iso\",\"shutterSpeed\",\"whiteBalance\"] }}"
+
+ Log.v(TAG, " >>>>> START STATUS WATCH : $getOptionsUrl $postData")
+ while (whileFetching)
+ {
+ val response: String? = httpClient.httpPostWithHeader(getOptionsUrl, postData, null, "application/json;charset=utf-8", timeoutMs)
+ if (!(response.isNullOrEmpty()))
+ {
+ // ステータスデータ受信
+ checkStatus1(response, notifier)
+ }
+ try
+ {
+ Thread.sleep(loopWaitMs)
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+ thread.start()
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+ private fun checkStatus1(response : String, notifier: ICameraStatusUpdateNotify)
+ {
+ try
+ {
+ //Log.v(TAG, " STATUS : $response")
+ val stateObject = JSONObject(response).getJSONObject("results").getJSONObject("options")
+ try
+ {
+ val exposureCompensation = stateObject.getDouble(THETA_EXPOSURE_COMPENSATION)
+ if (exposureCompensation != currentExposureCompensation)
+ {
+ Log.v(TAG, " EXPREV : $currentExposureCompensation => $exposureCompensation")
+ currentExposureCompensation = exposureCompensation
+ notifier.updatedExposureCompensation(String.format("%1.1f",currentExposureCompensation))
+ }
+ }
+ catch (e : Exception)
+ {
+ e.printStackTrace()
+ }
+
+ try
+ {
+ val whiteBalance = stateObject.getString(THETA_WHITE_BALANCE)
+ if (whiteBalance != currentWhiteBalance)
+ {
+ Log.v(TAG, " WB : $currentWhiteBalance => $whiteBalance")
+ currentWhiteBalance = whiteBalance
+ }
+ }
+ catch (e : Exception)
+ {
+ e.printStackTrace()
+ }
+
+ try
+ {
+ val captureMode = stateObject.getString(THETA_CAPTURE_MODE)
+ if (captureMode != currentCaptureMode)
+ {
+ Log.v(TAG, " CAPTURE MODE : $currentCaptureMode -> $captureMode")
+ notifier.updateCaptureMode(captureMode)
+ currentCaptureMode = captureMode
+ statusHolder.setCaptureMode(captureMode)
+ }
+ }
+ catch (e : Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+ catch (ee : Exception)
+ {
+ ee.printStackTrace()
+ }
+ }
+
+
+ private fun startStatusWatch0(notifier: ICameraStatusUpdateNotify)
+ {
if (whileFetching)
{
Log.v(TAG, "startStatusWatch() already starting.")
if (!(response.isNullOrEmpty()))
{
// ステータスデータ受信
- checkStatus(response, notifier)
+ checkStatus0(response, notifier)
}
try
{
- Thread.sleep(300)
+ Thread.sleep(loopWaitMs)
}
catch (e: Exception)
{
}
}
- private fun checkStatus(response : String, notifier: ICameraStatusUpdateNotify)
+ private fun checkStatus0(response : String, notifier: ICameraStatusUpdateNotify)
{
try
{
whileFetching = false
}
+ override fun prepareStatusWatch()
+ {
+ //
+ }
+
companion object
{
private val TAG = ThetaCameraStatusWatcher::class.java.simpleName
private const val timeoutMs = 1500
+ private const val loopWaitMs : Long = 660
}
-
-}
\ No newline at end of file
+}
<item >OPC</item>
<item >THETA</item>
</string-array>
+
+ <string-array name="exposure_compensation">
+ <item>-2.0</item>
+ <item>-1.7</item>
+ <item>-1.3</item>
+ <item>-1.0</item>
+ <item>-0.7</item>
+ <item>-0.3</item>
+ <item>0.0</item>
+ <item>0.3</item>
+ <item>0.7</item>
+ <item>1.0</item>
+ <item>1.3</item>
+ <item>1.7</item>
+ <item>2.0</item>
+ </string-array>
+
+ <string-array name="exposure_compensation_value">
+ <item>"exposureCompensation" : -2.0</item>
+ <item>"exposureCompensation" : -1.7</item>
+ <item>"exposureCompensation" : -1.3</item>
+ <item>"exposureCompensation" : -1.0</item>
+ <item>"exposureCompensation" : -0.7</item>
+ <item>"exposureCompensation" : -0.3</item>
+ <item>"exposureCompensation" : 0.0</item>
+ <item>"exposureCompensation" : 0.3</item>
+ <item>"exposureCompensation" : 0.7</item>
+ <item>"exposureCompensation" : 1.0</item>
+ <item>"exposureCompensation" : 1.3</item>
+ <item>"exposureCompensation" : 1.7</item>
+ <item>"exposureCompensation" : 2.0</item>
+ </string-array>
+
</resources>
\ No newline at end of file