OSDN Git Service

Canonのライブビュー通信安定性を向上させる。
authorMRSa <mrsa@myad.jp>
Sat, 19 Dec 2020 01:40:35 +0000 (10:40 +0900)
committerMRSa <mrsa@myad.jp>
Sat, 19 Dec 2020 01:40:35 +0000 (10:40 +0900)
13 files changed:
app/src/main/java/net/osdn/gokigen/a01d/camera/canon/wrapper/CanonInterfaceProvider.java
app/src/main/java/net/osdn/gokigen/a01d/camera/canon/wrapper/connection/CanonCameraConnectSequence.java
app/src/main/java/net/osdn/gokigen/a01d/camera/canon/wrapper/liveview/CanonLiveViewControl.java
app/src/main/java/net/osdn/gokigen/a01d/camera/canon/wrapper/liveview/CanonLiveViewImageReceiver.java [deleted file]
app/src/main/java/net/osdn/gokigen/a01d/camera/canon/wrapper/liveview/CanonLiveViewImageReceiver.kt [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/canon/wrapper/liveview/CanonLiveViewImageReceiverPrev.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/a01d/camera/ptpip/wrapper/command/IPtpIpMessages.java
app/src/main/java/net/osdn/gokigen/a01d/camera/ptpip/wrapper/command/PtpIpCommandPublisher.kt
app/src/main/java/net/osdn/gokigen/a01d/preference/IPreferencePropertyAccessor.java
app/src/main/java/net/osdn/gokigen/a01d/preference/canon/CanonPreferenceFragment.java
app/src/main/res/values-ja/strings.xml
app/src/main/res/values/strings.xml
app/src/main/res/xml/preferences_canon.xml

index 704b689..237e67c 100644 (file)
@@ -68,6 +68,7 @@ public class CanonInterfaceProvider implements IPtpIpInterfaceProvider, IDisplay
         this.activity = context;
 
         String ipAddress;
+        int delayMs = 30;
         try
         {
             SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
@@ -76,6 +77,22 @@ public class CanonInterfaceProvider implements IPtpIpInterfaceProvider, IDisplay
             {
                 ipAddress = "192.168.0.1";
             }
+            try
+            {
+                String delayMsStr = preferences.getString(IPreferencePropertyAccessor.CANON_LIVEVIEW_WAIT, IPreferencePropertyAccessor.CANON_LIVEVIEW_WAIT_DEFAULT_VALUE);
+                if (delayMsStr != null)
+                {
+                    delayMs = Integer.parseInt(delayMsStr);
+                }
+                if (delayMs < 10)
+                {
+                    delayMs = 10;
+                }
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+            }
         }
         catch (Exception e)
         {
@@ -84,7 +101,7 @@ public class CanonInterfaceProvider implements IPtpIpInterfaceProvider, IDisplay
         }
         Log.v(TAG, " Canon IP : " + ipAddress);
         commandPublisher = new PtpIpCommandPublisher(ipAddress, CONTROL_PORT, false, false);
-        liveViewControl = new CanonLiveViewControl(context, this, 10);  //
+        liveViewControl = new CanonLiveViewControl(context, this, delayMs);  //
         asyncReceiver = new PtpIpAsyncResponseReceiver(ipAddress, ASYNC_RESPONSE_PORT);
         statusChecker = new CanonStatusChecker(context, commandPublisher, ipAddress, EVENT_PORT);
         canonConnection = new CanonConnection(context, provider, this, statusChecker);
index 236ccaa..ff849c0 100644 (file)
@@ -29,7 +29,7 @@ public class CanonCameraConnectSequence implements Runnable, IPtpIpCommandCallba
     private final IPtpIpInterfaceProvider interfaceProvider;
     private final IPtpIpCommandPublisher commandIssuer;
     private final CanonStatusChecker statusChecker;
-    private boolean isDumpLog = false;
+    private final boolean isDumpLog = false;
 
     CanonCameraConnectSequence(@NonNull Activity context, @NonNull ICameraStatusReceiver statusReceiver, @NonNull final ICameraConnection cameraConnection, @NonNull IPtpIpInterfaceProvider interfaceProvider, @NonNull CanonStatusChecker statusChecker)
     {
@@ -157,7 +157,8 @@ public class CanonCameraConnectSequence implements Runnable, IPtpIpCommandCallba
             case SEQ_GET_EVENT1:
                 Log.v(TAG, " SEQ_GET_EVENT1 ");
                 interfaceProvider.getInformationReceiver().updateMessage(context.getString(R.string.canon_connect_connecting7), false, false, 0);
-                commandIssuer.enqueueCommand(new PtpIpCommandGeneric(this, SEQ_DEVICE_INFORMATION, isDumpLog, 0, 0x1001));
+                //commandIssuer.enqueueCommand(new PtpIpCommandGeneric(this, SEQ_DEVICE_INFORMATION, isDumpLog, 0, 0x1001));
+                commandIssuer.enqueueCommand(new PtpIpCommandGeneric(this, SEQ_SET_REMOTE_SHOOTING_MODE, isDumpLog, 0, 0x1001));
                 break;
 
             case SEQ_DEVICE_INFORMATION:
@@ -207,9 +208,29 @@ public class CanonCameraConnectSequence implements Runnable, IPtpIpCommandCallba
             case SEQ_SET_DEVICE_PROPERTY_3:
                 Log.v(TAG, " SEQ_SET_DEVICE_PROPERTY_3 ");
                 interfaceProvider.getInformationReceiver().updateMessage(context.getString(R.string.canon_connect_connecting12), false, false, 0);
+                //commandIssuer.enqueueCommand(new CanonSetDevicePropertyValue(this, SEQ_SET_REMOTE_SHOOTING_MODE, isDumpLog, 0, 300, 0xd1b0, 0x08));
                 commandIssuer.enqueueCommand(new CanonSetDevicePropertyValue(this, SEQ_DEVICE_PROPERTY_FINISHED, isDumpLog, 0, 300, 0xd1b0, 0x08));
                 break;
 
+            case SEQ_SET_REMOTE_SHOOTING_MODE:
+                Log.v(TAG, " SEQ_SET_REMOTE_SHOOTING_MODE ");
+                interfaceProvider.getInformationReceiver().updateMessage(context.getString(R.string.canon_connect_connecting12), false, false, 0);
+                try
+                {
+                    // ちょっと(250ms)待つ
+                    Thread.sleep(250);
+
+                    // コマンド発行
+                    //commandIssuer.enqueueCommand(new PtpIpCommandGeneric(this, SEQ_DEVICE_PROPERTY_FINISHED, isDumpLog, 0, 0x9086, 4, 0x00000001));
+                    commandIssuer.enqueueCommand(new PtpIpCommandGeneric(this, SEQ_DEVICE_INFORMATION, isDumpLog, 0, 0x9086, 4, 0x00000001));
+
+                }
+                catch (Exception e)
+                {
+                    e.printStackTrace();
+                }
+                break;
+
             case SEQ_DEVICE_PROPERTY_FINISHED:
                 Log.v(TAG, " SEQ_DEVICE_PROPERTY_FINISHED ");
                 interfaceProvider.getInformationReceiver().updateMessage(context.getString(R.string.connect_connect_finished), false, false, 0);
index af2ba87..8f2c441 100644 (file)
@@ -9,7 +9,7 @@ import net.osdn.gokigen.a01d.camera.ILiveViewControl;
 import net.osdn.gokigen.a01d.camera.ptpip.IPtpIpInterfaceProvider;
 import net.osdn.gokigen.a01d.camera.ptpip.wrapper.command.IPtpIpCommandPublisher;
 import net.osdn.gokigen.a01d.camera.ptpip.wrapper.command.IPtpIpCommunication;
-import net.osdn.gokigen.a01d.camera.ptpip.wrapper.command.messages.PtpIpCommandGeneric;
+import net.osdn.gokigen.a01d.camera.ptpip.wrapper.command.messages.PtpIpCommandGenericWithRetry;
 import net.osdn.gokigen.a01d.camera.ptpip.wrapper.liveview.IPtpIpLiveViewImageCallback;
 import net.osdn.gokigen.a01d.liveview.liveviewlistener.IImageDataReceiver;
 import net.osdn.gokigen.a01d.liveview.liveviewlistener.ILiveViewListener;
@@ -24,7 +24,8 @@ public class CanonLiveViewControl implements ILiveViewControl, ILiveViewListener
     private final String TAG = this.toString();
     private final IPtpIpCommandPublisher commandIssuer;
     private final int delayMs;
-    private CanonLiveViewImageReceiver imageReceiver;
+    //private CanonLiveViewImageReceiver imageReceiver;
+    private final CanonLiveViewImageReceiver imageReceiver;
     private IImageDataReceiver dataReceiver = null;
     private boolean liveViewIsReceiving = false;
     private boolean commandIssued = false;
@@ -33,7 +34,9 @@ public class CanonLiveViewControl implements ILiveViewControl, ILiveViewListener
     {
         this.commandIssuer = interfaceProvider.getCommandPublisher();
         this.delayMs = delayMs;
+        //this.imageReceiver = new CanonLiveViewImageReceiver(this);
         this.imageReceiver = new CanonLiveViewImageReceiver(this);
+        Log.v(TAG, " -=-=-=-=-=- CanonLiveViewControl : delay " + delayMs + " ms");
     }
 
     public ILiveViewListener getLiveViewListener()
@@ -65,7 +68,7 @@ public class CanonLiveViewControl implements ILiveViewControl, ILiveViewListener
                             if (!commandIssued)
                             {
                                 commandIssued = true;
-                                commandIssuer.enqueueCommand(new PtpIpCommandGeneric(imageReceiver, SEQ_GET_VIEWFRAME, 20, false, 0, 0x9153, 12, 0x00200000, 0x01, 0x00, 0x00));
+                                commandIssuer.enqueueCommand(new PtpIpCommandGenericWithRetry(imageReceiver, SEQ_GET_VIEWFRAME, delayMs, 2000, false, false, 0, 0x9153, 12, 0x00200000, 0x01, 0x00, 0x00));
                             }
                             try
                             {
@@ -152,7 +155,7 @@ public class CanonLiveViewControl implements ILiveViewControl, ILiveViewListener
         {
             if ((dataReceiver != null)&&(data != null))
             {
-                //Log.v(TAG, "  ---+++--- RECEIVED LV IMAGE ---+++--- : " + data.length + " bytes.");
+                Log.v(TAG, "  ---+++--- RECEIVED LV IMAGE ---+++--- : " + data.length + " bytes.");
                 //dataReceiver.setImageData(data, metadata);
                 if (data.length > 8)
                 {
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/canon/wrapper/liveview/CanonLiveViewImageReceiver.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/canon/wrapper/liveview/CanonLiveViewImageReceiver.java
deleted file mode 100644 (file)
index d1bc43d..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-package net.osdn.gokigen.a01d.camera.canon.wrapper.liveview;
-
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import net.osdn.gokigen.a01d.camera.ptpip.wrapper.command.IPtpIpCommandCallback;
-import net.osdn.gokigen.a01d.camera.ptpip.wrapper.liveview.IPtpIpLiveViewImageCallback;
-
-import java.io.ByteArrayOutputStream;
-
-public class CanonLiveViewImageReceiver implements IPtpIpCommandCallback
-{
-    private final String TAG = toString();
-
-    private IPtpIpLiveViewImageCallback callback;
-
-    private int received_total_bytes = 0;
-    private int received_remain_bytes = 0;
-
-    private int target_image_size = 0;
-    private boolean receivedFirstData = false;
-    private ByteArrayOutputStream byteStream;
-
-    CanonLiveViewImageReceiver(@NonNull IPtpIpLiveViewImageCallback callback)
-    {
-        this.callback = callback;
-        byteStream = new ByteArrayOutputStream();
-    }
-
-    @Override
-    public void receivedMessage(int id, byte[] rx_body)
-    {
-        try
-        {
-            // end of receive sequence.
-            //byte [] thumbnail = byteStream.toByteArray();
-            //Log.v(TAG, " TransferComplete() RECEIVED  : " + id + " size : " + target_image_size + " (" + thumbnail.length + ")");
-            //SimpleLogDumper.dump_bytes(" [xxxxx]", Arrays.copyOfRange(thumbnail, 0, (64)));
-            //SimpleLogDumper.dump_bytes(" [zzzzz]", Arrays.copyOfRange(thumbnail, (thumbnail.length - 64), (thumbnail.length)));
-            callback.onCompleted(byteStream.toByteArray(), null);
-            receivedFirstData = false;
-            received_remain_bytes = 0;
-            received_total_bytes = 0;
-            target_image_size = 0;
-
-            byteStream.reset();
-        }
-        catch (Exception e)
-        {
-            e.printStackTrace();
-            {
-                callback.onErrorOccurred(e);
-            }
-        }
-    }
-
-    @Override
-    public void onReceiveProgress(final int currentBytes, final int totalBytes, byte[] rx_body)
-    {
-        // Log.v(TAG, " onReceiveProgress() " + currentBytes + "/" + totalBytes);
-
-        // 受信したデータから、通信のヘッダ部分を削除する
-        cutHeader(rx_body);
-    }
-
-    private void cutHeader(byte[] rx_body)
-    {
-        if (rx_body == null)
-        {
-            return;
-        }
-        int length = rx_body.length;
-        int data_position = 0;
-        if (!receivedFirstData)
-        {
-            // データを最初に読んだとき。ヘッダ部分を読み飛ばす
-            receivedFirstData = true;
-            data_position = (int) rx_body[0] & (0xff);
-            //Log.v(TAG, " FIRST DATA POS. : " + data_position);
-            //SimpleLogDumper.dump_bytes(" [sssss]", Arrays.copyOfRange(rx_body, 0, (64)));
-        }
-        else if (received_remain_bytes > 0)
-        {
-            // データの読み込みが途中だった場合...
-            if (length < received_remain_bytes)
-            {
-                // 全部コピーする、足りないバイト数は残す
-                received_remain_bytes = received_remain_bytes - length;
-                received_total_bytes = received_total_bytes + rx_body.length;
-                byteStream.write(rx_body, 0, rx_body.length);
-                return;
-            }
-            else
-            {
-                byteStream.write(rx_body, data_position, received_remain_bytes);
-                data_position = received_remain_bytes;
-                received_remain_bytes = 0;
-            }
-        }
-
-        while (data_position <= (length - 12)) {
-            int body_size = (rx_body[data_position] & 0xff) + ((rx_body[data_position + 1] & 0xff) << 8) +
-                    ((rx_body[data_position + 2] & 0xff) << 16) + ((rx_body[data_position + 3] & 0xff) << 24);
-            if (body_size <= 12) {
-                Log.v(TAG, " --- BODY SIZE IS SMALL : " + data_position + " (" + body_size + ") [" + received_remain_bytes + "] " + rx_body.length + "  (" + target_image_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(" [zzz] " + data_position + ": ", Arrays.copyOfRange(rx_body, data_position, (data_position + 48)));
-
-            if ((data_position + body_size) > length) {
-                // データがすべてバッファ内になかったときは、バッファすべてコピーして残ったサイズを記憶しておく。
-                int copysize = (length - ((data_position + 12)));
-                byteStream.write(rx_body, (data_position + 12), copysize);
-                received_remain_bytes = body_size - copysize - 12;  // マイナス12は、ヘッダ分
-                received_total_bytes = received_total_bytes + copysize;
-                //Log.v(TAG, " ----- copy : " + (data_position + 12) + " " + copysize + " remain : " + received_remain_bytes + "  body size : " + body_size);
-                break;
-            }
-            try {
-                byteStream.write(rx_body, (data_position + 12), (body_size - 12));
-                data_position = data_position + body_size;
-                received_total_bytes = received_total_bytes + 12;
-                //Log.v(TAG, " --- COPY : " + (data_position + 12) + " " + (body_size - 12) + " remain : " + received_remain_bytes);
-
-            } catch (Exception e) {
-                Log.v(TAG, "  pos : " + data_position + "  size : " + body_size + " length : " + length);
-                e.printStackTrace();
-            }
-        }
-    }
-
-    @Override
-    public boolean isReceiveMulti()
-    {
-        return (true);
-    }
-
-}
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/canon/wrapper/liveview/CanonLiveViewImageReceiver.kt b/app/src/main/java/net/osdn/gokigen/a01d/camera/canon/wrapper/liveview/CanonLiveViewImageReceiver.kt
new file mode 100644 (file)
index 0000000..cf00b22
--- /dev/null
@@ -0,0 +1,168 @@
+package net.osdn.gokigen.a01d.camera.canon.wrapper.liveview
+
+import android.util.Log
+import net.osdn.gokigen.a01d.camera.ptpip.wrapper.command.IPtpIpCommandCallback
+import net.osdn.gokigen.a01d.camera.ptpip.wrapper.liveview.IPtpIpLiveViewImageCallback
+import net.osdn.gokigen.a01d.camera.utils.SimpleLogDumper
+import java.io.ByteArrayOutputStream
+import java.util.*
+
+class CanonLiveViewImageReceiver(val callback: IPtpIpLiveViewImageCallback) : IPtpIpCommandCallback
+{
+    private val isDumpLog = false
+    private val byteStream = ByteArrayOutputStream()
+
+    private var receivedTotalBytes = 0
+    private var receivedRemainBytes = 0
+    private var receivedFirstData = false
+
+    override fun receivedMessage(id: Int, rx_body: ByteArray?)
+    {
+        if (rx_body == null)
+        {
+            Log.v(TAG, " CanonLiveViewReceiver: MSG BODY IS NULL. (ID:$id)")
+            callback.onCompleted(rx_body, null)
+            return
+        }
+        receivedMultiMessage(id, rx_body)
+    }
+
+    override fun onReceiveProgress(currentBytes: Int, totalBytes: Int, rx_body: ByteArray?)
+    {
+        if (rx_body == null)
+        {
+            Log.v(TAG, " CanonLiveViewReceiver: MSG BODY is NULL. ($currentBytes/$totalBytes)")
+            callback.onCompleted(rx_body, null)
+            return
+        }
+        if (isDumpLog)
+        {
+            Log.v(TAG, " CanonLiveViewReceiver::onReceiveProgress() $currentBytes/$totalBytes [size: ${rx_body.size}]")
+        }
+        parseReceivedBody(rx_body)
+    }
+
+
+    private fun parseReceivedBody(rx_body: ByteArray)
+    {
+        try
+        {
+            val length = rx_body.size
+            var dataPosition = 0
+            if (!receivedFirstData)
+            {
+                // データを最初に読んだとき。ヘッダ部分を読み飛ばす
+                receivedFirstData = true
+                dataPosition = rx_body[0].toUByte().toInt()
+                if (isDumpLog)
+                {
+                    Log.v(TAG, " FIRST DATA POS. : $dataPosition len: $length ")
+                    SimpleLogDumper.dump_bytes(" [1stData]", rx_body.copyOfRange(0, (32)))
+                }
+            }
+            else
+            {
+                // 2回目以降の受信データ
+                if (receivedRemainBytes > 0)
+                {
+                    // データの読み込みが途中だった場合...
+                    if (length < receivedRemainBytes)
+                    {
+                        // 全部コピーする、足りないバイト数は残す
+                        receivedRemainBytes -= length
+                        receivedTotalBytes += rx_body.size
+                        byteStream.write(rx_body, 0, rx_body.size)
+                        return
+                    }
+                    else
+                    {
+                        byteStream.write(rx_body, dataPosition, receivedRemainBytes)
+                        dataPosition = receivedRemainBytes
+                        receivedRemainBytes = 0
+                    }
+                }
+            }
+            while (dataPosition <= length - 12)
+            {
+                val body_size = (rx_body[dataPosition].toUByte()).toInt() + ((rx_body[dataPosition + 1].toUByte()).toInt() * 256) + ((rx_body[dataPosition + 2].toUByte()).toInt() * 256 * 256) + ((rx_body[dataPosition + 3].toUByte()).toInt() * 256 * 256 * 256)
+                //Log.v(TAG, " <> body_size : ${body_size} [$dataPosition] ($length)  aa: ${rx_body[dataPosition].toUByte().toInt()}  ${rx_body[dataPosition + 1].toUByte().toInt()} + ${rx_body[dataPosition + 2].toUByte().toInt()}")
+                if (body_size <= 12)
+                {
+                    Log.v(TAG, " ----- BODY SIZE IS SMALL : " + dataPosition + " (" + body_size + ") [" + receivedRemainBytes + "] " + rx_body.size + " ")
+                    break
+                }
+
+                //Log.v(TAG, " RX DATA : " + dataPosition + " (" + body_size + ") [" + receivedRemainBytes + "] (" + receivedTotalBytes + ")");
+                if (dataPosition + body_size > length)
+                {
+                    // データがすべてバッファ内になかったときは、バッファすべてコピーして残ったサイズを記憶しておく。
+                    val copysize = length - (dataPosition + 12)
+                    byteStream.write(rx_body, dataPosition + 12, copysize)
+                    receivedRemainBytes = body_size - copysize - 12 // マイナス12は、ヘッダ分
+                    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, body_size - 12)
+                    dataPosition += body_size
+                    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 : $body_size length : $length")
+                    e.printStackTrace()
+                }
+            }
+        }
+        catch (e : Exception)
+        {
+            e.printStackTrace()
+        }
+    }
+
+
+    private fun receivedMultiMessage(id: Int, rx_body: ByteArray)
+    {
+        try
+        {
+            byteStream.write(rx_body, 0, rx_body.size)
+            if (isDumpLog)
+            {
+                val thumbNail = byteStream.toByteArray()
+                var dumpLength = thumbNail.size
+                if (dumpLength > 256)
+                {
+                    dumpLength = 256
+                }
+                SimpleLogDumper.dump_bytes(" [--ID:$id(>)--]", Arrays.copyOfRange(thumbNail, 0, dumpLength))
+                SimpleLogDumper.dump_bytes(" [-ID:$id(<)-]", Arrays.copyOfRange(thumbNail, thumbNail.size - dumpLength, thumbNail.size))
+            }
+            callback.onCompleted(byteStream.toByteArray(), null)
+            receivedFirstData = false
+            receivedRemainBytes = 0
+            receivedTotalBytes = 0
+            byteStream.reset()
+        }
+        catch (e: Exception)
+        {
+            e.printStackTrace()
+            callback.onErrorOccurred(e)
+        }
+    }
+
+
+
+    override fun isReceiveMulti(): Boolean
+    {
+        return (true)
+    }
+
+    companion object
+    {
+        private val TAG = "CanonLiveViewReceiver"
+    }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/net/osdn/gokigen/a01d/camera/canon/wrapper/liveview/CanonLiveViewImageReceiverPrev.java b/app/src/main/java/net/osdn/gokigen/a01d/camera/canon/wrapper/liveview/CanonLiveViewImageReceiverPrev.java
new file mode 100644 (file)
index 0000000..8b4218e
--- /dev/null
@@ -0,0 +1,166 @@
+package net.osdn.gokigen.a01d.camera.canon.wrapper.liveview;
+
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import net.osdn.gokigen.a01d.camera.ptpip.wrapper.command.IPtpIpCommandCallback;
+import net.osdn.gokigen.a01d.camera.ptpip.wrapper.liveview.IPtpIpLiveViewImageCallback;
+import net.osdn.gokigen.a01d.camera.utils.SimpleLogDumper;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Arrays;
+
+public class CanonLiveViewImageReceiverPrev implements IPtpIpCommandCallback
+{
+    private final String TAG = toString();
+
+    private final IPtpIpLiveViewImageCallback callback;
+
+    private int received_total_bytes = 0;
+    private int received_remain_bytes = 0;
+
+    private int target_image_size = 0;
+    private boolean receivedFirstData = false;
+    private final ByteArrayOutputStream byteStream;
+
+    CanonLiveViewImageReceiverPrev(@NonNull IPtpIpLiveViewImageCallback callback)
+    {
+        this.callback = callback;
+        byteStream = new ByteArrayOutputStream();
+    }
+
+    @Override
+    public void receivedMessage(int id, byte[] rx_body)
+    {
+        try
+        {
+            // end of receive sequence.
+            if (rx_body != null)
+            {
+                byteStream.write(rx_body, 0, rx_body.length);
+            }
+            byte [] thumbnail = byteStream.toByteArray();
+            Log.v(TAG, " TransferComplete() RECEIVED  : " + id + " size : " + target_image_size + " (" + thumbnail.length + ")");
+            int dump_length = 96;
+            if (thumbnail.length > dump_length)
+            {
+                SimpleLogDumper.dump_bytes(" [xxx(head)xxx]", Arrays.copyOfRange(thumbnail, 0, (dump_length)));
+                SimpleLogDumper.dump_bytes(" [zz(bottom)zz]", Arrays.copyOfRange(thumbnail, (thumbnail.length - dump_length), (thumbnail.length)));
+            }
+            callback.onCompleted(byteStream.toByteArray(), null);
+            receivedFirstData = false;
+            received_remain_bytes = 0;
+            received_total_bytes = 0;
+            target_image_size = 0;
+            byteStream.reset();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+            {
+                callback.onErrorOccurred(e);
+            }
+        }
+    }
+
+    @Override
+    public void onReceiveProgress(final int currentBytes, final int totalBytes, byte[] rx_body)
+    {
+        Log.v(TAG, " onReceiveProgress() " + currentBytes + "/" + totalBytes);
+
+        // 受信したデータから、通信のヘッダ部分を削除する
+        cutHeader(rx_body);
+    }
+
+    private void cutHeader(byte[] rx_body)
+    {
+        if (rx_body == null)
+        {
+            return;
+        }
+        try
+        {
+            int length = rx_body.length;
+            int data_position = 0;
+            if (!receivedFirstData)
+            {
+                // データを最初に読んだとき。ヘッダ部分を読み飛ばす
+                receivedFirstData = true;
+                data_position = (int) rx_body[0] & (0xff);
+                Log.v(TAG, " FIRST DATA POS. : " + data_position + " [size : " + rx_body.length + "]");
+                //SimpleLogDumper.dump_bytes(" [sssss]", Arrays.copyOfRange(rx_body, 0, (96)));
+            }
+            else if (received_remain_bytes > 0)
+            {
+                // データの読み込みが途中だった場合...
+                if (length < received_remain_bytes)
+                {
+                    // 全部コピーする、足りないバイト数は残す
+                    received_remain_bytes = received_remain_bytes - length;
+                    received_total_bytes = received_total_bytes + rx_body.length;
+                    byteStream.write(rx_body, 0, rx_body.length);
+                    return;
+                }
+                else
+                {
+                    byteStream.write(rx_body, data_position, received_remain_bytes);
+                    data_position = received_remain_bytes;
+                    received_remain_bytes = 0;
+                }
+            }
+
+            while (data_position <= (length - 12))
+            {
+                int body_size = (rx_body[data_position] & 0xff) + ((rx_body[data_position + 1] & 0xff) << 8) +
+                        ((rx_body[data_position + 2] & 0xff) << 16) + ((rx_body[data_position + 3] & 0xff) << 24);
+                if (body_size <= 12)
+                {
+                    Log.v(TAG, " --- BODY SIZE IS SMALL : " + data_position + " (" + body_size + ") [" + received_remain_bytes + "] " + rx_body.length + "  (" + target_image_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(" [zzz] " + data_position + ": ", Arrays.copyOfRange(rx_body, data_position, (data_position + 48)));
+
+                if ((data_position + body_size) > length)
+                {
+                    // データがすべてバッファ内になかったときは、バッファすべてコピーして残ったサイズを記憶しておく。
+                    int copysize = (length - ((data_position + 12)));
+                    byteStream.write(rx_body, (data_position + 12), copysize);
+                    received_remain_bytes = body_size - copysize - 12;  // マイナス12は、ヘッダ分
+                    received_total_bytes = received_total_bytes + copysize;
+                    Log.v(TAG, " ----- copy : " + (data_position + 12) + " " + copysize + " remain : " + received_remain_bytes + "  body size : " + body_size);
+                    break;
+                }
+                try
+                {
+                    byteStream.write(rx_body, (data_position + 12), (body_size - 12));
+                    data_position = data_position + body_size;
+                    received_total_bytes = received_total_bytes + 12;
+                    Log.v(TAG, " --- COPY : " + (data_position + 12) + " " + (body_size - 12) + " remain : " + received_remain_bytes);
+
+                }
+                catch (Exception e)
+                {
+                    Log.v(TAG, "  pos : " + data_position + "  size : " + body_size + " length : " + length);
+                    e.printStackTrace();
+                }
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+
+    }
+
+    @Override
+    public boolean isReceiveMulti()
+    {
+        return (true);
+    }
+
+}
index 866c086..68ac893 100644 (file)
@@ -29,6 +29,7 @@ public interface IPtpIpMessages
     int SEQ_GET_DEVICE_PROP1 = 24;
     int SEQ_GET_DEVICE_PROP2 = 25;
     int SEQ_GET_CAMERASTATUS = 26;
+    int SEQ_SET_REMOTE_SHOOTING_MODE = 27;
 
     int GET_STORAGE_ID = 101;
     int GET_STORAGE_INFO = 102;
index 7cbe43a..c4de295 100644 (file)
@@ -198,7 +198,11 @@ class PtpIpCommandPublisher(private val ipAddress : String, private val portNumb
                 isHold = true
                 holdId = command.holdId
             }
-            Log.v(TAG, "Enqueue [ID: " + command.getId() + "] size: " + commandQueue.size);
+            if (commandQueue.size > 1)
+            {
+                // たまっているときだけログを吐く
+                Log.v(TAG, "Enqueue [ID: " + command.getId() + "] size: " + commandQueue.size)
+            }
             return (commandQueue.offer(command))
         }
         catch (e: Exception)
index 1ea8c2d..d20d2dd 100644 (file)
@@ -120,6 +120,9 @@ public interface IPreferencePropertyAccessor
     String CANON_HOST_IP = "canon_host_ip";
     String CANON_HOST_IP_DEFAULT_VALUE = "192.168.0.1";
 
+    String CANON_LIVEVIEW_WAIT = "canon_liveview_wait";
+    String CANON_LIVEVIEW_WAIT_DEFAULT_VALUE = "25";
+
  /*
     int CHOICE_SPLASH_SCREEN = 10;
 
index ec402d8..90d93a8 100644 (file)
@@ -136,6 +136,9 @@ public class CanonPreferenceFragment extends PreferenceFragmentCompat implements
             if (!items.containsKey(IPreferencePropertyAccessor.CANON_HOST_IP)) {
                 editor.putString(IPreferencePropertyAccessor.CANON_HOST_IP, IPreferencePropertyAccessor.CANON_HOST_IP_DEFAULT_VALUE);
             }
+            if (!items.containsKey(IPreferencePropertyAccessor.CANON_LIVEVIEW_WAIT)) {
+                editor.putString(IPreferencePropertyAccessor.CANON_LIVEVIEW_WAIT, IPreferencePropertyAccessor.CANON_LIVEVIEW_WAIT_DEFAULT_VALUE);
+            }
             editor.apply();
         }
         catch (Exception e)
@@ -304,6 +307,7 @@ public class CanonPreferenceFragment extends PreferenceFragmentCompat implements
      * @param key          Preference(データ)のキー
      * @param defaultValue Preferenceのデフォルト値
      */
+    @SuppressWarnings("SameParameterValue")
     private void setBooleanPreference(String pref_key, String key, boolean defaultValue)
     {
         try
index ee59d57..fd49387 100644 (file)
     <string name="pref_canon_host_ip">カメラIPアドレス</string>
     <string name="pref_summary_canon_host_ip">通常、変更は不要です (初期値:192.168.0.1)</string>
 
+    <string name="pref_canon_liveview_wait">LV画像受信待ち間隔(default: 25)</string>
+    <string name="pref_summary_canon_liveview_wait">ライブビュー画像受信間隔を指定します</string>
+
 </resources>
index f5b5c0c..03c2cfe 100644 (file)
     <string name="pref_canon_host_ip">Camera IP Address</string>
     <string name="pref_summary_canon_host_ip">default: 192.168.0.1 </string>
 
+    <string name="pref_canon_liveview_wait">Liveview receive wait (default: 25)</string>
+    <string name="pref_summary_canon_liveview_wait"> </string>
+
 </resources>
index 24fc2d4..5ef8b9e 100644 (file)
             android:title="@string/pref_canon_host_ip"
             android:defaultValue="192.168.0.1"
             android:summary="@string/pref_summary_canon_host_ip" />
+
+        <EditTextPreference
+            android:key="canon_liveview_wait"
+            android:title="@string/pref_canon_liveview_wait"
+            android:defaultValue="25"
+            android:summary="@string/pref_summary_canon_liveview_wait" />
+
 <!--
         <CheckBoxPreference
             android:key="capture_both_camera_and_live_view"