From b680ded108793d08c5b04f9ba360ad20802b6254 Mon Sep 17 00:00:00 2001 From: MRSa Date: Sat, 18 Sep 2021 18:04:59 +0900 Subject: [PATCH] =?utf8?q?OMDS=E7=B3=BB=E3=81=AE=E3=82=AB=E3=83=A1?= =?utf8?q?=E3=83=A9=E5=88=B6=E5=BE=A1=E3=83=AD=E3=82=B8=E3=83=83=E3=82=AF?= =?utf8?q?=E3=82=92=E8=BF=BD=E5=8A=A0=E3=80=82(=E5=8B=95=E4=BD=9C=E7=B5=84?= =?utf8?q?=E3=81=BF=E8=BE=BC=E3=81=BF=E3=81=AF=E3=81=BE=E3=81=A0=E3=80=82)?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- .idea/deploymentTargetDropDown.xml | 17 -- .idea/dictionaries/MRSa.xml | 1 + .../camera/vendor/omds/OmdsCameraControl.kt | 252 ++++++++++++++++++ .../omds/connection/OmdsCameraConnectSequence.kt | 87 +++++++ .../vendor/omds/connection/OmdsCameraConnection.kt | 197 ++++++++++++++ .../connection/OmdsCameraDisconnectSequence.kt | 43 +++ .../vendor/omds/liveview/OmdsLiveViewControl.kt | 288 +++++++++++++++++++++ .../vendor/omds/operation/OmdsAutoFocusControl.kt | 210 +++++++++++++++ .../vendor/omds/operation/OmdsCameraPowerOff.kt | 48 ++++ .../vendor/omds/operation/OmdsSingleShotControl.kt | 55 ++++ .../vendor/omds/status/OmdsCameraStatusWatcher.kt | 167 ++++++++++++ .../vendor/omds/wrapper/OmdsCaptureControl.kt | 33 +++ .../camera/vendor/omds/wrapper/OmdsFocusControl.kt | 75 ++++++ .../camera/vendor/omds/wrapper/OmdsRunMode.kt | 70 +++++ .../vendor/omds/wrapper/OmdsZoomLensControl.kt | 110 ++++++++ .../messages/specific/PixproExecuteShutter.kt | 3 + 16 files changed, 1639 insertions(+), 17 deletions(-) delete mode 100644 .idea/deploymentTargetDropDown.xml create mode 100644 app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/OmdsCameraControl.kt create mode 100644 app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/connection/OmdsCameraConnectSequence.kt create mode 100644 app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/connection/OmdsCameraConnection.kt create mode 100644 app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/connection/OmdsCameraDisconnectSequence.kt create mode 100644 app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/liveview/OmdsLiveViewControl.kt create mode 100644 app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/operation/OmdsAutoFocusControl.kt create mode 100644 app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/operation/OmdsCameraPowerOff.kt create mode 100644 app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/operation/OmdsSingleShotControl.kt create mode 100644 app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/status/OmdsCameraStatusWatcher.kt create mode 100644 app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/wrapper/OmdsCaptureControl.kt create mode 100644 app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/wrapper/OmdsFocusControl.kt create mode 100644 app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/wrapper/OmdsRunMode.kt create mode 100644 app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/wrapper/OmdsZoomLensControl.kt diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml deleted file mode 100644 index 67a3249..0000000 --- a/.idea/deploymentTargetDropDown.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/dictionaries/MRSa.xml b/.idea/dictionaries/MRSa.xml index 3db6b5e..8a8765b 100644 --- a/.idea/dictionaries/MRSa.xml +++ b/.idea/dictionaries/MRSa.xml @@ -8,6 +8,7 @@ liveview mpget mpset + omds pixpro recmode ricoh diff --git a/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/OmdsCameraControl.kt b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/OmdsCameraControl.kt new file mode 100644 index 0000000..fcf249b --- /dev/null +++ b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/OmdsCameraControl.kt @@ -0,0 +1,252 @@ +package jp.osdn.gokigen.gokigenassets.camera.vendor.omds + +import android.util.Log +import android.view.KeyEvent +import android.view.View +import androidx.appcompat.app.AppCompatActivity +import jp.osdn.gokigen.gokigenassets.camera.interfaces.* +import jp.osdn.gokigen.gokigenassets.camera.preference.ICameraPreferenceProvider +import jp.osdn.gokigen.gokigenassets.camera.vendor.omds.connection.OmdsCameraConnection +import jp.osdn.gokigen.gokigenassets.camera.vendor.omds.liveview.OmdsLiveViewControl +import jp.osdn.gokigen.gokigenassets.camera.vendor.omds.status.OmdsCameraStatusWatcher +import jp.osdn.gokigen.gokigenassets.camera.vendor.omds.wrapper.OmdsCaptureControl +import jp.osdn.gokigen.gokigenassets.camera.vendor.omds.wrapper.OmdsFocusControl +import jp.osdn.gokigen.gokigenassets.constants.IApplicationConstantConvert +import jp.osdn.gokigen.gokigenassets.constants.ICameraConstantConvert +import jp.osdn.gokigen.gokigenassets.liveview.ICachePositionProvider +import jp.osdn.gokigen.gokigenassets.liveview.IIndicatorControl +import jp.osdn.gokigen.gokigenassets.liveview.ILiveView +import jp.osdn.gokigen.gokigenassets.liveview.ILiveViewRefresher +import jp.osdn.gokigen.gokigenassets.liveview.focusframe.IAutoFocusFrameDisplay +import jp.osdn.gokigen.gokigenassets.liveview.image.CameraLiveViewListenerImpl +import jp.osdn.gokigen.gokigenassets.liveview.storeimage.StoreImage +import jp.osdn.gokigen.gokigenassets.preference.PreferenceAccessWrapper +import jp.osdn.gokigen.gokigenassets.scene.IInformationReceiver +import jp.osdn.gokigen.gokigenassets.scene.IVibrator + +class OmdsCameraControl(private val context: AppCompatActivity, private val vibrator: IVibrator, informationNotify : IInformationReceiver, private val preference: ICameraPreferenceProvider, provider: ICameraStatusReceiver) : ICameraControl, View.OnClickListener, View.OnLongClickListener, ICameraShutter, IKeyDown, IDisplayInjector +{ + private val liveViewListener = CameraLiveViewListenerImpl(context, informationNotify) + private val statusChecker = OmdsCameraStatusWatcher() + private val cameraConnection = OmdsCameraConnection(context, provider) + private val storeImage = StoreImage(context, liveViewListener) + + private lateinit var liveViewControl : OmdsLiveViewControl + private lateinit var cachePositionProvider : ICachePositionProvider + private lateinit var focusControl: OmdsFocusControl + private lateinit var captureControl: OmdsCaptureControl + + private var cameraPositionId = 0 + + override fun getConnectionMethod(): String + { + return ("OMDS") + } + + override fun initialize() + { + Log.v(TAG, " --- initialize() : SEQ : ${preference.getConnectionSequence()}") + } + + override fun connectToCamera() + { + Log.v(TAG, " connectToCamera() : OMDS ") + try + { + cameraConnection.connect() + } + catch (e : Exception) + { + e.printStackTrace() + } + } + + override fun startCamera(isPreviewView: Boolean, cameraSequence : Int) + { + try + { + if (cameraConnection.getConnectionStatus() != ICameraConnectionStatus.CameraConnectionStatus.CONNECTED) + { + cameraConnection.startWatchWifiStatus(context) + } + else + { + cameraConnection.connect() + } + } + catch (e : Exception) + { + e.printStackTrace() + } + } + + override fun finishCamera() + { + try + { + if (::liveViewControl.isInitialized) + { + liveViewControl.stopLiveView() + } + statusChecker.stopStatusWatch() + cameraConnection.disconnect(false) + cameraConnection.stopWatchWifiStatus(context) + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + override fun changeCaptureMode(mode: String) { } + override fun needRotateImage(): Boolean { return (false) } + override fun setRefresher(id : Int, refresher: ILiveViewRefresher, imageView: ILiveView, cachePosition : ICachePositionProvider) + { + try + { + liveViewListener.setRefresher(refresher) + imageView.setImageProvider(liveViewListener) + cachePositionProvider = cachePosition + } + catch (e : Exception) + { + e.printStackTrace() + } + } + + override fun captureButtonReceiver(id: Int): View.OnClickListener + { + cameraPositionId = id + return (this) + } + + override fun onLongClickReceiver(id: Int): View.OnLongClickListener + { + cameraPositionId = id + return (this) + } + + override fun keyDownReceiver(id: Int): IKeyDown + { + cameraPositionId = id + return (this) + } + + override fun getFocusingControl(id: Int): IFocusingControl + { + cameraPositionId = id + return (focusControl) + } + + override fun getDisplayInjector(): IDisplayInjector + { + return (this) + } + + override fun injectDisplay(frameDisplayer: IAutoFocusFrameDisplay, indicator: IIndicatorControl, focusingModeNotify: IFocusingModeNotify) + { + Log.v(TAG, "injectDisplay()") + focusControl = OmdsFocusControl(frameDisplayer, indicator) + captureControl = OmdsCaptureControl(frameDisplayer, indicator, statusChecker) + } + + override fun setNeighborCameraControl(camera0: ICameraControl?, camera1: ICameraControl?, camera2: ICameraControl?, camera3: ICameraControl?) { } + override fun getCameraStatus(): ICameraStatus { return (statusChecker) } + + override fun onClick(v: View?) + { + if (v == null) + { + return + } + when (v.id) + { + IApplicationConstantConvert.ID_BUTTON_SHUTTER -> { doShutter() } + else -> { } + } + } + + override fun handleKeyDown(keyCode: Int, event: KeyEvent): Boolean + { + if ((event.action == KeyEvent.ACTION_DOWN)&&((keyCode == KeyEvent.KEYCODE_VOLUME_UP)||(keyCode == KeyEvent.KEYCODE_CAMERA))) + { + doShutter() + return (true) + } + return (false) + } + + override fun onLongClick(v: View?): Boolean + { + return (false) + } + + override fun doShutter() + { + try + { + Log.v(TAG, " doShutter()") + val isNotDriveShutter = captureImageLiveView() + if (isNotDriveShutter) + { + // シャッターを駆動させない(けど、バイブレーションで通知する) + vibrator.vibrate(IVibrator.VibratePattern.SIMPLE_SHORT) + return + } + captureControl.doCapture(0) + } + catch (e : Exception) + { + e.printStackTrace() + } + } + + override fun doShutterOff() + { + try + { + Log.v(TAG, " doShutterOff()") + captureControl.doCapture(0) + } + catch (e : Exception) + { + e.printStackTrace() + } + } + + private fun captureImageLiveView() : Boolean + { + try + { + // preferenceから設定を取得する + val captureBothCamera = PreferenceAccessWrapper(context).getBoolean( + IApplicationConstantConvert.ID_PREFERENCE_CAPTURE_BOTH_CAMERA_AND_LIVE_VIEW, IApplicationConstantConvert.ID_PREFERENCE_CAPTURE_BOTH_CAMERA_AND_LIVE_VIEW_DEFAULT_VALUE) + val notUseShutter = PreferenceAccessWrapper(context).getBoolean( + IApplicationConstantConvert.ID_PREFERENCE_CAPTURE_ONLY_LIVEVIEW_IMAGE, IApplicationConstantConvert.ID_PREFERENCE_CAPTURE_ONLY_LIVEVIEW_IMAGE_DEFAULT_VALUE) + if ((captureBothCamera)&&(liveViewListener.isImageReceived())) + { + // ライブビュー画像を保管する場合... + val thread = Thread { storeImage.doStore(cameraPositionId, false, cachePositionProvider.getCachePosition()) } + try + { + thread.start() + } + catch (e: Exception) + { + e.printStackTrace() + } + } + return (notUseShutter) + } + catch (e : Exception) + { + e.printStackTrace() + } + return (false) + } + + companion object + { + private val TAG = OmdsCameraControl::class.java.simpleName + } +} diff --git a/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/connection/OmdsCameraConnectSequence.kt b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/connection/OmdsCameraConnectSequence.kt new file mode 100644 index 0000000..a9b74a0 --- /dev/null +++ b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/connection/OmdsCameraConnectSequence.kt @@ -0,0 +1,87 @@ +package jp.osdn.gokigen.gokigenassets.camera.vendor.omds.connection + +import android.util.Log +import androidx.appcompat.app.AppCompatActivity +import jp.osdn.gokigen.gokigenassets.camera.interfaces.ICameraConnection +import jp.osdn.gokigen.gokigenassets.camera.interfaces.ICameraConnectionStatus +import jp.osdn.gokigen.gokigenassets.camera.interfaces.ICameraStatusReceiver +import jp.osdn.gokigen.gokigenassets.constants.ICameraConstantConvert +import jp.osdn.gokigen.gokigenassets.utils.communication.SimpleHttpClient +import java.lang.Exception +import java.util.HashMap + +class OmdsCameraConnectSequence(private val context: AppCompatActivity, private val cameraStatusReceiver: ICameraStatusReceiver, private val cameraConnection : ICameraConnection, private val liveViewQuality : String = "0640x0480", private val executeUrl : String = "http://192.168.0.10") : Runnable +{ + private val headerMap: MutableMap = HashMap() + private val http = SimpleHttpClient() + + override fun run() + { + val camInfoUrl = "$executeUrl/get_caminfo.cgi" + val getCommandListUrl = "$executeUrl/get_commandlist.cgi" + val getConnectModeUrl = "$executeUrl/get_connectmode.cgi" + val switchCameraModeUrl = "$executeUrl/switch_cammode.cgi" + //final String getCameraStatusUrl = "$executeUrl/get_activate.cgi"; + try + { + val response: String = http.httpGetWithHeader(getConnectModeUrl, headerMap, null, TIMEOUT_MS) ?: "" + Log.v(TAG, " $getConnectModeUrl $response") + if (response.isNotEmpty()) + { + val response2: String = http.httpGetWithHeader(getCommandListUrl, headerMap, null, TIMEOUT_MS) ?: "" + Log.v(TAG, " $getCommandListUrl $response2") + val response3: String = http.httpGetWithHeader(camInfoUrl, headerMap, null, TIMEOUT_MS) ?: "" + Log.v(TAG, " $camInfoUrl $response3") + + // 撮影モードに切り替え。 + val lvUrl = "$switchCameraModeUrl?mode=rec&lvqty=$liveViewQuality" + val response4: String = http.httpGetWithHeader(lvUrl, headerMap, null, TIMEOUT_MS) ?: "" + Log.v(TAG, " $lvUrl $response4") + + //// カメラのステータス取得 + //String response5 = SimpleHttpClient.httpGetWithHeader(getCameraStatusUrl, headerMap, null, TIMEOUT_MS); + //Log.v(TAG, " " + getCameraStatusUrl + " " + response5); + onConnectNotify() + } + else + { + cameraConnection.alertConnectingFailed(context.getString(ICameraConstantConvert.ID_STRING_CAMERA_NOT_FOUND)) + } + } + catch (e: Exception) + { + e.printStackTrace() + cameraConnection.alertConnectingFailed(e.localizedMessage) + } + } + + private fun onConnectNotify() + { + try + { + val thread = Thread { // カメラとの接続確立を通知する + cameraStatusReceiver.onStatusNotify(context.getString(ICameraConstantConvert.ID_STRING_CONNECT_CONNECTED)) + cameraStatusReceiver.onCameraConnected() + Log.v(TAG, "onConnectNotify()") + cameraConnection.forceUpdateConnectionStatus(ICameraConnectionStatus.CameraConnectionStatus.CONNECTED) + } + thread.start() + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + init + { + headerMap["User-Agent"] = "OlympusCameraKit" // "OI.Share" + headerMap["X-Protocol"] = "OlympusCameraKit" // "OI.Share" + } + + companion object + { + private val TAG = OmdsCameraConnectSequence::class.java.simpleName + private const val TIMEOUT_MS = 5000 + } +} diff --git a/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/connection/OmdsCameraConnection.kt b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/connection/OmdsCameraConnection.kt new file mode 100644 index 0000000..e4ed59f --- /dev/null +++ b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/connection/OmdsCameraConnection.kt @@ -0,0 +1,197 @@ +package jp.osdn.gokigen.gokigenassets.camera.vendor.omds.connection + +import android.content.* +import android.net.ConnectivityManager +import android.net.wifi.WifiManager +import android.provider.Settings +import android.util.Log +import androidx.appcompat.app.AlertDialog +import androidx.appcompat.app.AppCompatActivity +import jp.osdn.gokigen.gokigenassets.camera.interfaces.* +import jp.osdn.gokigen.gokigenassets.constants.ICameraConstantConvert +import java.lang.Exception +import java.util.concurrent.Executor +import java.util.concurrent.Executors + +class OmdsCameraConnection(private val context: AppCompatActivity, private val statusReceiver: ICameraStatusReceiver) : ICameraConnection, ICameraConnectionStatus +{ + private val cameraExecutor: Executor = Executors.newFixedThreadPool(1) + private var connectionStatus: ICameraConnectionStatus.CameraConnectionStatus = ICameraConnectionStatus.CameraConnectionStatus.UNKNOWN + private val connectionReceiver: BroadcastReceiver = object : BroadcastReceiver() + { + override fun onReceive(context: Context, intent: Intent) + { + onReceiveBroadcastOfConnection(context, intent) + } + } + + private fun onReceiveBroadcastOfConnection(context: Context, intent: Intent) + { + statusReceiver.onStatusNotify(context.getString(ICameraConstantConvert.ID_STRING_CONNECT_CHECK_WIFI)) + Log.v(TAG, context.getString(ICameraConstantConvert.ID_STRING_CONNECT_CHECK_WIFI)) + val action = intent.action + if (action == null) + { + Log.v(TAG, "intent.getAction() : null") + return + } + try + { + @Suppress("DEPRECATION") + if (action == ConnectivityManager.CONNECTIVITY_ACTION) + { + Log.v(TAG, "onReceiveBroadcastOfConnection() : CONNECTIVITY_ACTION") + val wifiManager = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager + val info = wifiManager.connectionInfo + if ((wifiManager.isWifiEnabled)&&(info != null)) + { + if (info.networkId != -1) + { + Log.v(TAG, "Network ID is -1, there is no currently connected network.") + } + // カメラと接続 + connectToCamera() + } + else + { + if (info == null) + { + Log.v(TAG, "NETWORK INFO IS NULL.") + } + else + { + Log.v(TAG, "isWifiEnabled : " + wifiManager.isWifiEnabled + " NetworkId : " + info.networkId) + } + } + } + } + catch (e: Exception) + { + Log.w(TAG, "onReceiveBroadcastOfConnection() EXCEPTION" + e.message) + e.printStackTrace() + } + } + + fun startWatchWifiStatus(context: Context) + { + Log.v(TAG, "startWatchWifiStatus()") + try + { + statusReceiver.onStatusNotify("prepare") + val filter = IntentFilter() + filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION) + @Suppress("DEPRECATION") + filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION) + context.registerReceiver(connectionReceiver, filter) + } + catch (e : Exception) + { + e.printStackTrace() + } + } + + fun stopWatchWifiStatus(context: Context) + { + Log.v(TAG, "stopWatchWifiStatus()") + context.unregisterReceiver(connectionReceiver) + disconnect(false) + } + + fun disconnect(powerOff: Boolean) + { + Log.v(TAG, "disconnect()") + disconnectFromCamera(powerOff) + connectionStatus = ICameraConnectionStatus.CameraConnectionStatus.DISCONNECTED + statusReceiver.onCameraDisconnected() + } + + fun connect() + { + Log.v(TAG, "connect()") + connectToCamera() + } + + override fun alertConnectingFailed(message: String?) + { + Log.v(TAG, "alertConnectingFailed() : $message") + val builder: AlertDialog.Builder = AlertDialog.Builder(context) + .setTitle(context.getString(ICameraConstantConvert.ID_STRING_DIALOG_TITLE_CONNECT_FAILED)) + .setMessage(message) + .setPositiveButton(context.getString(ICameraConstantConvert.ID_STRING_DIALOG_BUTTON_RETRY)) { _, _ -> connect() } + .setNeutralButton(ICameraConstantConvert.ID_STRING_DIALOG_BUTTON_NETWORK_SETTINGS) { _, _ -> + try { + // Wifi 設定画面を表示する + context.startActivity(Intent(Settings.ACTION_WIFI_SETTINGS)) + } catch (ex: ActivityNotFoundException) { + // Activity が存在しなかった...設定画面が起動できなかった + Log.v(TAG, "android.content.ActivityNotFoundException...") + + // この場合は、再試行と等価な動きとする + connect() + } catch (e: Exception) { + e.printStackTrace() + } + } + context.runOnUiThread { + try + { + builder.show() + } + catch (e: Exception) + { + e.printStackTrace() + } + } + } + + override fun getConnectionStatus(): ICameraConnectionStatus.CameraConnectionStatus + { + Log.v(TAG, "getConnectionStatus()") + return connectionStatus + } + + override fun forceUpdateConnectionStatus(status: ICameraConnectionStatus.CameraConnectionStatus) + { + Log.v(TAG, "forceUpdateConnectionStatus()") + connectionStatus = status + } + + /** + * カメラとの切断処理 + */ + private fun disconnectFromCamera(powerOff: Boolean) + { + Log.v(TAG, "disconnectFromCamera()") + try + { + cameraExecutor.execute(OmdsCameraDisconnectSequence(context, powerOff)) + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + /** + * カメラとの接続処理 + */ + private fun connectToCamera() + { + Log.v(TAG, "connectToCamera()") + connectionStatus = ICameraConnectionStatus.CameraConnectionStatus.CONNECTING + try + { + cameraExecutor.execute(OmdsCameraConnectSequence(context, statusReceiver, this)) + } + catch (e: Exception) + { + Log.v(TAG, "connectToCamera() EXCEPTION : " + e.message) + e.printStackTrace() + } + } + + companion object + { + private val TAG = OmdsCameraConnection::class.java.simpleName + } +} diff --git a/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/connection/OmdsCameraDisconnectSequence.kt b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/connection/OmdsCameraDisconnectSequence.kt new file mode 100644 index 0000000..6bbd386 --- /dev/null +++ b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/connection/OmdsCameraDisconnectSequence.kt @@ -0,0 +1,43 @@ +package jp.osdn.gokigen.gokigenassets.camera.vendor.omds.connection + +import android.util.Log +import androidx.appcompat.app.AppCompatActivity +import jp.osdn.gokigen.gokigenassets.utils.communication.SimpleHttpClient +import java.lang.Exception +import java.util.HashMap + +class OmdsCameraDisconnectSequence(private val context: AppCompatActivity, private val powerOff: Boolean, private val executeUrl : String = "http://192.168.0.10") : Runnable +{ + private val headerMap: MutableMap = HashMap() + private val http = SimpleHttpClient() + + override fun run() + { + // カメラをPowerOffして接続を切る + try + { + if (powerOff) + { + val cameraPowerOffUrl = "$executeUrl/exec_pwoff.cgi" + val response: String = http.httpGetWithHeader(cameraPowerOffUrl, headerMap, null, TIMEOUT_MS) ?: "" + Log.v(TAG, " $cameraPowerOffUrl $response") + } + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + init + { + headerMap["User-Agent"] = "OlympusCameraKit" // "OI.Share" + headerMap["X-Protocol"] = "OlympusCameraKit" // "OI.Share" + } + + companion object + { + private val TAG = OmdsCameraDisconnectSequence::class.java.simpleName + private const val TIMEOUT_MS = 5000 + } +} diff --git a/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/liveview/OmdsLiveViewControl.kt b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/liveview/OmdsLiveViewControl.kt new file mode 100644 index 0000000..4b46101 --- /dev/null +++ b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/liveview/OmdsLiveViewControl.kt @@ -0,0 +1,288 @@ +package jp.osdn.gokigen.gokigenassets.camera.vendor.omds.liveview + +import android.util.Log +import jp.osdn.gokigen.gokigenassets.camera.interfaces.ICameraStatusUpdateNotify +import jp.osdn.gokigen.gokigenassets.camera.interfaces.ILiveViewController +import jp.osdn.gokigen.gokigenassets.camera.vendor.omds.status.OmdsCameraStatusWatcher +import jp.osdn.gokigen.gokigenassets.liveview.image.IImageDataReceiver +import jp.osdn.gokigen.gokigenassets.liveview.message.IMessageDrawer +import jp.osdn.gokigen.gokigenassets.utils.communication.SimpleHttpClient +import java.io.ByteArrayOutputStream +import java.lang.Exception +import java.net.DatagramPacket +import java.net.DatagramSocket +import java.util.* + + +class OmdsLiveViewControl(private val imageDataReceiver: IImageDataReceiver, + private val statusWatcher: OmdsCameraStatusWatcher, + private val indicator: IMessageDrawer?, + private val notifier: ICameraStatusUpdateNotify?, + private val executeUrl : String = "http://192.168.0.10", + ) : ILiveViewController +{ + private val headerMap: MutableMap = HashMap() + private val http = SimpleHttpClient() + + private var receiveSocket: DatagramSocket? = null + private var whileStreamReceive = false + private val receivedByteStream: ByteArrayOutputStream + + override fun startLiveView(isCameraScreen: Boolean) + { + Log.v(TAG, "startLiveView()") + try + { + val thread = Thread(Runnable { + try + { + startReceiveStream() + if (!whileStreamReceive) { + Log.v(TAG, "CANNOT OPEN : UDP RECEIVE SOCKET") + return@Runnable + } + val requestUrl = executeUrl + LIVEVIEW_START_REQUEST + val reply: String = http.httpGetWithHeader(requestUrl, headerMap, null, TIMEOUT_MS) ?: "" + Log.v(TAG, " ----- START LIVEVIEW ----- : $requestUrl $reply") + } + catch (e: Exception) + { + e.printStackTrace() + } + }) + thread.start() + statusWatcher.startStatusWatch(indicator, notifier) + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + override fun stopLiveView() + { + Log.v(TAG, "stopLiveView()") + try + { + val thread = Thread { + try + { + val requestUrl = executeUrl + LIVEVIEW_STOP_REQUEST + val reply: String = http.httpGetWithHeader(requestUrl, headerMap, null, TIMEOUT_MS) ?: "" + Log.v(TAG, "stopLiveview() is issued. $reply") + + // ライブビューウォッチャーを止める + whileStreamReceive = false + closeReceiveSocket() + } + catch (e: Exception) + { + e.printStackTrace() + } + } + thread.start() + statusWatcher.stopStatusWatch() + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + private fun startReceiveStream() + { + if (whileStreamReceive) + { + Log.v(TAG, "startReceiveStream() : already starting.") + return + } + + // ソケットをあける (UDP) + try + { + receiveSocket = DatagramSocket(LIVEVIEW_PORT) + whileStreamReceive = true + receivedByteStream.flush() + } + catch (e: Exception) + { + e.printStackTrace() + whileStreamReceive = false + receiveSocket = null + } + + // 受信スレッドを動かす + val thread = Thread { receiverThread() } + try + { + thread.start() + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + private fun checkReceiveImage(packet: DatagramPacket) + { + try + { + val dataLength = packet.length + val receivedData = packet.data + if (receivedData == null) + { + // 受信データが取れなかったのでいったん終了する + Log.v(TAG, "RECEIVED DATA IS NULL...") + return + } + val position = 12 + var extensionLength = 0 + var isFinished = false + if (receivedData[0] == 0x90.toByte()) + { + // 先頭パケット (RTPヘッダは 12bytes + 拡張ヘッダ...) + //extensionLength = (receivedData[14]); + //extensionLength = (extensionLength * 256) + (receivedData[15]); + extensionLength = 16 + extensionLength = checkJpegStartPosition(receivedData, extensionLength) - position + statusWatcher.setRtpHeader(Arrays.copyOf(receivedData, extensionLength)) + System.gc() + } else if (receivedData[1] == 0xe0.toByte()) + { + // 末尾パケット (RTPヘッダは 12bytes) + isFinished = true + } + val offset = position + extensionLength + receivedByteStream.write(receivedData, position + extensionLength, dataLength - offset) + if (isFinished) + { + val dataArray = receivedByteStream.toByteArray() + receivedByteStream.flush() + imageDataReceiver.onUpdateLiveView(Arrays.copyOf(dataArray, dataArray.size), null) + receivedByteStream.reset() + //System.gc(); + } + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + private fun checkJpegStartPosition(bytes: ByteArray, offset: Int): Int + { + try + { + var position = offset + val maxLength = bytes.size - 1 + while (position < maxLength) + { + if (bytes[position] == 0xff.toByte()) + { + if (bytes[position + 1] == 0xd8.toByte()) + { + return position + } + } + position++ + } + } + catch (e: Exception) + { + e.printStackTrace() + } + return 0 + } + + private fun receiverThread() + { + var exceptionCount = 0 + val buffer = ByteArray(RECEIVE_BUFFER_SIZE) + while (whileStreamReceive) + { + try + { + val receive_packet = DatagramPacket(buffer, buffer.size) + if (receiveSocket != null) + { + receiveSocket?.soTimeout = TIMEOUT_MS + receiveSocket?.receive(receive_packet) + checkReceiveImage(receive_packet) + exceptionCount = 0 + } + else + { + Log.v(TAG, "receiveSocket is NULL...") + } + } + catch (e: Exception) + { + exceptionCount++ + e.printStackTrace() + if (exceptionCount > TIMEOUT_MAX) + { + try + { + // ライブビューの送信が来なくなった... それも回数が超えた... + Log.v(TAG, "LV : RETRY REQUEST") + exceptionCount = 0 + /* + String reply = SimpleHttpClient.httpGet(camera.getCmdUrl() + LIVEVIEW_START_REQUEST, TIMEOUT_MS); + if (!reply.contains("ok")) + { + Log.v(TAG, "LV : RETRY COMMAND FAIL..."); + } +*/ + } + catch (ee: Exception) + { + ee.printStackTrace() + } + } + } + } + closeReceiveSocket() + Log.v(TAG, " ----- startReceiveStream() : Finished.") + System.gc() + } + + private fun closeReceiveSocket() + { + Log.v(TAG, "closeReceiveSocket()") + try + { + if (receiveSocket != null) + { + Log.v(TAG, " ----- SOCKET CLOSE ----- ") + receiveSocket!!.close() + receiveSocket = null + } + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + init + { + headerMap["User-Agent"] = "OlympusCameraKit" // "OI.Share" + headerMap["X-Protocol"] = "OlympusCameraKit" // "OI.Share" + + receivedByteStream = ByteArrayOutputStream(RECEIVE_BUFFER_SIZE) + } + + companion object + { + private val TAG = OmdsLiveViewControl::class.java.simpleName + + private const val LIVEVIEW_START_REQUEST = "/exec_takemisc.cgi?com=startliveview&port=49152" + private const val LIVEVIEW_STOP_REQUEST = "/exec_takemisc.cgi?com=stopliveview" + + private const val TIMEOUT_MAX = 3 + private const val RECEIVE_BUFFER_SIZE = 1024 * 1024 * 4 + private const val TIMEOUT_MS = 1500 + private const val LIVEVIEW_PORT = 49152 + } + +} diff --git a/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/operation/OmdsAutoFocusControl.kt b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/operation/OmdsAutoFocusControl.kt new file mode 100644 index 0000000..e911b91 --- /dev/null +++ b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/operation/OmdsAutoFocusControl.kt @@ -0,0 +1,210 @@ +package jp.osdn.gokigen.gokigenassets.camera.vendor.omds.operation + +import android.graphics.PointF +import android.graphics.RectF +import android.util.Log +import jp.osdn.gokigen.gokigenassets.liveview.IIndicatorControl +import jp.osdn.gokigen.gokigenassets.liveview.focusframe.IAutoFocusFrameDisplay +import jp.osdn.gokigen.gokigenassets.utils.communication.SimpleHttpClient +import java.lang.Exception +import java.util.* +import kotlin.math.floor + +class OmdsAutoFocusControl(private val frameDisplayer: IAutoFocusFrameDisplay, private val indicator: IIndicatorControl, private val executeUrl : String = "http://192.168.0.10") +{ + private val headerMap: MutableMap = HashMap() + private val http = SimpleHttpClient() + + fun lockAutoFocus(point: PointF) + { + Log.v(TAG, "lockAutoFocus() : [" + point.x + ", " + point.y + "]") + try { + val thread = Thread { + val preFocusFrameRect = getPreFocusFrameRect(point) + try { + showFocusFrame( + preFocusFrameRect, + IAutoFocusFrameDisplay.FocusFrameStatus.Running, + 0.0 + ) + val posX = floor((point.x * scaleX).toDouble()).toInt() + val posY = floor((point.y * scaleY).toDouble()).toInt() + Log.v( + TAG, + "AF ($posX, $posY)" + ) + val sendUrl = String.format( + Locale.US, + "%s%s&point=%04dx%04d", + executeUrl, + AF_FRAME_COMMAND, + posX, + posY + ) + val reply: String = http.httpGetWithHeader( + sendUrl, + headerMap, + null, + TIMEOUT_MS + ) ?: "" + if (!reply.contains("ok")) { + Log.v( + TAG, + "setTouchAFPosition() reply is null." + ) + } + if (findTouchAFPositionResult( + reply, + " [" + posX + "x" + posY + "]" + ) + ) { + // AF FOCUSED + Log.v( + TAG, + "lockAutoFocus() : FOCUSED" + ) + showFocusFrame( + preFocusFrameRect, + IAutoFocusFrameDisplay.FocusFrameStatus.Focused, + 0.0 + ) + } else { + // AF ERROR + Log.v( + TAG, + "lockAutoFocus() : ERROR" + ) + showFocusFrame( + preFocusFrameRect, + IAutoFocusFrameDisplay.FocusFrameStatus.Failed, + 1.0 + ) + } + //showFocusFrame(preFocusFrameRect, IAutoFocusFrameDisplay.FocusFrameStatus.Errored, 1.0); + } catch (e: Exception) { + e.printStackTrace() + try { + showFocusFrame( + preFocusFrameRect, + IAutoFocusFrameDisplay.FocusFrameStatus.Errored, + 1.0 + ) + } catch (ee: Exception) { + ee.printStackTrace() + } + } + } + thread.start() + } catch (e: Exception) { + e.printStackTrace() + } + } + + /** + * シャッター半押し処理 + * + */ + fun halfPressShutter(isPressed: Boolean) + { + if (isPressed) + { + lockAutoFocus(PointF(0.5f, 0.5f)) + } + else + { + unlockAutoFocus() + } + } + + fun unlockAutoFocus() + { + Log.v(TAG, "unlockAutoFocus()") + try { + val thread = Thread { + try { + val reply: String = http.httpGetWithHeader( + executeUrl + AF_RELEASE_COMMAND, + headerMap, + null, + TIMEOUT_MS + ) ?: "" + if (!reply.contains("ok")) { + Log.v( + TAG, + "unlockAutoFocus() reply is null." + ) + } + hideFocusFrame() + } catch (e: Exception) { + e.printStackTrace() + } + } + thread.start() + } catch (e: Exception) { + e.printStackTrace() + } + } + + private fun showFocusFrame(rect: RectF, status: IAutoFocusFrameDisplay.FocusFrameStatus, duration: Double) + { + frameDisplayer.showFocusFrame(rect, status, duration.toFloat()) + indicator.onAfLockUpdate(IAutoFocusFrameDisplay.FocusFrameStatus.Focused === status) + } + + private fun hideFocusFrame() + { + frameDisplayer.hideFocusFrame() + indicator.onAfLockUpdate(false) + } + + private fun getPreFocusFrameRect(point: PointF): RectF + { + val imageWidth: Float = frameDisplayer.getContentSizeWidth() + val imageHeight: Float = frameDisplayer.getContentSizeHeight() + + // Display a provisional focus frame at the touched point. + val focusWidth = 0.125f // 0.125 is rough estimate. + var focusHeight = 0.125f + focusHeight *= if (imageWidth > imageHeight) { + imageWidth / imageHeight + } else { + imageHeight / imageWidth + } + return RectF( + point.x - focusWidth / 2.0f, point.y - focusHeight / 2.0f, + point.x + focusWidth / 2.0f, point.y + focusHeight / 2.0f + ) + } + + private fun findTouchAFPositionResult(replyXml: String, position: String): Boolean { + try { + Log.v( + TAG, + " REPLY : $replyXml $position" + ) + if (replyXml.contains("ok")) { + return true + } + } catch (e: Exception) { + e.printStackTrace() + } + return false + } + + init + { + headerMap["User-Agent"] = "OlympusCameraKit" // "OI.Share" + headerMap["X-Protocol"] = "OlympusCameraKit" // "OI.Share" + } + + companion object + { + private val TAG = OmdsAutoFocusControl::class.java.simpleName + private const val TIMEOUT_MS = 3000 + + private const val AF_FRAME_COMMAND = "/exec_takemotion.cgi?com=assignafframe" + private const val AF_RELEASE_COMMAND = "/exec_takemotion.cgi?com=releaseafframe" + private const val scaleX = 640.0f + private const val scaleY = 480.0f + } +} diff --git a/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/operation/OmdsCameraPowerOff.kt b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/operation/OmdsCameraPowerOff.kt new file mode 100644 index 0000000..c3da12b --- /dev/null +++ b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/operation/OmdsCameraPowerOff.kt @@ -0,0 +1,48 @@ +package jp.osdn.gokigen.gokigenassets.camera.vendor.omds.operation + +import android.content.Context +import androidx.preference.Preference +import jp.osdn.gokigen.gokigenassets.constants.IApplicationConstantConvert +import jp.osdn.gokigen.gokigenassets.scene.IChangeSceneBasic +import jp.osdn.gokigen.gokigenassets.utils.ConfirmationDialog + +class OmdsCameraPowerOff(private val context: Context, private val changeScene: IChangeSceneBasic) : Preference.OnPreferenceClickListener, ConfirmationDialog.ConfirmationCallback +{ + private var preferenceKey: String? = null + + fun prepare() + { + // 何もしない + } + + override fun onPreferenceClick(preference: Preference): Boolean + { + if (!preference.hasKey()) + { + return false + } + preferenceKey = preference.key + val isContain = preferenceKey?.contains(IApplicationConstantConvert.ID_PREFERENCE_LABEL_EXIT_APPLICATION) + if ((isContain != null)&&(isContain)) + { + + // 確認ダイアログの生成と表示 + val dialog: ConfirmationDialog = ConfirmationDialog.newInstance(context) + dialog.show( + IApplicationConstantConvert.ID_DIALOG_TITLE_CONFIRMATION, + IApplicationConstantConvert.ID_DIALOG_EXIT_POWER_OFF, this) + return true + } + return false + } + + override fun confirm() + { + val isContain = preferenceKey?.contains(IApplicationConstantConvert.ID_PREFERENCE_LABEL_EXIT_APPLICATION) + if ((isContain != null)&&(isContain)) + { + // カメラの電源をOFFにしたうえで、アプリケーションを終了する。 + changeScene.exitApplication() + } + } +} diff --git a/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/operation/OmdsSingleShotControl.kt b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/operation/OmdsSingleShotControl.kt new file mode 100644 index 0000000..066400f --- /dev/null +++ b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/operation/OmdsSingleShotControl.kt @@ -0,0 +1,55 @@ +package jp.osdn.gokigen.gokigenassets.camera.vendor.omds.operation + +import android.util.Log +import jp.osdn.gokigen.gokigenassets.liveview.IIndicatorControl +import jp.osdn.gokigen.gokigenassets.liveview.focusframe.IAutoFocusFrameDisplay +import jp.osdn.gokigen.gokigenassets.utils.communication.SimpleHttpClient +import java.lang.Exception +import java.util.HashMap + +class OmdsSingleShotControl(private val frameDisplayer: IAutoFocusFrameDisplay, private val indicator: IIndicatorControl, private val executeUrl : String = "http://192.168.0.10") +{ + private val headerMap: MutableMap = HashMap() + private val http = SimpleHttpClient() + + fun singleShot() + { + Log.v(TAG, "singleShot()") + try + { + val thread = Thread { + try + { + val reply: String = http.httpGetWithHeader(executeUrl + CAPTURE_COMMAND, headerMap, null, TIMEOUT_MS) ?: "" + if (!reply.contains("ok")) + { + Log.v(TAG, "Capture Failure... : $reply") + } + } + catch (e: Exception) + { + e.printStackTrace() + } + frameDisplayer.hideFocusFrame() + } + thread.start() + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + companion object + { + private val TAG: String = OmdsSingleShotControl::class.java.simpleName + private const val TIMEOUT_MS = 3000 + private const val CAPTURE_COMMAND = "/exec_takemotion.cgi?com=starttake" + } + + init + { + headerMap["User-Agent"] = "OlympusCameraKit" // "OI.Share" + headerMap["X-Protocol"] = "OlympusCameraKit" // "OI.Share" + } +} diff --git a/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/status/OmdsCameraStatusWatcher.kt b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/status/OmdsCameraStatusWatcher.kt new file mode 100644 index 0000000..c3f85da --- /dev/null +++ b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/status/OmdsCameraStatusWatcher.kt @@ -0,0 +1,167 @@ +package jp.osdn.gokigen.gokigenassets.camera.vendor.omds.status + +import android.graphics.Color +import android.util.Log +import jp.osdn.gokigen.gokigenassets.camera.interfaces.ICameraStatus +import jp.osdn.gokigen.gokigenassets.camera.interfaces.ICameraStatusUpdateNotify +import jp.osdn.gokigen.gokigenassets.camera.interfaces.ICameraStatusWatcher +import jp.osdn.gokigen.gokigenassets.liveview.message.IMessageDrawer +import java.lang.Exception +import kotlin.collections.ArrayList + +class OmdsCameraStatusWatcher() : ICameraStatusWatcher, ICameraStatus +{ + private var buffer: ByteArray? = null + private var isWatching = false + private var statusReceived = false + private var notifier: ICameraStatusUpdateNotify? = null + private var focusingStatus = 0 + + fun setRtpHeader(byteBuffer: ByteArray?) + { + try + { + //buffer = byteBuffer?.copyOf() + if (byteBuffer != null) + { + buffer = byteBuffer + statusReceived = true + } + else + { + statusReceived = false + } + } + catch (e: Exception) + { + e.printStackTrace() + statusReceived = false + } + } + + override fun startStatusWatch(indicator: IMessageDrawer?, notifier: ICameraStatusUpdateNotify?) + { + try + { + this.notifier = notifier + val thread = Thread { + val waitMs = SLEEP_TIME_MS + isWatching = true + while (isWatching) + { + if (statusReceived) + { + // データを解析する + parseRtpHeader() + statusReceived = false + } + sleep(waitMs) + } + } + thread.start() + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + private fun sleep(waitMs: Int) + { + try + { + Thread.sleep(waitMs.toLong()) + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + private fun parseRtpHeader() + { + try + { + if (buffer == null) + { + Log.v(TAG, " parseRtpHeader() : null") + return + } + var position = 16 + val maxLength = buffer?.size ?: 0 + while (position + 4 < maxLength) + { + val id: Int = ((buffer?.get(position) ?: 0).toInt() and 0xff) * 256 + ((buffer?.get(position + 1) ?: 0).toInt() and 0xff) + val length: Int = ((buffer?.get(position + 2) ?: 0).toInt() and 0xff) * 256 + ((buffer?.get(position + 3) ?: 0).toInt() and 0xff) + when (id) + { + ID_AF_FRAME_INFO -> { checkFocused(buffer, position, length) } + ID_ZOOM_LENS_INFO, ID_FRAME_SIZE -> { } + else -> { } + } + position += 4 + length * 4 // header : 4bytes , data : length * 4 bytes + } + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + private fun checkFocused(buffer: ByteArray?, position: Int, length: Int) + { + if ((length != 5)||(buffer == null)) + { + // データがそろっていないので何もしない + return + } + val status: Int = buffer[position + 7].toInt() and 0xff + if (status != focusingStatus) + { + // ドライブ停止時には、マーカの色は消さない + if (status > 0) + { + val focus = status == 1 + val isError = status == 2 + notifier?.updateFocusedStatus(focus, isError) + } + focusingStatus = status + } + } + + override fun stopStatusWatch() + { + isWatching = false + } + + override fun getStatusList(key: String): List + { + return (ArrayList()) + } + + override fun getStatus(key: String): String + { + return ("") + } + + override fun getStatusColor(key: String): Int + { + return (Color.WHITE) + } + + override fun setStatus(key: String, value: String) + { + + } + + companion object + { + private val TAG = OmdsCameraStatusWatcher::class.java.simpleName + + private const val SLEEP_TIME_MS = 250 + private const val ID_FRAME_SIZE = 1 + private const val ID_AF_FRAME_INFO = 2 + private const val ID_ZOOM_LENS_INFO = 18 + } + +} diff --git a/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/wrapper/OmdsCaptureControl.kt b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/wrapper/OmdsCaptureControl.kt new file mode 100644 index 0000000..d4c47ba --- /dev/null +++ b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/wrapper/OmdsCaptureControl.kt @@ -0,0 +1,33 @@ +package jp.osdn.gokigen.gokigenassets.camera.vendor.omds.wrapper + +import android.util.Log +import jp.osdn.gokigen.gokigenassets.camera.interfaces.ICameraStatus +import jp.osdn.gokigen.gokigenassets.camera.interfaces.ICaptureControl +import jp.osdn.gokigen.gokigenassets.camera.vendor.omds.operation.OmdsSingleShotControl +import jp.osdn.gokigen.gokigenassets.liveview.IIndicatorControl +import jp.osdn.gokigen.gokigenassets.liveview.focusframe.IAutoFocusFrameDisplay +import java.lang.Exception + +class OmdsCaptureControl(private val frameDisplay: IAutoFocusFrameDisplay, indicator: IIndicatorControl, statusChecker : ICameraStatus): ICaptureControl +{ + private val singleShotControl = OmdsSingleShotControl(frameDisplay, indicator) + + override fun doCapture(kind: Int) + { + Log.v(TAG, "doCapture() : $kind") + try + { + singleShotControl.singleShot() + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + companion object + { + private val TAG: String = OmdsCaptureControl::class.java.getSimpleName() + } + +} diff --git a/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/wrapper/OmdsFocusControl.kt b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/wrapper/OmdsFocusControl.kt new file mode 100644 index 0000000..be32283 --- /dev/null +++ b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/wrapper/OmdsFocusControl.kt @@ -0,0 +1,75 @@ +package jp.osdn.gokigen.gokigenassets.camera.vendor.omds.wrapper + +import android.graphics.PointF +import android.util.Log +import android.view.MotionEvent +import jp.osdn.gokigen.gokigenassets.camera.interfaces.IFocusingControl +import jp.osdn.gokigen.gokigenassets.camera.vendor.omds.operation.OmdsAutoFocusControl +import jp.osdn.gokigen.gokigenassets.liveview.IIndicatorControl +import jp.osdn.gokigen.gokigenassets.liveview.focusframe.IAutoFocusFrameDisplay +import java.lang.Exception + +class OmdsFocusControl(private val frameDisplay: IAutoFocusFrameDisplay, indicator: IIndicatorControl) : IFocusingControl +{ + private val afControl = OmdsAutoFocusControl(frameDisplay, indicator) + + override fun driveAutoFocus(motionEvent: MotionEvent?): Boolean + { + Log.v(TAG, "driveAutoFocus()") + if (motionEvent?.action != MotionEvent.ACTION_DOWN) + { + return false + } + try + { + val point: PointF = frameDisplay.getPointWithEvent(motionEvent) ?: PointF(0.5f, 0.5f) + if (frameDisplay.isContainsPoint(point)) + { + afControl.lockAutoFocus(point) + } + } + catch (e: Exception) + { + e.printStackTrace() + } + return false + } + + override fun unlockAutoFocus() + { + Log.v(TAG, "unlockAutoFocus()") + try + { + afControl.unlockAutoFocus() + frameDisplay.hideFocusFrame() + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + override fun halfPressShutter(isPressed: Boolean) + { + Log.v(TAG, "halfPressShutter() $isPressed") + try + { + afControl.halfPressShutter(isPressed) + if (!isPressed) + { + // フォーカスを外す + frameDisplay.hideFocusFrame() + afControl.unlockAutoFocus() + } + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + companion object + { + private val TAG = OmdsFocusControl::class.java.simpleName + } +} diff --git a/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/wrapper/OmdsRunMode.kt b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/wrapper/OmdsRunMode.kt new file mode 100644 index 0000000..98b975f --- /dev/null +++ b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/wrapper/OmdsRunMode.kt @@ -0,0 +1,70 @@ +package jp.osdn.gokigen.gokigenassets.camera.vendor.omds.wrapper + +import android.util.Log +import jp.osdn.gokigen.gokigenassets.camera.interfaces.ICameraRunMode +import jp.osdn.gokigen.gokigenassets.camera.interfaces.ICameraRunModeCallback +import jp.osdn.gokigen.gokigenassets.utils.communication.SimpleHttpClient +import java.lang.Exception +import java.util.HashMap + + +class OmdsRunMode(private val executeUrl : String = "http://192.168.0.10") : ICameraRunMode +{ + private val headerMap: MutableMap = HashMap() + private val http = SimpleHttpClient() + private var runMode = false + + override fun changeRunMode(isRecording: Boolean, callback: ICameraRunModeCallback) + { + try + { + Log.v(TAG, " changeRunMode : $isRecording") + val thread = Thread { // カメラとの接続確立を通知する + var playModeUrl = "$executeUrl/switch_cammode.cgi" + playModeUrl = if (isRecording) + { + "$playModeUrl?mode=rec" + } + else + { + "$playModeUrl?mode=play" + } + val response: String = http.httpGetWithHeader(playModeUrl, headerMap, null, TIMEOUT_MS) ?: "" + Log.v(TAG, " $playModeUrl $response") + try + { + if (response.contains("ok")) + { + runMode = isRecording + } + } + catch (e: Exception) + { + e.printStackTrace() + } + } + thread.start() + } + catch (e: Exception) + { + e.printStackTrace() + } + } + + override fun isRecordingMode(): Boolean + { + return (runMode) + } + + init + { + headerMap["User-Agent"] = "OlympusCameraKit" // "OI.Share" + headerMap["X-Protocol"] = "OlympusCameraKit" // "OI.Share" + } + + companion object + { + private val TAG = OmdsRunMode::class.java.simpleName + private const val TIMEOUT_MS = 5000 + } +} diff --git a/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/wrapper/OmdsZoomLensControl.kt b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/wrapper/OmdsZoomLensControl.kt new file mode 100644 index 0000000..8953505 --- /dev/null +++ b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/omds/wrapper/OmdsZoomLensControl.kt @@ -0,0 +1,110 @@ +package jp.osdn.gokigen.gokigenassets.camera.vendor.omds.wrapper + +import android.util.Log +import jp.osdn.gokigen.gokigenassets.camera.interfaces.IZoomLensControl +import jp.osdn.gokigen.gokigenassets.utils.communication.SimpleHttpClient +import java.lang.Exception +import java.util.HashMap + +class OmdsZoomLensControl(private val executeUrl : String = "http://192.168.0.10") : IZoomLensControl +{ + private val headerMap: MutableMap = HashMap() + private val http = SimpleHttpClient() + private var isZooming = false + + override fun canZoom(): Boolean + { + Log.v(TAG, "canZoom()") + return true + } + + override fun updateStatus() + { + Log.v(TAG, "updateStatus()") + } + + override fun getMaximumFocalLength(): Float + { + Log.v(TAG, "getMaximumFocalLength()") + return (0.0f) + } + + override fun getMinimumFocalLength(): Float + { + Log.v(TAG, "getMinimumFocalLength()") + return (0.0f) + } + + override fun getCurrentFocalLength(): Float + { + Log.v(TAG, "getCurrentFocalLength()") + return (0.0f) + } + + override fun driveZoomLens(targetLength: Float) + { + Log.v(TAG, "driveZoomLens() : $targetLength") + } + + override fun moveInitialZoomPosition() + { + Log.v(TAG, "moveInitialZoomPosition()") + } + + override fun isDrivingZoomLens(): Boolean + { + Log.v(TAG, "isDrivingZoomLens()") + return (false) + } + + override fun driveZoomLens(isZoomIn: Boolean) { + Log.v(TAG, "driveZoomLens() : $isZoomIn") + try { + val thread = Thread { + try { + val command: String + command = if (isZooming) { + "/exec_takemisc.cgi?com=ctrlzoom&move=off" + } else { + if (isZoomIn) "/exec_takemisc.cgi?com=ctrlzoom&move=telemove" else "/exec_takemisc.cgi?com=ctrlzoom&move=widemove" + } + val reply: String = http.httpGetWithHeader( + executeUrl + command, + headerMap, + null, + TIMEOUT_MS + ) ?: "" + isZooming = !isZooming + Log.v(TAG, "ZOOM : $isZooming cmd : $command RET : $reply") + /* + if (reply.contains("ok")) + { + isZooming = !isZooming; + } + else + { + Log.v(TAG, "driveZoomLens() reply is failure."); + } + */ + } catch (e: Exception) { + e.printStackTrace() + } + } + thread.start() + } catch (e: Exception) { + e.printStackTrace() + } + } + + companion object + { + private val TAG = OmdsZoomLensControl::class.java.simpleName + private const val TIMEOUT_MS = 3000 + } + + init + { + headerMap["User-Agent"] = "OlympusCameraKit" // "OI.Share" + headerMap["X-Protocol"] = "OlympusCameraKit" // "OI.Share" + } +} diff --git a/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/pixpro/wrapper/command/messages/specific/PixproExecuteShutter.kt b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/pixpro/wrapper/command/messages/specific/PixproExecuteShutter.kt index 6868229..56630f2 100644 --- a/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/pixpro/wrapper/command/messages/specific/PixproExecuteShutter.kt +++ b/app/src/main/java/jp/osdn/gokigen/gokigenassets/camera/vendor/pixpro/wrapper/command/messages/specific/PixproExecuteShutter.kt @@ -6,6 +6,8 @@ import jp.osdn.gokigen.gokigenassets.camera.vendor.pixpro.wrapper.command.messag class PixproExecuteShutter(private val callback: IPixproCommandCallback, posX: Int = 0x00004dbf, posY: Int = 0xb6658801.toInt()) : PixproCommandBase() { + +/* private val data00: Byte = (0x000000ff and posX).toByte() private val data01: Byte = (0x0000ff00 and posX shr 8).toByte() private val data02: Byte = (0x00ff0000 and posX shr 16).toByte() @@ -15,6 +17,7 @@ class PixproExecuteShutter(private val callback: IPixproCommandCallback, posX: I private val data11: Byte = (0x0000ff00 and posY shr 8).toByte() private val data12: Byte = (0x00ff0000 and posY shr 16).toByte() private val data13: Byte = (-0x1000000 and posY shr 24).toByte() +*/ override fun getId() : Int { -- 2.11.0