Fujifilm X Series Remote Control for Android (Prototype)
Fujifilm Xシリーズカメラの遠隔操作アプリ for Android (プロトタイプ)
Revision | 31d5b79bc41b732f89f11f9ab2fcd6f5ca6d3d11 (tree) |
---|---|
Zeit | 2019-05-25 00:57:51 |
Autor | MRSa <mrsa@myad...> |
Commiter | MRSa |
ライブビューの受信間隔もパラメータ化。
@@ -23,7 +23,6 @@ import net.osdn.gokigen.cameratest.fuji.statuses.IFujiStatus; | ||
23 | 23 | import net.osdn.gokigen.cameratest.fuji.statuses.IFujiStatusNotify; |
24 | 24 | |
25 | 25 | import androidx.annotation.NonNull; |
26 | -import androidx.preference.EditTextPreference; | |
27 | 26 | import androidx.preference.PreferenceManager; |
28 | 27 | |
29 | 28 | public class CamTest implements View.OnClickListener, View.OnTouchListener, ILiveViewImage, IFujiStatusNotify |
@@ -46,7 +45,7 @@ public class CamTest implements View.OnClickListener, View.OnTouchListener, ILiv | ||
46 | 45 | public CamTest(@NonNull Activity activity) |
47 | 46 | { |
48 | 47 | this.activity = activity; |
49 | - this.connection = new Connection(this, this); | |
48 | + this.connection = new Connection(activity, this, this); | |
50 | 49 | } |
51 | 50 | |
52 | 51 | public void connect() |
@@ -1,5 +1,6 @@ | ||
1 | 1 | package net.osdn.gokigen.cameratest.fuji; |
2 | 2 | |
3 | +import android.app.Activity; | |
3 | 4 | import android.util.Log; |
4 | 5 | |
5 | 6 | import androidx.annotation.NonNull; |
@@ -30,9 +31,9 @@ class Communication | ||
30 | 31 | private final FujiStreamReceiver stream; |
31 | 32 | private final FujiAsyncResponseReceiver response; |
32 | 33 | |
33 | - Communication(@NonNull ILiveViewImage imageViewer) | |
34 | + Communication(@NonNull Activity activity, @NonNull ILiveViewImage imageViewer) | |
34 | 35 | { |
35 | - this.stream = new FujiStreamReceiver(CAMERA_IP, STREAM_PORT, imageViewer); | |
36 | + this.stream = new FujiStreamReceiver(activity, CAMERA_IP, STREAM_PORT, imageViewer); | |
36 | 37 | this.response = new FujiAsyncResponseReceiver(CAMERA_IP, ASYNC_RESPONSE_PORT); |
37 | 38 | } |
38 | 39 |
@@ -1,5 +1,6 @@ | ||
1 | 1 | package net.osdn.gokigen.cameratest.fuji; |
2 | 2 | |
3 | +import android.app.Activity; | |
3 | 4 | import android.graphics.PointF; |
4 | 5 | import android.util.Log; |
5 | 6 |
@@ -16,9 +17,9 @@ public class Connection implements IFujiStatusRequest | ||
16 | 17 | private final Communication comm; |
17 | 18 | private final FujiStatusChecker statusChecker; |
18 | 19 | |
19 | - public Connection(@NonNull ILiveViewImage imageViewer, @NonNull IFujiStatusNotify notify) | |
20 | + public Connection(@NonNull Activity activity, @NonNull ILiveViewImage imageViewer, @NonNull IFujiStatusNotify notify) | |
20 | 21 | { |
21 | - this.comm = new Communication(imageViewer); | |
22 | + this.comm = new Communication(activity, imageViewer); | |
22 | 23 | this.sequence = new MessageSequence(); |
23 | 24 | this.statusChecker = new FujiStatusChecker(this, notify); |
24 | 25 | } |
@@ -12,6 +12,7 @@ class FujiAsyncResponseReceiver | ||
12 | 12 | private final int portNumber; |
13 | 13 | private static final int BUFFER_SIZE = 1280 + 8; |
14 | 14 | private static final int WAIT_MS = 250; // 250ms |
15 | + private static final int ERROR_LIMIT = 30; | |
15 | 16 | private boolean isStart = false; |
16 | 17 | |
17 | 18 | FujiAsyncResponseReceiver(String ip, int portNumber) |
@@ -22,6 +23,11 @@ class FujiAsyncResponseReceiver | ||
22 | 23 | |
23 | 24 | void start() |
24 | 25 | { |
26 | + if (isStart) | |
27 | + { | |
28 | + // すでに受信スレッド動作中なので抜ける | |
29 | + return; | |
30 | + } | |
25 | 31 | isStart = true; |
26 | 32 | Thread thread = new Thread(new Runnable() |
27 | 33 | { |
@@ -57,6 +63,7 @@ class FujiAsyncResponseReceiver | ||
57 | 63 | |
58 | 64 | private void startReceive(Socket socket) |
59 | 65 | { |
66 | + int errorCount = 0; | |
60 | 67 | InputStreamReader isr; |
61 | 68 | char[] char_array; |
62 | 69 | try |
@@ -81,10 +88,17 @@ class FujiAsyncResponseReceiver | ||
81 | 88 | //return (new ReceivedDataHolder(char_array, read_bytes)); |
82 | 89 | |
83 | 90 | Thread.sleep(WAIT_MS); |
91 | + errorCount = 0; | |
84 | 92 | } |
85 | 93 | catch (Exception e) |
86 | 94 | { |
87 | 95 | e.printStackTrace(); |
96 | + errorCount++; | |
97 | + } | |
98 | + if (errorCount > ERROR_LIMIT) | |
99 | + { | |
100 | + // エラーが連続でたくさん出たらループをストップさせる | |
101 | + isStart = false; | |
88 | 102 | } |
89 | 103 | } |
90 | 104 | try |
@@ -1,29 +1,59 @@ | ||
1 | 1 | package net.osdn.gokigen.cameratest.fuji; |
2 | 2 | |
3 | +import android.app.Activity; | |
4 | +import android.content.SharedPreferences; | |
3 | 5 | import android.util.Log; |
4 | 6 | import androidx.annotation.NonNull; |
7 | +import androidx.preference.PreferenceManager; | |
8 | + | |
5 | 9 | import java.io.InputStream; |
6 | 10 | import java.net.Socket; |
7 | 11 | |
12 | +import static net.osdn.gokigen.cameratest.fuji.preference.IPreferencePropertyAccessor.FUJIX_LIVEVIEW_WAIT; | |
13 | +import static net.osdn.gokigen.cameratest.fuji.preference.IPreferencePropertyAccessor.FUJIX_LIVEVIEW_WAIT_DEFAULT_VALUE; | |
14 | + | |
8 | 15 | class FujiStreamReceiver |
9 | 16 | { |
10 | 17 | private final String TAG = toString(); |
11 | 18 | private final String ipAddress; |
12 | 19 | private final int portNumber; |
13 | 20 | private final ILiveViewImage imageViewer; |
14 | - private static final int WAIT_MS = 80; | |
21 | + private int waitMs = 80; | |
15 | 22 | private static final int BUFFER_SIZE = 1280 * 1024 + 8; |
23 | + private static final int ERROR_LIMIT = 30; | |
16 | 24 | private boolean isStart = false; |
17 | 25 | |
18 | - FujiStreamReceiver(String ip, int portNumber, @NonNull ILiveViewImage imageViewer) | |
26 | + FujiStreamReceiver(@NonNull Activity activity, String ip, int portNumber, @NonNull ILiveViewImage imageViewer) | |
19 | 27 | { |
20 | 28 | this.ipAddress = ip; |
21 | 29 | this.portNumber = portNumber; |
22 | 30 | this.imageViewer = imageViewer; |
31 | + | |
32 | + try | |
33 | + { | |
34 | + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity); | |
35 | + String waitMsStr = preferences.getString(FUJIX_LIVEVIEW_WAIT, FUJIX_LIVEVIEW_WAIT_DEFAULT_VALUE); | |
36 | + int wait = Integer.parseInt(waitMsStr); | |
37 | + if ((wait >= 10)&&(wait <= 800)) | |
38 | + { | |
39 | + waitMs = wait; | |
40 | + } | |
41 | + } | |
42 | + catch (Exception e) | |
43 | + { | |
44 | + e.printStackTrace(); | |
45 | + waitMs = 80; | |
46 | + } | |
47 | + Log.v(TAG, "LOOP WAIT : " + waitMs + " ms"); | |
23 | 48 | } |
24 | 49 | |
25 | 50 | void start() |
26 | 51 | { |
52 | + if (isStart) | |
53 | + { | |
54 | + // すでに受信スレッド動作中なので抜ける | |
55 | + return; | |
56 | + } | |
27 | 57 | isStart = true; |
28 | 58 | Thread thread = new Thread(new Runnable() |
29 | 59 | { |
@@ -59,6 +89,7 @@ class FujiStreamReceiver | ||
59 | 89 | |
60 | 90 | private void startReceive(Socket socket) |
61 | 91 | { |
92 | + int errorCount = 0; | |
62 | 93 | InputStream isr; |
63 | 94 | byte[] byteArray; |
64 | 95 | try |
@@ -78,11 +109,18 @@ class FujiStreamReceiver | ||
78 | 109 | { |
79 | 110 | int read_bytes = isr.read(byteArray, 0, BUFFER_SIZE); |
80 | 111 | imageViewer.updateImage(new ReceivedDataHolder(byteArray, read_bytes)); |
81 | - Thread.sleep(WAIT_MS); | |
112 | + Thread.sleep(waitMs); | |
113 | + errorCount = 0; | |
82 | 114 | } |
83 | 115 | catch (Exception e) |
84 | 116 | { |
85 | 117 | e.printStackTrace(); |
118 | + errorCount++; | |
119 | + } | |
120 | + if (errorCount > ERROR_LIMIT) | |
121 | + { | |
122 | + // エラーが連続でたくさん出たらループをストップさせる | |
123 | + isStart = false; | |
86 | 124 | } |
87 | 125 | } |
88 | 126 | try |
@@ -17,7 +17,6 @@ import androidx.preference.PreferenceManager; | ||
17 | 17 | import net.osdn.gokigen.cameratest.IApplicationControl; |
18 | 18 | import net.osdn.gokigen.cameratest.R; |
19 | 19 | |
20 | -import java.net.Inet4Address; | |
21 | 20 | import java.util.Map; |
22 | 21 | |
23 | 22 | public class FujiPreferenceFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener |
@@ -116,6 +115,17 @@ public class FujiPreferenceFragment extends PreferenceFragmentCompat implements | ||
116 | 115 | { |
117 | 116 | e.printStackTrace(); |
118 | 117 | } |
118 | + try | |
119 | + { | |
120 | + EditTextPreference lvWait = (EditTextPreference) findPreference(IPreferencePropertyAccessor.FUJIX_LIVEVIEW_WAIT); | |
121 | + String wait = lvWait.getText(); | |
122 | + int waitMs = Integer.parseInt(wait); | |
123 | + lvWait.setText("" + waitMs); | |
124 | + } | |
125 | + catch (Exception e) | |
126 | + { | |
127 | + e.printStackTrace(); | |
128 | + } | |
119 | 129 | } |
120 | 130 | |
121 | 131 | /** |
@@ -141,6 +151,9 @@ public class FujiPreferenceFragment extends PreferenceFragmentCompat implements | ||
141 | 151 | if (!items.containsKey(IPreferencePropertyAccessor.FUJIX_FOCUS_XY)) { |
142 | 152 | editor.putString(IPreferencePropertyAccessor.FUJIX_FOCUS_XY, IPreferencePropertyAccessor.FUJIX_FOCUS_XY_DEFAULT_VALUE); |
143 | 153 | } |
154 | + if (!items.containsKey(IPreferencePropertyAccessor.FUJIX_LIVEVIEW_WAIT)) { | |
155 | + editor.putString(IPreferencePropertyAccessor.FUJIX_LIVEVIEW_WAIT, IPreferencePropertyAccessor.FUJIX_LIVEVIEW_WAIT_DEFAULT_VALUE); | |
156 | + } | |
144 | 157 | editor.apply(); |
145 | 158 | } |
146 | 159 | catch (Exception e) |
@@ -10,7 +10,11 @@ public interface IPreferencePropertyAccessor | ||
10 | 10 | String CAPTURE_BOTH_CAMERA_AND_LIVE_VIEW = "capture_both_camera_and_live_view"; |
11 | 11 | |
12 | 12 | String FUJIX_DISPLAY_CAMERA_VIEW = "fujix_display_camera_view"; |
13 | + | |
13 | 14 | String FUJIX_FOCUS_XY = "fujix_focus_xy"; |
14 | 15 | String FUJIX_FOCUS_XY_DEFAULT_VALUE = "7,7"; |
15 | 16 | |
17 | + String FUJIX_LIVEVIEW_WAIT = "fujix_liveview_wait"; | |
18 | + String FUJIX_LIVEVIEW_WAIT_DEFAULT_VALUE = "80"; | |
19 | + | |
16 | 20 | } |
@@ -12,6 +12,7 @@ public class FujiStatusChecker implements IFujiStatusReceiver | ||
12 | 12 | private final IFujiStatusRequest comm; |
13 | 13 | private final IFujiStatusNotify notify; |
14 | 14 | private final FujiStatusHolder statusHolder; |
15 | + private static final int ERROR_LIMIT = 10; | |
15 | 16 | private boolean threadIsRunning = false; |
16 | 17 | private final int WAIT_MS = 400; |
17 | 18 |
@@ -35,22 +36,28 @@ public class FujiStatusChecker implements IFujiStatusReceiver | ||
35 | 36 | @Override |
36 | 37 | public void run() |
37 | 38 | { |
38 | - try | |
39 | + | |
40 | + int errorCount = 0; | |
41 | + threadIsRunning = true; | |
42 | + while (threadIsRunning) | |
39 | 43 | { |
40 | - threadIsRunning = true; | |
41 | - while (threadIsRunning) | |
44 | + try | |
42 | 45 | { |
43 | 46 | comm.requestStatus(); |
44 | 47 | Thread.sleep(WAIT_MS); |
48 | + errorCount = 0; | |
49 | + } | |
50 | + catch (Exception e) | |
51 | + { | |
52 | + e.printStackTrace(); | |
53 | + errorCount++; | |
54 | + } | |
55 | + if (errorCount > ERROR_LIMIT) | |
56 | + { | |
57 | + threadIsRunning = false; | |
45 | 58 | } |
46 | 59 | } |
47 | - catch (Exception e) | |
48 | - { | |
49 | - e.printStackTrace(); | |
50 | - } | |
51 | - threadIsRunning = false; | |
52 | 60 | Log.v(TAG, "--- FINISH STATUS WATCH ---"); |
53 | - | |
54 | 61 | } |
55 | 62 | }); |
56 | 63 | try |
@@ -37,8 +37,11 @@ | ||
37 | 37 | <string name="pref_fujix_display_camera_view">Use Camera Display</string> |
38 | 38 | <string name="pref_fujix_display_camera_view_summary">Shows liveview screen both camera and smartphone.</string> |
39 | 39 | |
40 | - <string name="pref_fujix_focus_xy">Focus Area X,Y (default: 7,7)</string> | |
41 | - <string name="pref_summary_fujix_focus_xy">Set Focus Area resolution X,Y (default: 7,7)</string> | |
40 | + <string name="pref_fujix_focus_xy">Number of Focus Point X,Y (default: 7,7)</string> | |
41 | + <string name="pref_summary_fujix_focus_xy"> </string> | |
42 | + | |
43 | + <string name="pref_fujix_liveview_wait">Liveview receive wait (default: 80)</string> | |
44 | + <string name="pref_summary_fujix_liveview_wait"> </string> | |
42 | 45 | |
43 | 46 | <string name="pref_special_thanks">Special Thanks to : fuji-cam-wifi-tool</string> |
44 | 47 |
@@ -30,6 +30,12 @@ | ||
30 | 30 | android:defaultValue="7,7" |
31 | 31 | android:summary="@string/pref_summary_fujix_focus_xy" /> |
32 | 32 | |
33 | + <EditTextPreference | |
34 | + android:key="fujix_liveview_wait" | |
35 | + android:title="@string/pref_fujix_liveview_wait" | |
36 | + android:defaultValue="80" | |
37 | + android:summary="@string/pref_summary_fujix_liveview_wait" /> | |
38 | + | |
33 | 39 | <CheckBoxPreference |
34 | 40 | android:key="capture_both_camera_and_live_view" |
35 | 41 | android:title="@string/pref_capture_both_camera_and_live_view" /> |