import jp.sfjp.gokigen.a01c.olycamerawrapper.property.ILoadSaveCameraProperties;
import jp.sfjp.gokigen.a01c.olycamerawrapper.property.IOlyCameraPropertyProvider;
import jp.sfjp.gokigen.a01c.olycamerawrapper.property.ICameraPropertyLoadSaveOperations;
-import jp.sfjp.gokigen.a01c.preference.PreferenceAccessWrapper;
/**
*
/** ムービー撮影機能の実行(開始・終了) **/
void movieControl();
+ /** ブラケット撮影(開始・終了) **/
+ void bracketingControl();
+
/** インターバル&ブラケッティング撮影の実行 **/
void bracketingShot(int bracketingStyle, int bracketingCount, int durationSeconds);
package jp.sfjp.gokigen.a01c;
+import androidx.annotation.NonNull;
+
/**
*
*/
void setEnabledOperation(operation operation);
void showFavoriteSettingsDialog();
+
+ void showToast(int rscId, @NonNull String appendMessage, int duration);
+
+ void invalidate();
}
import android.widget.TextView;
import android.Manifest;
import android.content.pm.PackageManager;
+import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import jp.sfjp.gokigen.a01c.liveview.CameraLiveViewListenerImpl;
import jp.sfjp.gokigen.a01c.liveview.dialog.FavoriteSettingSelectionDialog;
import jp.sfjp.gokigen.a01c.liveview.dialog.IDialogDismissedNotifier;
-import jp.sfjp.gokigen.a01c.olycamerawrapper.dispatcher.FeatureDispatcher;
import jp.sfjp.gokigen.a01c.liveview.ICameraStatusReceiver;
import jp.sfjp.gokigen.a01c.liveview.IMessageDrawer;
import jp.sfjp.gokigen.a01c.liveview.CameraLiveViewOnTouchListener;
liveView = findViewById(R.id.liveview);
}
olyAirCoordinator = new OlyCameraCoordinator(this, liveView, this, this);
- thetaCoordinator = new ThetaCameraController(this, liveView, this, this, preferences);
+ thetaCoordinator = new ThetaCameraController(this, this, this);
currentCoordinator = (connectionMethod.contains(IPreferenceCameraPropertyAccessor.CONNECTION_METHOD_THETA)) ? thetaCoordinator : olyAirCoordinator;
currentCoordinator.setLiveViewListener(new CameraLiveViewListenerImpl(liveView));
listener = new CameraLiveViewOnTouchListener(this, currentCoordinator.getFeatureDispatcher(this, this, currentCoordinator, preferences, liveView), this);
}
}
+ @Override
+ public void showToast(final int rscId, @NonNull final String appendMessage, final int duration)
+ {
+ try
+ {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ try
+ {
+ String message = (rscId != 0) ? getString(rscId) + appendMessage : appendMessage;
+ Toast.makeText(getApplicationContext(), message, duration).show();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+ });
+
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void invalidate()
+ {
+ try
+ {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (liveView != null)
+ {
+ liveView.invalidate();
+ }
+ }
+ });
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
/**
* 「お気に入り設定」表示画面を閉じる
*
}
/**
+ * ブラケット撮影
+ *
+ */
+ @Override
+ public void bracketingControl()
+ {
+ // ダミー
+ }
+
+ /**
* インターバル&ブラケッティング撮影の実行
*
* @param bracketingStyle : ブラケッティングスタイル
import androidx.preference.PreferenceDataStore
import jp.sfjp.gokigen.a01c.*
import jp.sfjp.gokigen.a01c.liveview.CameraLiveViewListenerImpl
-import jp.sfjp.gokigen.a01c.liveview.IAutoFocusFrameDisplay
import jp.sfjp.gokigen.a01c.liveview.ICameraStatusReceiver
import jp.sfjp.gokigen.a01c.liveview.ILiveImageStatusNotify
import jp.sfjp.gokigen.a01c.olycamerawrapper.ICameraRunMode
import jp.sfjp.gokigen.a01c.olycamerawrapper.property.ICameraPropertyLoadSaveOperations
import jp.sfjp.gokigen.a01c.olycamerawrapper.property.ILoadSaveCameraProperties
import jp.sfjp.gokigen.a01c.olycamerawrapper.property.IOlyCameraPropertyProvider
-import jp.sfjp.gokigen.a01c.preference.PreferenceAccessWrapper
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 jp.sfjp.gokigen.a01c.thetacamerawrapper.operation.*
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, IThetaSessionIdProvider, IThetaStatusHolder
+class ThetaCameraController(val context: AppCompatActivity, showInformation: IShowInformation, receiver: ICameraStatusReceiver) : ICameraController, IIndicatorControl, IThetaSessionIdProvider, IThetaStatusHolder
{
private lateinit var featureDispatcher : ThetaFeatureDispatcher
private lateinit var liveViewControl : ThetaLiveViewControl
private val dummyOperation = ThetaDummyOperation()
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 singleShot = ThetaSingleShotControl(sessionIdHolder, showInformation, this)
+ private val movieShot = ThetaMovieRecordingControl(context, sessionIdHolder, showInformation, this)
+ private val bracketShot = ThetaBracketingControl(context, sessionIdHolder, showInformation, this)
private val optionSet = ThetaOptionUpdateControl(sessionIdHolder)
private val statusWatcher = ThetaCameraStatusWatcher(this, this, showInformation)
private var takeMode = "P"
optionSet.setOptions("\"captureMode\" : \"_video\"", apiV21)
// API Level 1 の対応機種では、Videoモードでライブビューが動かないので止める
- waitMs(200);
+ waitMs(200)
stopLiveView()
}
}
movieShot.movieControl(sessionIdHolder.isApiLevelV21())
}
+ override fun bracketingControl()
+ {
+ bracketShot.bracketingControl(sessionIdHolder.isApiLevelV21())
+ }
+
override fun bracketingShot(bracketingStyle: Int, bracketingCount: Int, durationSeconds: Int)
{
// TODO("Not yet implemented")
changeIsoSensitivityDown()
ICameraFeatureDispatcher.FEATURE_ISO_UP -> // ISO感度を選択
changeIsoSensitivityUp()
+ ICameraFeatureDispatcher.FEATURE_SHOT_BRACKET_EXPOSURE -> // ブラケット撮影
+ bracketingControl()
else -> // 上記以外...なにもしない
duration = IShowInformation.VIBRATE_PATTERN_NONE
}
}
/**
+ * ブラケット撮影・停止を行う
+ *
+ */
+ private fun bracketingControl()
+ {
+ camera.bracketingControl()
+ }
+
+ /**
* フィルター
*
*/
{
try
{
- if (thetaShutterSpeedIndex > MAX_SHUTTER_SPEED)
+ if (thetaShutterSpeedIndex < MAX_SHUTTER_SPEED)
{
thetaShutterSpeedIndex++
{
try
{
- if (thetaIsoSensitivityIndex == MAX_ISO_SENSITIVITY)
+ thetaIsoSensitivityIndex++
+ if (thetaIsoSensitivityIndex > MAX_ISO_SENSITIVITY)
{
thetaIsoSensitivityIndex = 0
}
- else
- {
- thetaIsoSensitivityIndex++
- }
val optionStr = context.resources.getStringArray(R.array.theta_iso_sensitivity_value)[thetaIsoSensitivityIndex]
optionSet.setOptions(optionStr, sessionIdProvider.sessionId.isEmpty())
}
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)
+class ThetaBracketingControl(val context: Context, private val sessionIdProvider: IThetaSessionIdProvider, private val statusDrawer: IShowInformation, private val liveViewControl: ICameraController)
{
private val httpClient = SimpleHttpClient()
private var isCapturing = false
if (!(isCapturing))
{
startCapture(useOSCv2)
- statusDrawer.setMessage(IShowInformation.AREA_9, Color.RED, context.getString(R.string.video_recording))
+ statusDrawer.setMessage(IShowInformation.AREA_9, Color.YELLOW, context.getString(R.string.capturing))
}
else
{
stopCapture(useOSCv2)
statusDrawer.setMessage(IShowInformation.AREA_9, Color.WHITE, "")
}
+ statusDrawer.invalidate()
isCapturing = !isCapturing
}
catch (e: Exception)
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\"}}}"
-
+// val postData = if (useOSCv2) "{\"name\":\"camera.startCapture\",\"parameters\":{\"timeout\":0, \"mode\":\"bracket\"}}" else "{\"name\":\"camera._startCapture\",\"parameters\":{\"sessionId\": \"" + sessionIdProvider.sessionId + "\", \"mode\":\"bracket\"}}"
+// val postData = if (useOSCv2) "{\"name\":\"camera.startCapture\",\"parameters\":{\"timeout\":0, \"mode\":\"composite\"}}" else "{\"name\":\"camera._startCapture\",\"parameters\":{\"sessionId\": \"" + sessionIdProvider.sessionId + "\", \"mode\":\"composite\"}}"
+ val postData = if (useOSCv2) "{\"name\":\"camera.startCapture\",\"parameters\":{\"timeout\":0, \"mode\":\"interval\"}}" else "{\"name\":\"camera._startCapture\",\"parameters\":{\"sessionId\": \"" + sessionIdProvider.sessionId + "\", \"mode\":\"interval\"}}"
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()
+/*
+ if (!useOSCv2)
+ {
+ liveViewControl.stopLiveView()
+ waitMs(300) // ちょっと待つ...
+ liveViewControl.startLiveView()
+ }
+*/
}
else
{
- Log.v(TAG, "startCapture() reply is null.")
+ Log.v(TAG, "startCapture() reply is null. $postData")
}
}
catch (e: Exception)
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()
+ if (!useOSCv2)
+ {
+ // THETA V / THETA Z1 は、videoモードでライブビューができるので...
+ liveViewControl.stopLiveView()
+ waitMs() // ちょっと待つ...
+ liveViewControl.startLiveView()
+ }
}
else
{
- Log.v(TAG, "stopCapture() reply is null.")
+ Log.v(TAG, "stopCapture() reply is null. $postData")
}
}
catch (e: Exception)
}
/**
- * 撮影状態が変わるまで待つ。
- * (ただし、タイムアウト時間を超えたらライブビューを再開させる)
- */
- 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)
+ private fun waitMs(waitMs: Int = 300)
{
try
{
private val TAG = ThetaBracketingControl::class.java.simpleName
private const val timeoutMs = 6000
}
-
-}
\ No newline at end of file
+}
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)
+class ThetaMovieRecordingControl(val context: Context, private val sessionIdProvider: IThetaSessionIdProvider, private val statusDrawer: IShowInformation, private val liveViewControl: ICameraController)
{
private val httpClient = SimpleHttpClient()
private var isCapturing = false
stopCapture(useOSCv2)
statusDrawer.setMessage(IShowInformation.AREA_9, Color.WHITE, "")
}
+ statusDrawer.invalidate()
isCapturing = !isCapturing
}
catch (e: Exception)
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)
}
else
{
- Log.v(TAG, "startCapture() reply is null.")
+ Log.v(TAG, "startCapture() reply is null. $postData")
}
}
catch (e: Exception)
if ((result != null)&&(result.isNotEmpty()))
{
Log.v(TAG, " stopCapture() : $result")
- indicator.onShootingStatusUpdate(IIndicatorControl.shootingStatus.Starting)
-
- //// 画像処理が終わるまで待つ
- //waitChangeStatus()
-
- // ライブビューのの再実行を指示する
- indicator.onShootingStatusUpdate(IIndicatorControl.shootingStatus.Stopping)
- if (useOSCv2)
+ if (!useOSCv2)
{
// THETA V / THETA Z1 は、videoモードでライブビューができるので...
liveViewControl.stopLiveView()
- waitMs(300) // ちょっと待つ...
+ waitMs() // ちょっと待つ...
liveViewControl.startLiveView()
}
}
else
{
- Log.v(TAG, "stopCapture() reply is null.")
+ Log.v(TAG, "stopCapture() reply is null. $postData")
}
}
catch (e: Exception)
}
/**
- * 撮影状態が変わるまで待つ。
- * (ただし、タイムアウト時間を超えたらライブビューを再開させる)
- */
- 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)
+ private fun waitMs(waitMs: Int = 300)
{
try
{
package jp.sfjp.gokigen.a01c.thetacamerawrapper.operation
import android.util.Log
+import android.widget.Toast
import jp.sfjp.gokigen.a01c.ICameraController
-import jp.sfjp.gokigen.a01c.olycamerawrapper.IIndicatorControl
+import jp.sfjp.gokigen.a01c.IShowInformation
+import jp.sfjp.gokigen.a01c.R
import jp.sfjp.gokigen.a01c.thetacamerawrapper.IThetaSessionIdProvider
import jp.sfjp.gokigen.a01c.utils.SimpleHttpClient
import org.json.JSONObject
-class ThetaSingleShotControl(private val sessionIdProvider: IThetaSessionIdProvider, private val indicator: IIndicatorControl, private val liveViewControl: ICameraController)
+class ThetaSingleShotControl(private val sessionIdProvider: IThetaSessionIdProvider, private val showInformation: IShowInformation, private val liveViewControl: ICameraController)
{
private val httpClient = SimpleHttpClient()
if ((result != null)&&(result.isNotEmpty()))
{
Log.v(TAG, " singleShot() : $result")
- indicator.onShootingStatusUpdate(IIndicatorControl.shootingStatus.Starting)
// 画像処理が終わるまで待つ
waitChangeStatus()
+ // 撮影成功をバイブレータで知らせる
+ showInformation.vibrate(IShowInformation.VIBRATE_PATTERN_SIMPLE_MIDDLE)
+
+ // 撮影成功の表示をToastで行う
+ showInformation.showToast(R.string.shoot_camera, "", Toast.LENGTH_SHORT)
+
// ライブビューのの再実行を指示する
- indicator.onShootingStatusUpdate(IIndicatorControl.shootingStatus.Stopping)
liveViewControl.stopLiveView()
waitMs(300) // ちょっと待つ...
liveViewControl.startLiveView()
{
showInformation.setMessage(IShowInformation.AREA_8, Color.WHITE, captureStatus)
}
+ else
+ {
+ showInformation.setMessage(IShowInformation.AREA_8, Color.WHITE, "")
+ }
+ showInformation.invalidate()
currentCaptureStatus = captureStatus
}
}
Log.v(TAG, " BATTERY : $currentBatteryLevel => $batteryLevel")
currentBatteryLevel = batteryLevel
updateRemainBattery(currentBatteryLevel)
+ showInformation.invalidate()
}
}
catch (e: Exception)
companion object
{
private val TAG = ThetaCameraStatusWatcher::class.java.simpleName
- private const val timeoutMs = 1500
+ private const val timeoutMs = 3300
private const val loopWaitMs : Long = 450
}
}
<string name="shoot_camera">撮影!</string>
<string name="shoot_camera_failure">失敗です…</string>
<string name="video_recording">●REC</string>
+ <string name="capturing">CAPTURE</string>
<string name="video_failure">失敗です…</string>
<string name="message_none">---</string>
<string name="shoot_camera">Capture!</string>
<string name="shoot_camera_failure">FAILED!</string>
<string name="video_recording">●REC</string>
+ <string name="capturing">CAPTURE</string>
<string name="video_failure">FAILED!</string>
<string name="message_none">---</string>