OSDN Git Service

fd9708735de647270438d90ff07420e1ffbdd60a
[gokigen/PKRemote.git] / app / src / main / java / net / osdn / gokigen / pkremote / camera / vendor / ptpip / wrapper / playback / PtpIpSmallImageReceiver.java
1 package net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.playback;
2
3 import android.app.Activity;
4 import android.util.Log;
5
6 import androidx.annotation.NonNull;
7 import androidx.annotation.Nullable;
8
9 import net.osdn.gokigen.pkremote.camera.interfaces.playback.IDownloadContentCallback;
10 import net.osdn.gokigen.pkremote.camera.interfaces.playback.IProgressEvent;
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.PtpIpCommandCanonGetPartialObject;
14 import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.messages.PtpIpCommandGeneric;
15 import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.messages.specific.CanonRequestInnerDevelopEnd;
16 import net.osdn.gokigen.pkremote.camera.vendor.ptpip.wrapper.command.messages.specific.CanonRequestInnerDevelopStart;
17
18 import java.io.ByteArrayOutputStream;
19
20
21 public class PtpIpSmallImageReceiver implements IPtpIpCommandCallback
22 {
23     private static final String TAG = PtpIpSmallImageReceiver.class.getSimpleName();
24
25     private final Activity activity;
26     private final IPtpIpCommandPublisher publisher;
27     private final IPtpIpCommandCallback mine;
28     private IDownloadContentCallback callback = null;
29     private int objectId = 0;
30     private boolean isReceiveMulti = false;
31     private boolean receivedFirstData = false;
32
33     private int received_total_bytes = 0;
34     private int received_remain_bytes = 0;
35
36     PtpIpSmallImageReceiver(@NonNull Activity activity, @NonNull IPtpIpCommandPublisher publisher)
37     {
38         this.activity = activity;
39         this.publisher = publisher;
40         this.mine = this;
41     }
42
43     void issueCommand(final int objectId, IDownloadContentCallback callback)
44     {
45         if (this.objectId != 0)
46         {
47             // already issued
48             Log.v(TAG, " COMMAND IS ALREADY ISSUED. : " + objectId);
49             return;
50         }
51         this.callback = callback;
52         this.objectId = objectId;
53         publisher.enqueueCommand(new CanonRequestInnerDevelopStart(new IPtpIpCommandCallback() {
54             @Override
55             public void receivedMessage(int id, byte[] rx_body) {
56                 Log.v(TAG, " getRequestStatusEvent  : " + objectId + " " + ((rx_body != null) ? rx_body.length : 0));
57                 publisher.enqueueCommand(new PtpIpCommandGeneric(mine,  (objectId + 5), false, objectId, 0x9116));
58             }
59
60             @Override
61             public void onReceiveProgress(int currentBytes, int totalBytes, byte[] rx_body) {
62             }
63
64             @Override
65             public boolean isReceiveMulti() {
66                 return (false);
67             }
68         }, objectId, false, objectId, objectId));   // 0x9141 : RequestInnerDevelopStart
69     }
70
71     @Override
72     public void receivedMessage(int id, byte[] rx_body)
73     {
74         try
75         {
76             if (id == objectId + 1)
77             {
78                 sendTransferComplete(rx_body);
79             }
80             else if (id == objectId + 2)
81             {
82                 Log.v(TAG, " requestInnerDevelopEnd() : " + objectId);
83                 publisher.enqueueCommand(new CanonRequestInnerDevelopEnd(this, (objectId + 3), false, objectId));  // 0x9143 : RequestInnerDevelopEnd
84             }
85             else if (id == objectId + 3)
86             {
87                 //Log.v(TAG, "  --- COMMAND RESET : " + objectId + " --- ");
88
89                 // リセットコマンドを送ってみる
90                 publisher.enqueueCommand(new PtpIpCommandGeneric(this, (objectId + 4), false, objectId, 0x902f));
91             }
92             else if (id == objectId + 4)
93             {
94                 // 画像取得終了
95                 Log.v(TAG, " ----- SMALL IMAGE RECEIVE SEQUENCE FINISHED  : " + objectId);
96                 callback.onCompleted();
97                 this.objectId = 0;
98                 this.callback = null;
99                 this.received_total_bytes = 0;
100                 this.received_remain_bytes = 0;
101                 this.receivedFirstData = false;
102                 System.gc();
103             }
104             else if (id == objectId + 5)
105             {
106                 requestGetPartialObject(rx_body);
107             }
108             else
109             {
110                 Log.v(TAG, " RECEIVED UNKNOWN ID : " + id);
111             }
112         }
113         catch (Exception e)
114         {
115             e.printStackTrace();
116             {
117                 callback.onErrorOccurred(e);
118             }
119         }
120     }
121
122     @Override
123     public void onReceiveProgress(final int currentBytes, final int totalBytes, byte[] rx_body)
124     {
125         byte[] body = cutHeader(rx_body);
126         int length = (body == null) ? 0 : body.length;
127         Log.v(TAG, " onReceiveProgress() " + currentBytes + "/" + totalBytes + " (" + length + " bytes.)");
128         callback.onProgress(body, length, new IProgressEvent() {
129             @Override
130             public float getProgress() {
131                 return ((float) currentBytes / (float) totalBytes);
132             }
133
134             @Override
135             public boolean isCancellable() {
136                 return (false);
137             }
138
139             @Override
140             public void requestCancellation() {
141
142             }
143         });
144     }
145
146     private byte[] cutHeader(byte[] rx_body)
147     {
148         if (rx_body == null)
149         {
150             return (null);
151         }
152         int length = rx_body.length;
153         int data_position = 0;
154         ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
155         if (!receivedFirstData)
156         {
157             // 初回データを読み込んだ
158             receivedFirstData = true;
159
160             // データを最初に読んだとき。ヘッダ部分を読み飛ばす
161             data_position = (int) rx_body[0] & (0xff);
162         }
163         else if (received_remain_bytes > 0)
164         {
165             //Log.v(TAG, "  >>> [ remain_bytes : " + received_remain_bytes + "] ( length : " + length + ") " + data_position);
166             //SimpleLogDumper.dump_bytes("[zzz]", Arrays.copyOfRange(rx_body, data_position, (data_position + 160)));
167
168             // データの読み込みが途中だった場合...
169             if (length < received_remain_bytes)
170             {
171                 // 全部コピーする、足りないバイト数は残す
172                 received_remain_bytes = received_remain_bytes - length;
173                 received_total_bytes = received_total_bytes + rx_body.length;
174                 return (rx_body);
175             }
176             else
177             {
178                 byteStream.write(rx_body, data_position, received_remain_bytes);
179                 data_position = received_remain_bytes;
180                 received_remain_bytes = 0;
181             }
182         }
183
184         while (data_position <= (length - 12))
185         {
186             int body_size =  (rx_body[data_position] & 0xff) + ((rx_body[data_position + 1]  & 0xff) << 8) +
187                             ((rx_body[data_position + 2] & 0xff) << 16) + ((rx_body[data_position + 3] & 0xff) << 24);
188             if (body_size <= 12)
189             {
190                 Log.v(TAG, "  BODY SIZE IS SMALL : " + data_position + " (" + body_size + ") [" + received_remain_bytes + "] " + rx_body.length + "  ");
191                 //int startpos = (data_position > 48) ? (data_position - 48) : 0;
192                 //SimpleLogDumper.dump_bytes("[xxx]", Arrays.copyOfRange(rx_body, startpos, (data_position + 48)));
193                 break;
194             }
195
196             // Log.v(TAG, " RX DATA : " + data_position + " (" + body_size + ") [" + received_remain_bytes + "] (" + received_total_bytes + ")");
197             //SimpleLogDumper.dump_bytes("[yyy] " + data_position + ": ", Arrays.copyOfRange(rx_body, data_position, (data_position + 64)));
198             if ((data_position + body_size) > length)
199             {
200                 // データがすべてバッファ内になかったときは、バッファすべてコピーして残ったサイズを記憶しておく。
201                 int copysize = (length - ((data_position + 12)));
202                 byteStream.write(rx_body, (data_position + 12), copysize);
203                 received_remain_bytes = body_size - copysize - 12;  // マイナス12は、ヘッダ分
204                 received_total_bytes = received_total_bytes + copysize;
205                // Log.v(TAG, " --- copy : " + (data_position + 12) + " " + copysize + " remain : " + received_remain_bytes + "  body size : " + body_size);
206                 break;
207             }
208             try
209             {
210                 byteStream.write(rx_body, (data_position + 12), (body_size - 12));
211                 data_position = data_position + body_size;
212                 received_total_bytes = received_total_bytes + 12;
213                 //Log.v(TAG, " --- COPY : " + (data_position + 12) + " " + (body_size - 12) + " remain : " + received_remain_bytes);
214             }
215             catch (Exception e)
216             {
217                 Log.v(TAG, "  pos : " + data_position + "  size : " + body_size + " length : " + length);
218                 e.printStackTrace();
219             }
220         }
221         return (byteStream.toByteArray());
222     }
223
224     @Override
225     public boolean isReceiveMulti()
226     {
227         return (isReceiveMulti);
228     }
229
230     private void requestGetPartialObject(@Nullable byte[] rx_body)
231     {
232         Log.v(TAG, " requestGetPartialObject() : " + objectId);
233         isReceiveMulti = true;
234         receivedFirstData = false;
235
236         // 0x9107 : GetPartialObject  (元は 0x00020000)
237         int pictureLength;
238         if ((rx_body != null)&&(rx_body.length > 52))
239         {
240             int dataIndex = 48;
241             pictureLength = (rx_body[dataIndex] & 0xff);
242             pictureLength = pictureLength + ((rx_body[dataIndex + 1]  & 0xff) << 8);
243             pictureLength = pictureLength + ((rx_body[dataIndex + 2] & 0xff) << 16);
244             pictureLength = pictureLength + ((rx_body[dataIndex + 3] & 0xff) << 24);
245         }
246         else
247         {
248             pictureLength = 0x020000;
249         }
250         publisher.enqueueCommand(new PtpIpCommandCanonGetPartialObject(this, (objectId + 1), false, objectId, 0x01, 0x00, pictureLength, pictureLength));
251     }
252
253     private void sendTransferComplete(byte[] rx_body)
254     {
255         Log.v(TAG, " sendTransferComplete(), id : " + objectId + " size: " + ((rx_body != null) ? rx_body.length : 0));
256         publisher.enqueueCommand(new PtpIpCommandGeneric(this,  (objectId + 2), false, objectId, 0x9117, 4,0x01));  // 0x9117 : TransferComplete
257         isReceiveMulti = false;
258     }
259 }