import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.IPtpIpCommandPublisher;
import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.IPtpIpCommunication;
import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.PtpIpAsyncResponseReceiver;
-import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.PtpIpCommandPublisher;
+import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.PtpIpCommandPublisher0;
import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.connection.NikonConnection;
import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.liveview.PtpIpLiveViewControl;
import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.status.IPtpIpRunModeHolder;
private final PtpIpHardwareStatus hardwareStatus;
private PtpIpButtonControl ptpIpButtonControl;
private NikonConnection nikonConnection;
- private PtpIpCommandPublisher commandPublisher;
+ private PtpIpCommandPublisher0 commandPublisher;
private PtpIpLiveViewControl liveViewControl;
private PtpIpAsyncResponseReceiver asyncReceiver;
private PtpIpZoomControl zoomControl;
{
e.printStackTrace();
}
- commandPublisher = new PtpIpCommandPublisher(ipAddress, CONTROL_PORT);
+ commandPublisher = new PtpIpCommandPublisher0(ipAddress, CONTROL_PORT);
liveViewControl = new PtpIpLiveViewControl(context, ipAddress, STREAM_PORT);
asyncReceiver = new PtpIpAsyncResponseReceiver(ipAddress, ASYNC_RESPONSE_PORT);
statusChecker = new NikonStatusChecker(activity, commandPublisher, ipAddress, EVENT_PORT);
import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.IPtpIpCommunication;
import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.PtpIpAsyncResponseReceiver;
import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.PtpIpCommandPublisher;
+import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.PtpIpCommandPublisher0;
import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.connection.CanonConnection;
import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.liveview.PtpIpLiveViewControl;
import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.playback.CanonPlaybackControl;
private final PtpIpHardwareStatus hardwareStatus;
private final PtpIpButtonControl ptpIpButtonControl;
private final CanonConnection canonConnection;
+ //private final PtpIpCommandPublisher0 commandPublisher;
private final PtpIpCommandPublisher commandPublisher;
private final PtpIpLiveViewControl liveViewControl;
private final PtpIpAsyncResponseReceiver asyncReceiver;
ipAddress = "192.168.0.1";
}
- commandPublisher = new PtpIpCommandPublisher(ipAddress, CONTROL_PORT);
+ commandPublisher = new PtpIpCommandPublisher(ipAddress, CONTROL_PORT, false, false);
+ //commandPublisher = new PtpIpCommandPublisher0(ipAddress, CONTROL_PORT);
liveViewControl = new PtpIpLiveViewControl(context, ipAddress, STREAM_PORT);
asyncReceiver = new PtpIpAsyncResponseReceiver(ipAddress, ASYNC_RESPONSE_PORT);
statusChecker = new PtpIpStatusChecker(context, commandPublisher, ipAddress, EVENT_PORT);
// デバッグ用: ログ(logcat)に通信結果を残すかどうか
boolean dumpLog();
+
+ // リトライオーバー発生時、コマンドを再送するか?
+ boolean isRetrySend();
+
+ // 最後に1回余計に受信をするか?
+ boolean isLastReceiveRetry();
+
+ // 受信待ち再試行回数
+ int maxRetryCount();
+
+ // リトライオーバーで再送するとき、SeqNoをインクリメントするか
+ boolean isIncrementSequenceNumberToRetry();
+
}
boolean flushHoldQueue();
+ int isExistCommandMessageQueue(int id);
+ int getCurrentQueueSize();
+ boolean flushQueue();
+
void start();
void stop();
}
--- /dev/null
+package net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command
+
+import android.util.Log
+import net.osdn.gokigen.pkremote.camera.utils.SimpleLogDumper
+import java.io.BufferedReader
+import java.io.ByteArrayOutputStream
+import java.io.DataOutputStream
+import java.io.InputStream
+import java.net.InetSocketAddress
+import java.net.Socket
+import java.util.*
+
+class PtpIpCommandPublisher(private val ipAddress : String, private val portNumber : Int, private val tcpNoDelay : Boolean, private val waitForever: Boolean) : IPtpIpCommandPublisher, IPtpIpCommunication
+{
+ private var isConnected = false
+ private var isStart = false
+ private var isHold = false
+ private var holdId = 0
+
+ private var socket : Socket? = null
+ private var dos: DataOutputStream? = null
+ private var bufferedReader: BufferedReader? = null
+
+ private var sequenceNumber = SEQUENCE_START_NUMBER
+ private var commandQueue: Queue<IPtpIpCommand> = ArrayDeque()
+ private var holdCommandQueue: Queue<IPtpIpCommand> = ArrayDeque()
+
+ init
+ {
+ commandQueue.clear()
+ holdCommandQueue.clear()
+ }
+
+ override fun isConnected(): Boolean
+ {
+ return (isConnected)
+ }
+
+ override fun connect(): Boolean
+ {
+ try
+ {
+ Log.v(TAG, " connect()")
+ socket = Socket()
+ socket?.tcpNoDelay = tcpNoDelay
+ if (tcpNoDelay)
+ {
+ //socket?.tcpNoDelay = true
+ //socket?.keepAlive = false
+ socket?.keepAlive = false
+ //socket?.setPerformancePreferences(0, 1, 2)
+ socket?.setPerformancePreferences(0, 1, 2)
+ //socket?.setPerformancePreferences(0, 1, 2)
+ //socket?.setPerformancePreferences(1, 0, 0)
+ //socket?.setPerformancePreferences(0, 0, 2)
+ socket?.oobInline = true
+ //socket?.reuseAddress = false
+ socket?.trafficClass = 0x80 // 0x80
+ socket?.soTimeout = 0
+ //socket?.soTimeout = 0
+ //socket?.receiveBufferSize = 8192 // 10240 // 16384 // 6144// 8192 // 49152 // 65536 // 32768
+ //socket?.sendBufferSize = 1024 // 8192 // 4096 // 2048 // 10240
+ socket?.setSoLinger(true, 500)
+ //socket?.setReceiveBufferSize(2097152);
+ //socket?.setSendBufferSize(524288);
+
+ Log.v(TAG, " SOCKET (SEND:${socket?.sendBufferSize}, RECV:${socket?.receiveBufferSize}) oob:${socket?.oobInline} SO_TIMEOUT:${socket?.soTimeout}ms trafficClass:${socket?.trafficClass}")
+ }
+ socket?.connect(InetSocketAddress(ipAddress, portNumber), 0)
+ isConnected = true
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ isConnected = false
+ socket = null
+ }
+ return (isConnected)
+ }
+
+ override fun disconnect()
+ {
+ try
+ {
+ dos?.close()
+ bufferedReader?.close()
+ socket?.close()
+ commandQueue.clear()
+ }
+ catch (e : Exception)
+ {
+ e.printStackTrace()
+ }
+ System.gc()
+
+ sequenceNumber = SEQUENCE_START_NUMBER
+ isConnected = false
+ isStart = false
+ dos = null
+ bufferedReader = null
+ socket = null
+ }
+
+ override fun start()
+ {
+ if (isStart)
+ {
+ // すでにコマンドのスレッド動作中なので抜ける
+ return
+ }
+ if (socket == null)
+ {
+ isStart = false
+ Log.v(TAG, " SOCKET IS NULL. (cannot start)")
+ return
+ }
+
+ isStart = true
+ Log.v(TAG, " start()")
+ val thread = Thread {
+ try
+ {
+ dos = DataOutputStream(socket?.getOutputStream())
+ while (isStart)
+ {
+ try
+ {
+ val command = commandQueue.poll()
+ command?.let { issueCommand(it) }
+ Thread.sleep(COMMAND_POLL_QUEUE_MS.toLong())
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+ }
+ catch (e: Exception)
+ {
+ Log.v(TAG, "<<<<< IP : $ipAddress port : $portNumber >>>>>")
+ e.printStackTrace()
+ }
+ }
+ try
+ {
+ thread.start()
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+ override fun stop()
+ {
+ isStart = false
+ commandQueue.clear()
+ }
+
+ override fun enqueueCommand(command: IPtpIpCommand): Boolean
+ {
+ try
+ {
+ if (isHold)
+ {
+ return (if (holdId == command.holdId) {
+ if (command.isRelease)
+ {
+ // コマンドをキューに積んだ後、リリースする
+ val ret = commandQueue.offer(command)
+ isHold = false
+
+ // 溜まっているキューを積みなおす
+ while (holdCommandQueue.size != 0)
+ {
+ val queuedCommand = holdCommandQueue.poll()
+ commandQueue.offer(queuedCommand)
+ if (queuedCommand != null && queuedCommand.isHold)
+ {
+ // 特定シーケンスに入った場合は、そこで積みなおすのをやめる
+ isHold = true
+ holdId = queuedCommand.holdId
+ break
+ }
+ }
+ return ret
+ }
+ commandQueue.offer(command)
+ }
+ else
+ {
+ // 特定シーケンスではなかったので HOLD
+ holdCommandQueue.offer(command)
+ })
+ }
+ if (command.isHold)
+ {
+ isHold = true
+ holdId = command.holdId
+ }
+ if (commandQueue.size > 1)
+ {
+ // たまっているときだけログを吐く
+ Log.v(TAG, "Enqueue [ID: " + command.id + "] size: " + commandQueue.size)
+ }
+ return (commandQueue.offer(command))
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ return (false)
+ }
+
+ override fun getCurrentQueueSize(): Int
+ {
+ return commandQueue.size
+ }
+
+ override fun flushQueue(): Boolean
+ {
+ Log.v(TAG, " flushQueue() size: ${commandQueue.size}")
+ // TODO: たまっているキューをダンプする
+ commandQueue.clear()
+ System.gc()
+ return (true)
+ }
+
+ override fun isExistCommandMessageQueue(id: Int): Int
+ {
+ var count = 0
+ for (cmd in commandQueue)
+ {
+ if (cmd.id == id)
+ {
+ count++
+ }
+ }
+ return count
+ }
+
+ override fun flushHoldQueue(): Boolean
+ {
+ Log.v(TAG, " flushHoldQueue()")
+ holdCommandQueue.clear()
+ System.gc()
+ return (true)
+ }
+
+ private fun issueCommand(command: IPtpIpCommand)
+ {
+ try
+ {
+ var retryOver = true
+ while (retryOver)
+ {
+ //Log.v(TAG, "issueCommand : " + command.getId());
+ val commandBody = command.commandBody()
+ if (commandBody != null)
+ {
+ // コマンドボディが入っていた場合には、コマンド送信(入っていない場合は受信待ち)
+ sendToCamera(command.dumpLog(), commandBody, command.useSequenceNumber(), command.embeddedSequenceNumberIndex())
+ val commandBody2 = command.commandBody2()
+ if (commandBody2 != null)
+ {
+ // コマンドボディの2つめが入っていた場合には、コマンドを連続送信する
+ sendToCamera(command.dumpLog(), commandBody2, command.useSequenceNumber(), command.embeddedSequenceNumberIndex2())
+ }
+ val commandBody3 = command.commandBody3()
+ if (commandBody3 != null)
+ {
+ // コマンドボディの3つめが入っていた場合には、コマンドを連続送信する
+ sendToCamera(command.dumpLog(), commandBody3, command.useSequenceNumber(), command.embeddedSequenceNumberIndex3())
+ }
+ if (command.isIncrementSeqNumber)
+ {
+ // シーケンス番号を更新する
+ sequenceNumber++
+ }
+ }
+ retryOver = receiveFromCamera(command)
+ if ((retryOver)&&(commandBody != null))
+ {
+ if (!command.isRetrySend)
+ {
+ while (retryOver)
+ {
+ // コマンドを再送信しない場合はここで応答を待つ...
+ retryOver = receiveFromCamera(command)
+ }
+ break
+ }
+ if (!command.isIncrementSequenceNumberToRetry)
+ {
+ // 再送信...のために、シーケンス番号を戻す...
+ sequenceNumber--
+ }
+ }
+ }
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+ /**
+ * カメラにコマンドを送信する(メイン部分)
+ *
+ */
+ private fun sendToCamera(isDumpReceiveLog: Boolean, byte_array: ByteArray, useSequenceNumber: Boolean, embeddedSequenceIndex: Int)
+ {
+ try
+ {
+ if (dos == null)
+ {
+ Log.v(TAG, " DataOutputStream is null.")
+ return
+ }
+
+ // メッセージボディを加工: 最初に4バイトのレングス長をつける
+ val sendData = ByteArray(byte_array.size + 4)
+ sendData[0] = (byte_array.size + 4).toByte()
+ sendData[1] = 0x00
+ sendData[2] = 0x00
+ sendData[3] = 0x00
+ System.arraycopy(byte_array, 0, sendData, 4, byte_array.size)
+ if (useSequenceNumber)
+ {
+ // Sequence Number を反映させる
+ sendData[embeddedSequenceIndex ] = (0x000000ff and sequenceNumber).toByte()
+ sendData[embeddedSequenceIndex + 1] = (0x0000ff00 and sequenceNumber ushr 8 and 0x000000ff).toByte()
+ sendData[embeddedSequenceIndex + 2] = (0x00ff0000 and sequenceNumber ushr 16 and 0x000000ff).toByte()
+ sendData[embeddedSequenceIndex + 3] = (-0x1000000 and sequenceNumber ushr 24 and 0x000000ff).toByte()
+ if (isDumpReceiveLog)
+ {
+ Log.v(TAG, "----- SEQ No. : $sequenceNumber -----")
+ }
+ }
+ if (isDumpReceiveLog)
+ {
+ // ログに送信メッセージを出力する
+ SimpleLogDumper.dump_bytes("SEND[" + sendData.size + "] ", sendData)
+ }
+
+ // (データを)送信
+ dos?.write(sendData)
+ dos?.flush()
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+ private fun sleep(delayMs: Int)
+ {
+ try
+ {
+ Thread.sleep(delayMs.toLong())
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ }
+
+ /**
+ * カメラからにコマンドの結果を受信する(メイン部分)
+ *
+ */
+ private fun receiveFromCamera(command: IPtpIpCommand): Boolean
+ {
+ val callback = command.responseCallback()
+ var delayMs = command.receiveDelayMs()
+ if (delayMs < 0 || delayMs > COMMAND_SEND_RECEIVE_DURATION_MAX)
+ {
+ delayMs = COMMAND_SEND_RECEIVE_DURATION_MS
+ }
+
+ return (if (callback != null && callback.isReceiveMulti)
+ {
+ // 受信したら逐次「受信したよ」と応答するパターン
+ //Log.v(TAG, " receiveMulti() : $delayMs [id:${command.id}] SEQ: $sequenceNumber")
+ receiveMulti(command, delayMs)
+ }
+ else
+ {
+ //Log.v(TAG, " receiveSingle() : $delayMs [id:${command.id}] SEQ: $sequenceNumber")
+ receiveSingle(command, delayMs)
+ })
+ // 受信した後、すべてをまとめて「受信したよ」と応答するパターン
+ }
+
+ private fun receiveSingle(command: IPtpIpCommand, delayMs: Int): Boolean
+ {
+ val isDumpReceiveLog = command.dumpLog()
+ val id = command.id
+ val callback = command.responseCallback()
+ try
+ {
+ val receiveMessageBufferSize = BUFFER_SIZE
+ val byteArray = ByteArray(receiveMessageBufferSize)
+ val inputStream = socket?.getInputStream()
+ if (inputStream == null)
+ {
+ Log.v(TAG, " InputStream is NULL... RECEIVE ABORTED.")
+ receivedAllMessage(isDumpReceiveLog, id, null, callback)
+ return (false)
+ }
+
+ // 初回データが受信バッファにデータが溜まるまで待つ...
+ var readBytes = waitForReceive(inputStream, delayMs, command.maxRetryCount())
+ if (readBytes <= 0)
+ {
+ // リトライオーバー...
+ Log.v(TAG, " RECEIVE : RETRY OVER...... : $delayMs ms x ${command.maxRetryCount()} SEQ: $sequenceNumber isRetry: ${command.isRetrySend}")
+ if (!command.isRetrySend)
+ {
+ // 再送しない場合には、応答がないことを通知する
+ receivedAllMessage(isDumpReceiveLog, id, null, callback)
+ return (false)
+ }
+ return (true)
+ }
+
+ // 受信したデータをバッファに突っ込む
+ var receivedLength = 0
+ val byteStream = ByteArrayOutputStream()
+ while (readBytes > 0)
+ {
+ readBytes = inputStream.read(byteArray, 0, receiveMessageBufferSize)
+ if (readBytes <= 0)
+ {
+ Log.v(TAG, " RECEIVED MESSAGE FINISHED ($readBytes)")
+ break
+ }
+ byteStream.write(byteArray, 0, readBytes)
+ sleep(delayMs)
+ receivedLength += readBytes
+ readBytes = inputStream.available()
+ }
+
+ Log.v(TAG, " receivedLength : $receivedLength")
+ if (receivedLength >= 4)
+ {
+ val outputStream = cutHeader(byteStream)
+ receivedAllMessage(isDumpReceiveLog, id, outputStream.toByteArray(), callback)
+ }
+ else
+ {
+ receivedAllMessage(isDumpReceiveLog, id, byteStream.toByteArray(), callback)
+ }
+ System.gc()
+ }
+ catch (e: Throwable)
+ {
+ e.printStackTrace()
+ System.gc()
+ }
+ return false
+ }
+
+ private fun receivedAllMessage(isDumpReceiveLog: Boolean, id: Int, body: ByteArray?, callback: IPtpIpCommandCallback?)
+ {
+ Log.v(TAG, "receivedAllMessage() : " + (body?.size ?: 0) + " bytes.")
+ if ((isDumpReceiveLog)&&(body != null))
+ {
+ // ログに受信メッセージを出力する
+ SimpleLogDumper.dump_bytes("RECV[" + body.size + "] ", body)
+ }
+ callback?.receivedMessage(id, body)
+ }
+
+ private fun receiveMulti(command: IPtpIpCommand, delayMs: Int): Boolean
+ {
+ val isDumpLog = command.dumpLog()
+ var maxRetryCount = command.maxRetryCount()
+ val id = command.id
+ val callback = command.responseCallback()
+ try
+ {
+ // Log.v(TAG, " ===== receive_multi() =====")
+ val receiveMessageBufferSize = BUFFER_SIZE
+ val byteArray = ByteArray(receiveMessageBufferSize)
+ val inputStream = socket?.getInputStream()
+ if (inputStream == null)
+ {
+ Log.v(TAG, " InputStream is NULL... RECEIVE ABORTED.")
+ return (false)
+ }
+
+ // 初回データが受信バッファにデータが溜まるまで待つ...
+ var readBytes = waitForReceive(inputStream, delayMs, command.maxRetryCount())
+ if (readBytes <= 0)
+ {
+ // リトライオーバー...
+ Log.v(TAG, " RECEIVE : RETRY OVER...... : $delayMs ms x ${command.maxRetryCount()} SEQ: $sequenceNumber ")
+ if (command.isRetrySend)
+ {
+ // 要求を再送する場合、、、ダメな場合は受信待ちとする
+ Log.v(TAG, " --- SEND RETRY ---")
+ return (true)
+ }
+ callback?.receivedMessage(id, null)
+ return (false)
+ }
+
+ // 初回データの読み込み...
+ var targetLength = parseDataLength(byteArray, readBytes)
+ readBytes = inputStream.read(byteArray, 0, receiveMessageBufferSize)
+ var receivedLength = readBytes
+ if (targetLength <= 0)
+ {
+ // もう一回データを読み直す...
+ targetLength = parseDataLength(byteArray, readBytes)
+ }
+ if ((targetLength == 0)&&(readBytes > 0))
+ {
+ // 知らないデータがついている...ダンプしてみる
+ // Log.v(TAG, " RECEIVE UNKNOWN BYTES : ${readBytes}")
+ if (isDumpLog)
+ {
+ // ログに送信メッセージを出力する
+ SimpleLogDumper.dump_bytes("RECV.UNKNOWN[${readBytes}] ", byteArray)
+ }
+ callback?.receivedMessage(id, null)
+ return (false)
+ }
+
+ if ((targetLength <= 0)||(readBytes <= 0))
+ {
+ // 受信サイズ異常の場合...
+ if (isDumpLog)
+ {
+ if (receivedLength > 0)
+ {
+ SimpleLogDumper.dump_bytes("WRONG DATA : ", byteArray.copyOfRange(0, Math.min(receivedLength, 64)))
+ }
+ Log.v(TAG, " WRONG LENGTH. : $targetLength READ : $receivedLength bytes.")
+ }
+ callback?.receivedMessage(id, null)
+
+ // 受信したデータが不足しているので、もう一度受信待ち
+ Log.v(TAG, " 1st receive : AGAIN. [$readBytes][$targetLength]")
+ return (true)
+ }
+
+ // 初回データの受信を報告する。
+ if (isDumpLog)
+ {
+ Log.v(TAG, " -=-=-=- 1st CALL : read_bytes : " + readBytes + "(" + receivedLength + ") : target_length : " + targetLength + " buffer SIZE : " + byteArray.size)
+ }
+ callback?.onReceiveProgress(receivedLength, targetLength, byteArray.copyOfRange(fromIndex = 0, toIndex = receivedLength))
+
+ var isWaitLogging = true
+ while ((maxRetryCount > 0)&&(readBytes >= 0)&&(receivedLength < targetLength))
+ {
+ sleep(delayMs)
+ readBytes = inputStream.available()
+ if (readBytes <= 0)
+ {
+ if (isWaitLogging)
+ {
+ Log.v(TAG, " WAIT is.available() ... [length: $receivedLength, target: $targetLength] $readBytes bytes, retry : $maxRetryCount SEQ: $sequenceNumber")
+ isWaitLogging = false
+ }
+ maxRetryCount--
+ continue
+ }
+ if (!isWaitLogging)
+ {
+ Log.v(TAG, " WAIT FOR RECEIVE COUNT: $maxRetryCount (SEQ: $sequenceNumber)")
+ }
+
+ readBytes = inputStream.read(byteArray, 0, receiveMessageBufferSize)
+ if (readBytes <= 0)
+ {
+ if (isDumpLog)
+ {
+ Log.v(TAG, " RECEIVED MESSAGE FINISHED ($readBytes) [receivedLength: $receivedLength, targetLength: $targetLength]")
+ }
+ break
+ }
+ receivedLength += readBytes
+ callback?.onReceiveProgress(receivedLength, targetLength, byteArray.copyOfRange(0, readBytes))
+ maxRetryCount = command.maxRetryCount()
+ }
+
+ // 最後のデータを受信した後にもう一度受信が必要な場合の処理...
+ if (command.isLastReceiveRetry)
+ {
+ var responseReceive = true
+ try
+ {
+ while (responseReceive)
+ {
+ Log.v(TAG, " --- isLastReceiveRetry is true --- SEQ: $sequenceNumber")
+ sleep(delayMs)
+ if (inputStream.available() > 0)
+ {
+ readBytes = inputStream.read(byteArray, 0, receiveMessageBufferSize)
+ if (readBytes > 0)
+ {
+ receivedLength += readBytes
+ callback?.onReceiveProgress(receivedLength, targetLength, byteArray.copyOfRange(0, readBytes))
+ Log.v(TAG, " --- isLastReceiveRetry: onReceiveProgress() $readBytes bytes. --- SEQ: $sequenceNumber ")
+ }
+ responseReceive = false
+ }
+ else
+ {
+ Log.v(TAG, " --- inputStream.available() is <= 0 --- : ${inputStream.available()} SEQ: $sequenceNumber")
+ responseReceive = false
+ }
+ }
+ }
+ catch (ex: Exception)
+ {
+ ex.printStackTrace()
+ }
+ }
+
+ // 終了報告...
+ if (isDumpLog)
+ {
+ Log.v(TAG, " --- receive_multi : $id ($readBytes) [$maxRetryCount] $receiveMessageBufferSize ($receivedLength) SEQ: $sequenceNumber")
+ }
+ val copyBytes = if (byteArray.size > receivedLength) { receivedLength } else { byteArray.size }
+ callback?.receivedMessage(id, byteArray.copyOfRange(0, copyBytes))
+ }
+ catch (e: Throwable)
+ {
+ e.printStackTrace()
+ }
+ return (false)
+ }
+
+ private fun parseDataLength(byte_array: ByteArray, read_bytes: Int): Int
+ {
+ var offset = 0
+ var lenlen = 0
+ try
+ {
+ if (read_bytes > 20)
+ {
+ if (byte_array[offset + 4].toUByte().toInt() == 0x07)
+ {
+ // 前の応答が入っていると考える... レングスバイト分読み飛ばす
+ offset = byte_array[offset].toUByte().toInt()
+ }
+ if (byte_array[offset + 4].toUByte().toInt() == 0x09)
+ {
+ // データバイト...
+ lenlen = (byte_array[offset + 15].toUByte().toInt() and 0xff shl 24) + (byte_array[offset + 14].toUByte().toInt() and 0xff shl 16) + (byte_array[offset + 13].toUByte().toInt() and 0xff shl 8) + (byte_array[offset + 12].toUByte().toInt() and 0xff)
+ }
+ }
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ return (lenlen)
+ }
+
+ private fun cutHeader(receivedBuffer: ByteArrayOutputStream): ByteArrayOutputStream
+ {
+ try
+ {
+ val byteArray = receivedBuffer.toByteArray()
+ val limit = byteArray.size
+ var lenlen = 0
+ val len = (byteArray[3].toUByte().toInt() and 0xff shl 24) + (byteArray[2].toUByte().toInt() and 0xff shl 16) + (byteArray[1].toUByte().toInt() and 0xff shl 8) + (byteArray[0].toUByte().toInt() and 0xff)
+ val packetType = byteArray[4].toUByte().toInt() and 0xff
+ if ((limit == len)||(limit < 16384))
+ {
+ // 応答は1つしか入っていない。もしくは受信データサイズが16kBの場合は、そのまま返す。
+ return (receivedBuffer)
+ }
+
+ if (packetType == 0x09)
+ {
+ lenlen = (byteArray[15].toUByte().toInt() and 0xff shl 24) + (byteArray[14].toUByte().toInt() and 0xff shl 16) + (byteArray[13].toUByte().toInt() and 0xff shl 8) + (byteArray[12].toUByte().toInt() and 0xff)
+ }
+
+ if (lenlen == 0)
+ {
+ // データとしては変なので、なにもしない
+ return receivedBuffer
+ }
+ val outputStream = ByteArrayOutputStream()
+ var position = 20 // ヘッダ込の先頭
+ while (position < limit)
+ {
+ lenlen = (byteArray[position + 3].toUByte().toInt() and 0xff shl 24) + (byteArray[position + 2].toUByte().toInt() and 0xff shl 16) + (byteArray[position + 1].toUByte().toInt() and 0xff shl 8) + (byteArray[position].toUByte().toInt() and 0xff)
+
+ val copyByte = Math.min(limit - (position + 12), lenlen - 12)
+ outputStream.write(byteArray, position + 12, copyByte)
+ position += lenlen
+ }
+ return (outputStream)
+ }
+ catch (e: Throwable)
+ {
+ e.printStackTrace()
+ System.gc()
+ }
+ return (receivedBuffer)
+ }
+
+ private fun waitForReceive(inputStream : InputStream, delayMs: Int, retryCnt : Int): Int
+ {
+ var retryCount = retryCnt
+ var isLogOutput = true
+ var readBytes = 0
+ try
+ {
+ while ((retryCount >= 0) && (readBytes <= 0))
+ {
+ sleep(delayMs)
+ readBytes = inputStream.available()
+ if (readBytes <= 0) // if (readBytes <= 0)
+ {
+ if (isLogOutput)
+ {
+ Log.v(TAG, "waitForReceive:: is.available() WAIT... : $delayMs ms (Count : $retryCount/$retryCnt) SEQ: $sequenceNumber")
+ isLogOutput = false
+ }
+ if (!waitForever)
+ {
+ retryCount--
+ }
+ else
+ {
+ Log.v(TAG, "waitForReceive: wait forever ")
+ isLogOutput = false
+ }
+ }
+ }
+ if (!isLogOutput)
+ {
+ Log.v(TAG, " --- waitForReceive : $readBytes bytes. (RetryCount : $retryCount/$retryCnt)")
+ }
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ }
+ return (readBytes)
+ }
+
+ companion object
+ {
+ private val TAG = PtpIpCommandPublisher::class.java.simpleName
+
+ private const val SEQUENCE_START_NUMBER = 1
+ private const val BUFFER_SIZE = 1024 * 1024 + 16 // 受信バッファは 1MB
+ private const val COMMAND_SEND_RECEIVE_DURATION_MS = 5
+ private const val COMMAND_SEND_RECEIVE_DURATION_MAX = 3000
+ private const val COMMAND_POLL_QUEUE_MS = 5 // 5
+ }
+}
import static net.osdn.gokigen.pkremote.camera.utils.SimpleLogDumper.dump_bytes;
-public class PtpIpCommandPublisher implements IPtpIpCommandPublisher, IPtpIpCommunication
+public class PtpIpCommandPublisher0 implements IPtpIpCommandPublisher, IPtpIpCommunication
{
- private static final String TAG = PtpIpCommandPublisher.class.getSimpleName();
+ private static final String TAG = PtpIpCommandPublisher0.class.getSimpleName();
private static final int SEQUENCE_START_NUMBER = 1;
private static final int BUFFER_SIZE = 1024 * 1024 + 16; // 受信バッファは 256kB
private DataOutputStream dos = null;
private BufferedReader bufferedReader = null;
private int sequenceNumber = SEQUENCE_START_NUMBER;
- private Queue<IPtpIpCommand> commandQueue;
- private Queue<IPtpIpCommand> holdCommandQueue;
+ private final Queue<IPtpIpCommand> commandQueue;
+ private final Queue<IPtpIpCommand> holdCommandQueue;
- public PtpIpCommandPublisher(@NonNull String ip, int portNumber)
+ public PtpIpCommandPublisher0(@NonNull String ip, int portNumber)
{
this.ipAddress = ip;
this.portNumber = portNumber;
return (true);
}
+ @Override
+ public int isExistCommandMessageQueue(int id)
+ {
+ int count = 0;
+ for (IPtpIpCommand cmd : commandQueue)
+ {
+ if (cmd.getId() == id)
+ {
+ count++;
+ }
+ }
+ return (count);
+ }
+
+ @Override
+ public int getCurrentQueueSize()
+ {
+ return (commandQueue.size());
+ }
+
+ @Override
+ public boolean flushQueue()
+ {
+ commandQueue.clear();
+ System.gc();
+ return (true);
+ }
+
private void issueCommand(@NonNull IPtpIpCommand command)
{
try
@Override
public int receiveDelayMs()
{
- return (15);
+ return (30);
}
@Override
{
return (true);
}
+
+ @Override
+ public boolean isRetrySend()
+ {
+ return (false);
+ }
+
+ @Override
+ public boolean isLastReceiveRetry()
+ {
+ return (false);
+ }
+
+ @Override
+ public int maxRetryCount()
+ {
+ return (3500);
+ }
+
+ @Override
+ public boolean isIncrementSequenceNumberToRetry()
+ {
+ return (false);
+ }
+
}
private final Activity activity;
private final PtpIpInterfaceProvider provider;
private final CanonFullImageReceiver fullImageReceiver;
- private final CanonSmallImageReceiver smallImageReciever;
- //private int delayMs = 20;
+ private final ICanonSmallImageReceiver smallImageReciever;
private String raw_suffix = "CR2";
- private boolean use_screennail_image = false;
- private CanonImageObjectReceiver canonImageObjectReceiver;
+ private boolean useScreennailImage = false;
+ private final CanonImageObjectReceiver canonImageObjectReceiver;
public CanonPlaybackControl(Activity activity, PtpIpInterfaceProvider provider)
{
+ int smallImageSequence = 0;
int delayMs = 20;
try
{
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
raw_suffix = preferences.getString(IPreferencePropertyAccessor.CANON_RAW_SUFFIX, IPreferencePropertyAccessor.CANON_RAW_SUFFIX_DEFAULT_VALUE);
- use_screennail_image = preferences.getBoolean(IPreferencePropertyAccessor.CANON_USE_SCREENNAIL_AS_SMALL, false);
+ useScreennailImage = preferences.getBoolean(IPreferencePropertyAccessor.CANON_USE_SCREENNAIL_AS_SMALL, false);
try
{
delayMs = Integer.parseInt(preferences.getString(IPreferencePropertyAccessor.CANON_RECEIVE_WAIT, IPreferencePropertyAccessor.CANON_RECEIVE_WAIT_DEFAULT_VALUE));
{
delayMs = 10; // 最短は 10msにする
}
+ try
+ {
+ smallImageSequence = Integer.parseInt(preferences.getString(IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE, IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE_DEFAULT_VALUE));
+ }
+ catch (Exception ee)
+ {
+ ee.printStackTrace();
+ }
}
catch (Exception e)
{
this.activity = activity;
this.provider = provider;
this.fullImageReceiver = new CanonFullImageReceiver(activity, provider.getCommandPublisher());
- this.smallImageReciever = new CanonSmallImageReceiver(activity, provider.getCommandPublisher());
+ if (smallImageSequence == 1)
+ {
+ this.smallImageReciever = new CanonReducedImageReceiver(activity, provider.getCommandPublisher());
+ }
+ else
+ {
+ this.smallImageReciever = new CanonSmallImageReceiver(activity, provider.getCommandPublisher());
+ }
canonImageObjectReceiver = new CanonImageObjectReceiver(provider, delayMs);
-
}
@Override
{
Log.v(TAG, " downloadContentScreennail() " + path);
- if (!use_screennail_image)
+ if (!useScreennailImage)
{
// Thumbnail と同じ画像を表示する
downloadContentThumbnail(path, callback);
{
start = 1;
}
- //String indexStr = path.substring(start, path.indexOf("."));
- final String indexStr = path.substring(start);
- //Log.v(TAG, "downloadContentThumbnail() : [" + path + "] " + indexStr);
+ final String indexStr = path.substring(start);
CanonImageContentInfo content = canonImageObjectReceiver.getContentObject(indexStr);
if (content != null)
{
- IPtpIpCommandPublisher publisher = provider.getCommandPublisher();
- //int storageId = content.getStorageId();
int objectId = content.getId();
- // Log.v(TAG, "downloadContentThumbnail() " + indexStr + " [" + objectId + "] (" + storageId + ")");
+ IPtpIpCommandPublisher publisher = provider.getCommandPublisher();
publisher.enqueueCommand(new PtpIpCommandGeneric(new PtpIpThumbnailImageReceiver(activity, callback), objectId, false, 0, 0x910a, 8, objectId, 0x00032000));
}
}
{
return;
}
-
try
{
Thread thread = new Thread(new Runnable() {
try
{
Log.v(TAG, " showPictureStarted() ");
-
IPtpIpCommandPublisher publisher = provider.getCommandPublisher();
publisher.flushHoldQueue();
System.gc();
try
{
Log.v(TAG, " showPictureFinished() ");
-
IPtpIpCommandPublisher publisher = provider.getCommandPublisher();
publisher.flushHoldQueue();
System.gc();
e.printStackTrace();
}
}
-
}
--- /dev/null
+package net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.playback
+
+import android.app.Activity
+import android.util.Log
+import net.osdn.gokigen.pkremote.camera.interfaces.playback.IDownloadContentCallback
+import net.osdn.gokigen.pkremote.camera.interfaces.playback.IProgressEvent
+import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.IPtpIpCommandCallback
+import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.IPtpIpCommandPublisher
+import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.messages.PtpIpCommandCanonGetPartialObject
+import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.messages.PtpIpCommandGeneric
+import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.messages.specific.CanonRequestInnerDevelopEnd
+import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.messages.specific.CanonRequestInnerDevelopStart
+import java.io.ByteArrayOutputStream
+
+class CanonReducedImageReceiver(private val activity: Activity, private val publisher: IPtpIpCommandPublisher) : IPtpIpCommandCallback, ICanonSmallImageReceiver
+{
+ private val mine = this
+
+ private var callback: IDownloadContentCallback? = null
+ private var objectId = 0
+ private var isReceiveMulti = false
+ private var receivedFirstData = false
+
+ private var receivedTotalBytes = 0
+ private var receivedRemainBytes = 0
+
+
+ override fun issueCommand(objectId: Int, callback: IDownloadContentCallback?)
+ {
+ Log.v(TAG, " issueCommand() : ${objectId}")
+ if (this.objectId != 0)
+ {
+ // already issued
+ Log.v(TAG, " COMMAND IS ALREADY ISSUED. : $objectId")
+ return
+ }
+ this.callback = callback
+ this.objectId = objectId
+ publisher.enqueueCommand(CanonRequestInnerDevelopStart(object : IPtpIpCommandCallback {
+ override fun receivedMessage(id: Int, rx_body: ByteArray?) {
+ Log.v(TAG, " getRequestStatusEvent : $objectId " + (rx_body?.size ?: 0))
+ publisher.enqueueCommand(PtpIpCommandGeneric(mine, objectId + 5, false, objectId, 0x9116))
+ }
+ override fun onReceiveProgress(currentBytes: Int, totalBytes: Int, rx_body: ByteArray?) { }
+ override fun isReceiveMulti(): Boolean { return (false) }
+ }, objectId, false, objectId, objectId)) // 0x9141 : RequestInnerDevelopStart
+ }
+
+ override fun receivedMessage(id: Int, rx_body: ByteArray?)
+ {
+ try
+ {
+ when (id)
+ {
+ (objectId + 1) -> {
+ sendTransferComplete(rx_body)
+ }
+ (objectId + 2) -> {
+ Log.v(TAG, " requestInnerDevelopEnd() : $objectId")
+ publisher.enqueueCommand(CanonRequestInnerDevelopEnd(this, objectId + 3, false, objectId)) // 0x9143 : RequestInnerDevelopEnd
+ }
+ (objectId + 3) -> {
+ //Log.v(TAG, " --- COMMAND RESET : " + objectId + " --- ");
+
+ // リセットコマンドを送ってみる
+ publisher.enqueueCommand(PtpIpCommandGeneric(this, objectId + 4, false, objectId, 0x902f))
+ }
+ (objectId + 4) -> {
+ // 画像取得終了
+ Log.v(TAG, " ----- SMALL IMAGE RECEIVE SEQUENCE FINISHED : $objectId")
+ callback!!.onCompleted()
+ objectId = 0
+ callback = null
+ receivedTotalBytes = 0
+ receivedRemainBytes = 0
+ receivedFirstData = false
+ System.gc()
+ }
+ (objectId + 5) -> {
+ requestGetPartialObject(rx_body)
+ }
+ else -> {
+ Log.v(TAG, " RECEIVED UNKNOWN ID : $id")
+ }
+ }
+ }
+ catch (e: Exception)
+ {
+ e.printStackTrace()
+ callback?.onErrorOccurred(e)
+ }
+ }
+
+ override fun onReceiveProgress(currentBytes: Int, totalBytes: Int, rx_body: ByteArray?)
+ {
+ val body = cutHeader(rx_body)
+ val length = body?.size ?: 0
+ Log.v(TAG, " onReceiveProgress() $currentBytes/$totalBytes ($length bytes.)")
+ callback?.onProgress(body, length, object : IProgressEvent
+ {
+ override fun getProgress(): Float { return (currentBytes.toFloat() / totalBytes.toFloat()) }
+ override fun isCancellable(): Boolean { return (false) }
+ override fun requestCancellation() { }
+ })
+ }
+
+ private fun cutHeader(rx_body: ByteArray?): ByteArray?
+ {
+ if (rx_body == null)
+ {
+ return (null)
+ }
+ val length = rx_body.size
+ var dataPosition = 0
+ val byteStream = ByteArrayOutputStream()
+ if (!receivedFirstData)
+ {
+ // 初回データを読み込んだ
+ receivedFirstData = true
+
+ // データを最初に読んだとき。ヘッダ部分を読み飛ばす
+ dataPosition = rx_body[0].toInt() and 0xff
+ }
+ else if (receivedRemainBytes > 0)
+ {
+ //Log.v(TAG, " >>> [ remain_bytes : " + received_remain_bytes + "] ( length : " + length + ") " + data_position);
+ //SimpleLogDumper.dump_bytes("[zzz]", Arrays.copyOfRange(rx_body, data_position, (data_position + 160)));
+
+ // データの読み込みが途中だった場合...
+ if (length < receivedRemainBytes)
+ {
+ // 全部コピーする、足りないバイト数は残す
+ receivedRemainBytes = receivedRemainBytes - length
+ receivedTotalBytes = receivedTotalBytes + rx_body.size
+ return rx_body
+ }
+ else
+ {
+ byteStream.write(rx_body, dataPosition, receivedRemainBytes)
+ dataPosition = receivedRemainBytes
+ receivedRemainBytes = 0
+ }
+ }
+ while (dataPosition <= length - 12)
+ {
+ val bodySize: Int = (rx_body[dataPosition].toUByte().toInt() and 0xff) + (rx_body[dataPosition + 1].toUByte().toInt() and 0xff shl 8) + (rx_body[dataPosition + 2].toUByte().toInt() and 0xff shl 16) + (rx_body[dataPosition + 3].toUByte().toInt() and 0xff shl 24)
+ if (bodySize <= 12)
+ {
+ Log.v(TAG, " BODY SIZE IS SMALL : " + dataPosition + " (" + bodySize + ") [" + receivedRemainBytes + "] " + rx_body.size + " ")
+ //int startpos = (data_position > 48) ? (data_position - 48) : 0;
+ //SimpleLogDumper.dump_bytes("[xxx]", Arrays.copyOfRange(rx_body, startpos, (data_position + 48)));
+ break
+ }
+
+ // Log.v(TAG, " RX DATA : " + data_position + " (" + body_size + ") [" + received_remain_bytes + "] (" + received_total_bytes + ")");
+ //SimpleLogDumper.dump_bytes("[yyy] " + data_position + ": ", Arrays.copyOfRange(rx_body, data_position, (data_position + 64)));
+ if (dataPosition + bodySize > length)
+ {
+ // データがすべてバッファ内になかったときは、バッファすべてコピーして残ったサイズを記憶しておく。
+ val copysize = length - (dataPosition + 12)
+ byteStream.write(rx_body, dataPosition + 12, copysize)
+ receivedRemainBytes = bodySize - copysize - 12 // マイナス12は、ヘッダ分
+ receivedTotalBytes = receivedTotalBytes + copysize
+ // Log.v(TAG, " --- copy : " + (data_position + 12) + " " + copysize + " remain : " + received_remain_bytes + " body size : " + body_size);
+ break
+ }
+ try
+ {
+ byteStream.write(rx_body, dataPosition + 12, bodySize - 12)
+ dataPosition = dataPosition + bodySize
+ receivedTotalBytes = receivedTotalBytes + 12
+ //Log.v(TAG, " --- COPY : " + (data_position + 12) + " " + (body_size - 12) + " remain : " + received_remain_bytes);
+ }
+ catch (e: Exception)
+ {
+ Log.v(TAG, " pos : $dataPosition size : $bodySize length : $length")
+ e.printStackTrace()
+ }
+ }
+ return byteStream.toByteArray()
+ }
+
+ override fun isReceiveMulti(): Boolean
+ {
+ return (isReceiveMulti)
+ }
+
+ private fun requestGetPartialObject(rx_body: ByteArray?) {
+ Log.v(TAG, " requestGetPartialObject() : $objectId")
+ isReceiveMulti = true
+ receivedFirstData = false
+
+ // 0x9107 : GetPartialObject (元は 0x00020000)
+ val pictureLength: Int
+ if (rx_body != null && rx_body.size > 52) {
+ val dataIndex = 48
+ pictureLength = (rx_body[dataIndex].toUByte().toInt() and 0xff) + (rx_body[dataIndex + 1].toUByte().toInt() and 0xff shl 8) + (rx_body[dataIndex + 2].toUByte().toInt() and 0xff shl 16) + (rx_body[dataIndex + 3].toUByte().toInt() and 0xff shl 24)
+ }
+ else
+ {
+ pictureLength = 0x020000
+ }
+ publisher.enqueueCommand(PtpIpCommandCanonGetPartialObject(this, objectId + 1, false, objectId, 0x01, 0x00, pictureLength, pictureLength))
+ }
+
+ private fun sendTransferComplete(rx_body: ByteArray?)
+ {
+ Log.v(TAG, " sendTransferComplete(), id : $objectId size: " + (rx_body?.size ?: 0))
+ publisher.enqueueCommand(PtpIpCommandGeneric(this, objectId + 2, false, objectId, 0x9117, 4, 0x01)) // 0x9117 : TransferComplete
+ isReceiveMulti = false
+ }
+
+ companion object
+ {
+ private val TAG = CanonReducedImageReceiver::class.java.simpleName
+ }
+}
import java.io.ByteArrayOutputStream;
-public class CanonSmallImageReceiver implements IPtpIpCommandCallback
+public class CanonSmallImageReceiver implements IPtpIpCommandCallback, ICanonSmallImageReceiver
{
private static final String TAG = CanonSmallImageReceiver.class.getSimpleName();
this.mine = this;
}
+ @Override
public void issueCommand(final int objectId, IDownloadContentCallback callback)
{
if (this.objectId != 0)
--- /dev/null
+package net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.playback;
+
+import net.osdn.gokigen.pkremote.camera.interfaces.playback.IDownloadContentCallback;
+
+public interface ICanonSmallImageReceiver
+{
+ void issueCommand(final int objectId, IDownloadContentCallback callback);
+}
String CANON_CONNECTION_SEQUENCE = "canon_connection_mode";
String CANON_CONNECTION_SEQUENCE_DEFAULT_VALUE = "0";
+ String CANON_SMALL_PICTURE_TYPE = "canon_small_picture_type";
+ String CANON_SMALL_PICTURE_TYPE_DEFAULT_VALUE = "0";
+
/*
//String GR2_DISPLAY_MODE = "gr2_display_mode";
//String GR2_DISPLAY_MODE_DEFAULT_VALUE = "0";
if (!items.containsKey(IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE)) {
editor.putString(IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE, IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE_DEFAULT_VALUE);
}
+ if (!items.containsKey(IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE)) {
+ editor.putString(IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE, IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE_DEFAULT_VALUE);
+ }
editor.apply();
}
catch (Exception e)
if (!items.containsKey(IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE)) {
editor.putString(IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE, IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE_DEFAULT_VALUE);
}
+ if (!items.containsKey(IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE)) {
+ editor.putString(IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE, IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE_DEFAULT_VALUE);
+ }
editor.apply();
}
catch (Exception e)
if (!items.containsKey(IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE)) {
editor.putString(IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE, IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE_DEFAULT_VALUE);
}
+ if (!items.containsKey(IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE)) {
+ editor.putString(IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE, IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE_DEFAULT_VALUE);
+ }
editor.apply();
}
catch (Exception e)
if (!items.containsKey(IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE)) {
editor.putString(IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE, IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE_DEFAULT_VALUE);
}
+ if (!items.containsKey(IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE)) {
+ editor.putString(IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE, IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE_DEFAULT_VALUE);
+ }
editor.apply();
}
if (!items.containsKey(IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE)) {
editor.putString(IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE, IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE_DEFAULT_VALUE);
}
+ if (!items.containsKey(IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE)) {
+ editor.putString(IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE, IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE_DEFAULT_VALUE);
+ }
editor.apply();
}
catch (Exception e)
if (!items.containsKey(IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE)) {
editor.putString(IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE, IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE_DEFAULT_VALUE);
}
+ if (!items.containsKey(IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE)) {
+ editor.putString(IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE, IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE_DEFAULT_VALUE);
+ }
editor.apply();
}
catch (Exception e)
if (!items.containsKey(IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE)) {
editor.putString(IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE, IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE_DEFAULT_VALUE);
}
+ if (!items.containsKey(IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE)) {
+ editor.putString(IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE, IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE_DEFAULT_VALUE);
+ }
editor.apply();
}
catch (Exception e)
if (!items.containsKey(IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE)) {
editor.putString(IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE, IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE_DEFAULT_VALUE);
}
+ if (!items.containsKey(IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE)) {
+ editor.putString(IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE, IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE_DEFAULT_VALUE);
+ }
editor.apply();
}
catch (Exception e)
if (!items.containsKey(IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE)) {
editor.putString(IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE, IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE_DEFAULT_VALUE);
}
+ if (!items.containsKey(IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE)) {
+ editor.putString(IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE, IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE_DEFAULT_VALUE);
+ }
editor.apply();
}
catch (Exception e)
if (!items.containsKey(IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE)) {
editor.putString(IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE, IPreferencePropertyAccessor.CANON_CONNECTION_SEQUENCE_DEFAULT_VALUE);
}
+ if (!items.containsKey(IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE)) {
+ editor.putString(IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE, IPreferencePropertyAccessor.CANON_SMALL_PICTURE_TYPE_DEFAULT_VALUE);
+ }
editor.apply();
}
catch (Exception e)
<string name="pref_canon_connection_mode">接続シーケンス</string>
<string name="pref_summary_canon_connection_mode">通常、変更は不要です (初期値: TYPE0)</string>
+ <string name="pref_canon_small_picture_type">スモール画像取得シーケンス</string>
+ <string name="pref_summary_canon_small_picture_type">(初期値: TYPE0)</string>
+
</resources>
<item>2</item>
</string-array>
+ <string-array name="canon_small_picture_type">
+ <item>TYPE0</item>
+ <item>TYPE1</item>
+ </string-array>
+
+ <string-array name="canon_small_picture_type_value">
+ <item>0</item>
+ <item>1</item>
+ </string-array>
+
</resources>
<string name="pref_canon_connection_mode">Connection Sequence</string>
<string name="pref_summary_canon_connection_mode">default: TYPE0 </string>
+ <string name="pref_canon_small_picture_type">Small Picture Getting Sequence</string>
+ <string name="pref_summary_canon_small_picture_type">default: TYPE0 </string>
+
</resources>
android:summary="@string/pref_summary_canon_host_ip" />
<ListPreference
+ android:title="@string/pref_canon_small_picture_type"
+ android:summary="@string/pref_summary_canon_small_picture_type"
+ android:entryValues="@array/canon_small_picture_type_value"
+ android:entries="@array/canon_small_picture_type"
+ android:key="canon_small_picture_type"
+ android:defaultValue="0"/>
+
+ <ListPreference
android:title="@string/pref_canon_connection_mode"
android:summary="@string/pref_summary_canon_connection_mode"
android:entryValues="@array/canon_connection_mode_value"