1 package net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.playback;
3 import android.app.Activity;
4 import android.util.Log;
6 import androidx.annotation.NonNull;
8 import net.osdn.gokigen.pkremote.camera.interfaces.playback.IDownloadContentCallback;
9 import net.osdn.gokigen.pkremote.camera.interfaces.playback.IProgressEvent;
10 import net.osdn.gokigen.pkremote.camera.utils.SimpleLogDumper;
11 import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.IPtpIpCommandCallback;
12 import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.IPtpIpCommandPublisher;
13 import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.messages.PtpIpCommandGeneric;
15 import java.io.ByteArrayOutputStream;
16 import java.util.Arrays;
18 public class PtpIpFullImageReceiver implements IPtpIpCommandCallback
20 private static final String TAG = PtpIpFullImageReceiver.class.getSimpleName();
22 private final Activity activity;
23 private final IPtpIpCommandPublisher publisher;
24 private IDownloadContentCallback callback = null;
25 private int objectId = 0;
27 private int received_total_bytes = 0;
28 private int received_remain_bytes = 0;
30 PtpIpFullImageReceiver(@NonNull Activity activity, @NonNull IPtpIpCommandPublisher publisher)
32 this.activity = activity;
34 this.publisher = publisher;
37 void issueCommand(int objectId, int imageSize, IDownloadContentCallback callback)
39 if (this.objectId != 0)
42 Log.v(TAG, " COMMAND IS ALREADY ISSUED. : " + objectId);
45 this.callback = callback;
46 Log.v(TAG, " GetPartialObject : " + objectId + " (size:" + imageSize + ")");
47 publisher.enqueueCommand(new PtpIpCommandGeneric(this, (objectId + 1), true, objectId, 0x9107, 12, 0x01, 0x00, imageSize)); // 0x9107 : GetPartialObject
48 this.objectId = objectId;
52 public void receivedMessage(int id, byte[] rx_body)
56 if (id == objectId + 1)
58 getPartialObjectEnd();
60 else if (id == objectId + 2)
62 Log.v(TAG, " RECEIVED : " + id);
64 // end of receive sequence.
65 callback.onCompleted();
72 Log.v(TAG, " RECEIVED UNKNOWN ID : " + id);
79 callback.onErrorOccurred(e);
85 public void onReceiveProgress(final int currentBytes, final int totalBytes, byte[] rx_body)
87 byte[] body = cutHeader(rx_body);
88 int length = (body == null) ? 0 : body.length;
89 Log.v(TAG, " onReceiveProgress() " + currentBytes + "/" + totalBytes + " (" + length + " bytes.)");
90 callback.onProgress(body, length, new IProgressEvent() {
92 public float getProgress() {
93 return ((float) currentBytes / (float) totalBytes);
97 public boolean isCancellable() {
102 public void requestCancellation() {
108 private byte[] cutHeader(byte[] rx_body)
114 int length = rx_body.length;
115 int data_position = 0;
116 ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
117 if (received_total_bytes == 0)
119 // データを最初に読んだとき。ヘッダ部分を読み飛ばす
120 data_position = (int) rx_body[0] & (0xff);
122 else if (received_remain_bytes > 0)
125 Log.v(TAG, " >>> [ remain_bytes : " + received_remain_bytes + "] ( length : " + length + ") " + data_position);
126 SimpleLogDumper.dump_bytes("[zzz]", Arrays.copyOfRange(rx_body, data_position, (data_position + 160)));
128 // データの読み込みが途中だった場合...
129 if (length < received_remain_bytes)
131 // 全部コピーする、足りないバイト数は残す
132 received_remain_bytes = received_remain_bytes - length;
133 received_total_bytes = received_total_bytes + rx_body.length;
138 byteStream.write(rx_body, data_position, received_remain_bytes);
139 data_position = received_remain_bytes;
140 received_remain_bytes = 0;
144 while (data_position <= (length - 12))
146 int body_size = (rx_body[data_position] & 0xff) + ((rx_body[data_position + 1] & 0xff) << 8) +
147 ((rx_body[data_position + 2] & 0xff) << 16) + ((rx_body[data_position + 3] & 0xff) << 24);
150 Log.v(TAG, " BODY SIZE IS SMALL : " + data_position + " (" + body_size + ") [" + received_remain_bytes + "] " + rx_body.length + " ");
152 int startpos = (data_position > 48) ? (data_position - 48) : 0;
153 SimpleLogDumper.dump_bytes("[xxx]", Arrays.copyOfRange(rx_body, startpos, (data_position + 48)));
158 Log.v(TAG, " RX DATA : " + data_position + " (" + body_size + ") [" + received_remain_bytes + "] (" + received_total_bytes + ")");
159 SimpleLogDumper.dump_bytes("[yyy] " + data_position + ": ", Arrays.copyOfRange(rx_body, data_position, (data_position + 64)));
162 if ((data_position + body_size) > length)
164 // データがすべてバッファ内になかったときは、バッファすべてコピーして残ったサイズを記憶しておく。
165 int copysize = (length - ((data_position + 12)));
166 byteStream.write(rx_body, (data_position + 12), copysize);
167 received_remain_bytes = body_size - copysize - 12; // マイナス12は、ヘッダ分
168 received_total_bytes = received_total_bytes + copysize;
169 Log.v(TAG, " --- copy : " + (data_position + 12) + " " + copysize + " remain : " + received_remain_bytes + " body size : " + body_size);
174 byteStream.write(rx_body, (data_position + 12), (body_size - 12));
175 data_position = data_position + body_size;
176 received_total_bytes = received_total_bytes + 12;
177 Log.v(TAG, " --- COPY : " + (data_position + 12) + " " + (body_size - 12) + " remain : " + received_remain_bytes);
182 Log.v(TAG, " pos : " + data_position + " size : " + body_size + " length : " + length);
186 return (byteStream.toByteArray());
190 public boolean isReceiveMulti()
195 private void getPartialObjectEnd()
199 Log.v(TAG, " getPartialObjectEnd(), id : " + objectId);
200 publisher.enqueueCommand(new PtpIpCommandGeneric(this, (objectId + 2), true, objectId, 0x9117, 4,0x01)); // 0x9117 : TransferComplete