OSDN Git Service

FujiXのLiveView取得部分をkotlin化。
[gokigen/A01d.git] / app / src / main / java / net / osdn / gokigen / a01d / camera / fujix / wrapper / liveview / FujiXLiveViewControl.kt
1 package net.osdn.gokigen.a01d.camera.fujix.wrapper.liveview
2
3 import android.app.Activity
4 import android.util.Log
5 import androidx.preference.PreferenceManager
6 import net.osdn.gokigen.a01d.camera.ILiveViewControl
7 import net.osdn.gokigen.a01d.camera.fujix.wrapper.command.IFujiXCommunication
8 import net.osdn.gokigen.a01d.camera.utils.SimpleLogDumper
9 import net.osdn.gokigen.a01d.liveview.liveviewlistener.CameraLiveViewListenerImpl
10 import net.osdn.gokigen.a01d.liveview.liveviewlistener.ILiveViewListener
11 import net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor
12 import java.net.Socket
13 import java.util.*
14
15 class FujiXLiveViewControl(activity: Activity, private val ipAddress: String, private val portNumber: Int) : ILiveViewControl, IFujiXCommunication
16 {
17     private val TAG = toString()
18     private val liveViewListener = CameraLiveViewListenerImpl()
19     private var waitMs = 0
20     private var isStart = false
21     private val logcat = false
22     private val preferences = PreferenceManager.getDefaultSharedPreferences(activity)
23
24     init
25     {
26         try
27         {
28             val waitMsStr = preferences.getString(IPreferencePropertyAccessor.FUJIX_LIVEVIEW_WAIT, IPreferencePropertyAccessor.FUJIX_LIVEVIEW_WAIT_DEFAULT_VALUE)
29             logcat(" waitMS : $waitMsStr")
30             if (waitMsStr != null)
31             {
32                 val wait = waitMsStr.toInt()
33                 if (wait in 20 .. 800)
34                 {
35                     waitMs = wait
36                 }
37             }
38         }
39         catch (e: Exception)
40         {
41             e.printStackTrace()
42             waitMs = 100
43         }
44         Log.v(TAG, " LOOP WAIT : $waitMs ms")
45     }
46
47     override fun startLiveView()
48     {
49         if (isStart)
50         {
51             // すでに受信スレッド動作中なので抜ける
52             Log.v(TAG, " LiveView IS ALREADY STARTED")
53             return
54         }
55         isStart = true
56         try
57         {
58             Thread {
59                 try
60                 {
61                     startReceive(Socket(ipAddress, portNumber))
62                 }
63                 catch (e: Exception)
64                 {
65                     Log.v(TAG, " IP : $ipAddress port : $portNumber")
66                     e.printStackTrace()
67                 }
68             }.start()
69         }
70         catch (e : Exception)
71         {
72             e.printStackTrace()
73         }
74     }
75
76     override fun stopLiveView()
77     {
78         isStart = false
79     }
80
81     override fun updateDigitalZoom()
82     {
83
84     }
85
86     override fun updateMagnifyingLiveViewScale(isChangeScale: Boolean)
87     {
88
89     }
90
91     override fun getMagnifyingLiveViewScale(): Float
92     {
93         return (1.0f)
94     }
95
96     override fun changeLiveViewSize(size: String)
97     {
98
99     }
100
101     override fun getDigitalZoomScale(): Float
102     {
103         return (1.0f)
104     }
105
106     fun getLiveViewListener(): ILiveViewListener
107     {
108         return (liveViewListener)
109     }
110
111     override fun connect(): Boolean
112     {
113         return (true)
114     }
115
116     override fun disconnect()
117     {
118         isStart = false
119     }
120
121     private fun logcat(message: String)
122     {
123         if (logcat)
124         {
125             Log.v(TAG, message)
126         }
127     }
128
129     private fun dump_bytes(header : String, byteArray: ByteArray, size : Int = 24)
130     {
131         if (logcat)
132         {
133             SimpleLogDumper.dump_bytes(header, byteArray.copyOf(size))
134         }
135     }
136
137     private fun startReceive(socket: Socket)
138     {
139         var errorCount = 0
140         val isr = socket.getInputStream()
141         val byteArray = ByteArray(BUFFER_SIZE + 32)
142
143         while (isStart)
144         {
145             try
146             {
147                 var findJpeg = false
148                 var length_bytes: Int
149                 var read_bytes = isr.read(byteArray, 0, BUFFER_SIZE)
150                 if (read_bytes > DATA_HEADER_OFFSET)
151                 {
152                     // メッセージボディの先頭にあるメッセージ長分は読み込む
153                     length_bytes = (byteArray[3].toInt() and 0xff shl 24) + (byteArray[2].toInt() and 0xff shl 16) + (byteArray[1].toInt() and 0xff shl 8) + (byteArray[0].toInt() and 0xff)
154                     if (byteArray[18] == 0xff.toByte() && byteArray[19] == 0xd8.toByte())
155                     {
156                         findJpeg = true
157                         while (read_bytes < length_bytes && read_bytes < BUFFER_SIZE && length_bytes <= BUFFER_SIZE)
158                         {
159                             val append_bytes = isr.read(byteArray, read_bytes, length_bytes - read_bytes)
160                             logcat("READ AGAIN : $append_bytes [$read_bytes]")
161                             if (append_bytes < 0)
162                             {
163                                 break
164                             }
165                             read_bytes = read_bytes + append_bytes
166                         }
167                         logcat("READ BYTES : " + read_bytes + "  (" + length_bytes + " bytes, " + waitMs + "ms)")
168                     }
169                     else
170                     {
171                         // ウェイトを短めに入れてマーカーを拾うまで待つ
172                         Thread.sleep(waitMs / 4.toLong())
173                         logcat(" --- wait LiveView ---")
174                         continue
175                     }
176                 }
177
178                 // 先頭データをダンプする
179                 dump_bytes("[LV]", byteArray)
180                 if (findJpeg)
181                 {
182                     liveViewListener.onUpdateLiveView(Arrays.copyOfRange(byteArray, DATA_HEADER_OFFSET, read_bytes - DATA_HEADER_OFFSET), null)
183                     errorCount = 0
184                 }
185                 Thread.sleep(waitMs.toLong())
186             }
187             catch (e: Exception)
188             {
189                 e.printStackTrace()
190                 errorCount++
191             }
192
193             if (errorCount > ERROR_LIMIT)
194             {
195                 // エラーが連続でたくさん出たらループをストップ(ライブビューを停止)させる
196                 isStart = false
197             }
198         }
199
200         try
201         {
202             isr.close()
203             socket.close()
204         }
205         catch (e: Exception)
206         {
207             e.printStackTrace()
208         }
209     }
210
211     private fun startReceiveAlter(socket: Socket)
212     {
213         var errorCount = 0
214         val isr = socket.getInputStream()
215         val byteArray = ByteArray(BUFFER_SIZE + 32)
216
217         while (isStart)
218         {
219             try
220             {
221                 var findJpeg = false
222                 var length_bytes: Int
223                 var read_bytes = isr.read(byteArray, 0, BUFFER_SIZE)
224
225                 // 先頭データ(48バイト分)をダンプ
226                 // dump_bytes("[lv]", byteArray, 48)
227                 if (read_bytes > DATA_HEADER_OFFSET)
228                 {
229                     // メッセージボディの先頭にあるメッセージ長分は読み込む
230                     length_bytes = (byteArray[3].toInt() and 0xff shl 24) + (byteArray[2].toInt() and 0xff shl 16) + (byteArray[1].toInt() and 0xff shl 8) + (byteArray[0].toInt() and 0xff)
231                     if (byteArray[18] == 0xff.toByte() && byteArray[19] == 0xd8.toByte())
232                     {
233                         findJpeg = true
234                         while (read_bytes < length_bytes && read_bytes < BUFFER_SIZE && length_bytes <= BUFFER_SIZE)
235                         {
236                             val append_bytes = isr.read(byteArray, read_bytes, length_bytes - read_bytes)
237                             logcat("READ AGAIN : $append_bytes [$read_bytes]")
238                             if (append_bytes < 0)
239                             {
240                                 break
241                             }
242                             read_bytes = read_bytes + append_bytes
243                         }
244                         logcat("READ BYTES : " + read_bytes + "  (" + length_bytes + " bytes, " + waitMs + "ms)")
245                     }
246                     else
247                     {
248                         // ウェイトを短めに入れてマーカーを拾うまで待つ
249                         Thread.sleep(waitMs / 4.toLong())
250                         logcat(" --- wait LiveView ---")
251                         continue
252                     }
253                 }
254
255                 // 先頭データをダンプする
256                 dump_bytes("[LV]", byteArray)
257                 if (findJpeg)
258                 {
259                     liveViewListener.onUpdateLiveView(Arrays.copyOfRange(byteArray, DATA_HEADER_OFFSET, read_bytes - DATA_HEADER_OFFSET), null)
260                     errorCount = 0
261                 }
262                 Thread.sleep(waitMs.toLong())
263             }
264             catch (e: Exception)
265             {
266                 e.printStackTrace()
267                 errorCount++
268             }
269
270             if (errorCount > ERROR_LIMIT)
271             {
272                 // エラーが連続でたくさん出たらループをストップ(ライブビューを停止)させる
273                 isStart = false
274             }
275         }
276
277         try
278         {
279             isr.close()
280             socket.close()
281         }
282         catch (e: Exception)
283         {
284             e.printStackTrace()
285         }
286     }
287
288
289     companion object
290     {
291         private const val DATA_HEADER_OFFSET = 18
292         private const val BUFFER_SIZE = 2048 * 1280
293         private const val ERROR_LIMIT = 30
294     }
295 }