OSDN Git Service

FUJI X対応の準備(その5)
authorMRSa <mrsa@myad.jp>
Tue, 21 Apr 2020 14:06:37 +0000 (23:06 +0900)
committerMRSa <mrsa@myad.jp>
Tue, 21 Apr 2020 14:06:37 +0000 (23:06 +0900)
13 files changed:
app/src/main/java/net/osdn/gokigen/gr2control/camera/fuji_x/IFujiXInterfaceProvider.java
app/src/main/java/net/osdn/gokigen/gr2control/camera/fuji_x/wrapper/FujiXInterfaceProvider.java
app/src/main/java/net/osdn/gokigen/gr2control/camera/fuji_x/wrapper/FujiXLiveViewControl.java
app/src/main/java/net/osdn/gokigen/gr2control/camera/fuji_x/wrapper/FujiXStatusChecker.java
app/src/main/java/net/osdn/gokigen/gr2control/camera/fuji_x/wrapper/FujiXStatusHolder.java
app/src/main/java/net/osdn/gokigen/gr2control/liveview/LiveViewClickTouchListener.java
app/src/main/java/net/osdn/gokigen/gr2control/preference/IPreferencePropertyAccessor.java
app/src/main/java/net/osdn/gokigen/gr2control/preference/fuji_x/FujiXPreferenceFragment.java
app/src/main/java/net/osdn/gokigen/gr2control/preference/olympus/PreferenceFragment.java
app/src/main/java/net/osdn/gokigen/gr2control/preference/ricohgr2/RicohGr2PreferenceFragment.java
app/src/main/res/values-ja/strings.xml
app/src/main/res/values/strings.xml
app/src/main/res/xml/preferences_fuji_x.xml

index 87c2f52..7262ffd 100644 (file)
@@ -43,11 +43,9 @@ public interface IFujiXInterfaceProvider
     ICameraHardwareStatus getHardwareStatus();
     ICameraRunMode getCameraRunMode();
 
-
     IFujiXCommunication getLiveviewCommunication();
     IFujiXCommunication getAsyncEventCommunication();
     IFujiXCommunication getCommandCommunication();
-    IFujiXCommandCallback getStatusHolder();
     ICameraStatusUpdateNotify getStatusListener();
     IFujiXCommandPublisher getCommandPublisher();
     void setAsyncEventReceiver(@NonNull IFujiXCommandCallback receiver);
index 1ab4e29..53954fb 100644 (file)
@@ -94,7 +94,7 @@ public class FujiXInterfaceProvider implements IFujiXInterfaceProvider, IDisplay
         asyncReceiver = new FujiXAsyncResponseReceiver(CAMERA_IP, ASYNC_RESPONSE_PORT);
         zoomControl = new FujiXZoomControl();
         buttonControl = new FujiXButtonControl();
-        statusChecker = new FujiXStatusChecker(500);
+        statusChecker = new FujiXStatusChecker(context, commandPublisher);
         playbackControl = new FujiXPlaybackControl(communicationTimeoutMs);
         hardwareStatus = new FujiXHardwareStatus();
         runMode = new FujiXRunMode();
@@ -203,30 +203,24 @@ public class FujiXInterfaceProvider implements IFujiXInterfaceProvider, IDisplay
 
     @Override
     public IFujiXCommunication getLiveviewCommunication() {
-        return null;
+        return (liveViewControl);
     }
 
     @Override
     public IFujiXCommunication getAsyncEventCommunication() {
-        return null;
+        return (asyncReceiver);
     }
 
     @Override
     public IFujiXCommunication getCommandCommunication()
     {
-        return (null);
-    }
-
-    @Override
-    public IFujiXCommandCallback getStatusHolder()
-    {
-        return null;
+        return (commandPublisher);
     }
 
     @Override
     public ICameraStatusUpdateNotify getStatusListener()
     {
-        return null;
+        return statusChecker.getStatusListener();
     }
 
     @Override
index 810f32c..92e6fed 100644 (file)
 package net.osdn.gokigen.gr2control.camera.fuji_x.wrapper;
 
 import android.app.Activity;
+import android.content.SharedPreferences;
+import android.util.Log;
 
 import androidx.annotation.NonNull;
+import androidx.preference.PreferenceManager;
 
 import net.osdn.gokigen.gr2control.camera.ILiveViewControl;
+import net.osdn.gokigen.gr2control.camera.fuji_x.wrapper.command.IFujiXCommunication;
 import net.osdn.gokigen.gr2control.liveview.liveviewlistener.CameraLiveViewListenerImpl;
 import net.osdn.gokigen.gr2control.liveview.liveviewlistener.ILiveViewListener;
 
-public class FujiXLiveViewControl  implements ILiveViewControl
+import java.io.InputStream;
+import java.net.Socket;
+import java.util.Arrays;
+
+import static net.osdn.gokigen.gr2control.preference.IPreferencePropertyAccessor.FUJI_X_LIVEVIEW_WAIT;
+import static net.osdn.gokigen.gr2control.preference.IPreferencePropertyAccessor.FUJI_X_LIVEVIEW_WAIT_DEFAULT_VALUE;
+
+public class FujiXLiveViewControl implements ILiveViewControl, IFujiXCommunication
 {
     private final String TAG = toString();
-
     private final String ipAddress;
     private final int portNumber;
-
     private final CameraLiveViewListenerImpl liveViewListener;
+    private int waitMs = 0;
+    private static final int DATA_HEADER_OFFSET = 18;
+    private static final int BUFFER_SIZE = 2048 * 1280;
+    private static final int ERROR_LIMIT = 30;
+    private boolean isStart = false;
+    private boolean logcat = false;
 
-    /**
-     *
-     *
-     */
     FujiXLiveViewControl(@NonNull Activity activity, String ip, int portNumber)
     {
         this.ipAddress = ip;
         this.portNumber = portNumber;
         liveViewListener = new CameraLiveViewListenerImpl();
-    }
-
-
-    @Override
-    public void changeLiveViewSize(String size)
-    {
 
+        try
+        {
+            SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
+            String waitMsStr = preferences.getString(FUJI_X_LIVEVIEW_WAIT, FUJI_X_LIVEVIEW_WAIT_DEFAULT_VALUE);
+            logcat("waitMS : " + waitMsStr);
+            int wait = Integer.parseInt(waitMsStr);
+            if ((wait >= 20)&&(wait <= 800))
+            {
+                waitMs = wait;
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+            waitMs = 100;
+        }
+        Log.v(TAG, "LOOP WAIT : " + waitMs + " ms");
     }
 
     @Override
     public void startLiveView(boolean isCameraScreen)
     {
-
+        if (isStart)
+        {
+            // すでに受信スレッド動作中なので抜ける
+            return;
+        }
+        isStart = true;
+        Thread thread = new Thread(new Runnable()
+        {
+            @Override
+            public void run()
+            {
+                try
+                {
+                    Socket socket = new Socket(ipAddress, portNumber);
+                    startReceive(socket);
+                }
+                catch (Exception e)
+                {
+                    Log.v(TAG, " IP : " + ipAddress + " port : " + portNumber);
+                    e.printStackTrace();
+                }
+            }
+        });
+        try
+        {
+            thread.start();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
     }
 
     @Override
     public void stopLiveView()
     {
+        isStart = false;
+    }
+
+    private void startReceive(Socket socket)
+    {
+        String lvHeader = "[LV]";
+        int lvHeaderDumpBytes = 24;
 
+        int errorCount = 0;
+        InputStream isr;
+        byte[] byteArray;
+        try
+        {
+            isr = socket.getInputStream();
+            byteArray = new byte[BUFFER_SIZE + 32];
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+            Log.v(TAG, "===== startReceive() aborted.");
+            return;
+        }
+        while (isStart)
+        {
+            try
+            {
+                boolean findJpeg = false;
+                int length_bytes;
+                int read_bytes = isr.read(byteArray, 0, BUFFER_SIZE);
+                if (read_bytes > DATA_HEADER_OFFSET)
+                {
+                    // メッセージボディの先頭にあるメッセージ長分は読み込む
+                    length_bytes = ((((int) byteArray[3]) & 0xff) << 24) + ((((int) byteArray[2]) & 0xff) << 16) + ((((int) byteArray[1]) & 0xff) << 8) + (((int) byteArray[0]) & 0xff);
+                    if ((byteArray[18] == (byte)0xff)&&(byteArray[19] == (byte)0xd8))
+                    {
+                        findJpeg = true;
+                        while ((read_bytes < length_bytes) && (read_bytes < BUFFER_SIZE) && (length_bytes <= BUFFER_SIZE))
+                        {
+                            int append_bytes = isr.read(byteArray, read_bytes, length_bytes - read_bytes);
+                            logcat("READ AGAIN : " + append_bytes + " [" + read_bytes + "]");
+                            if (append_bytes < 0)
+                            {
+                                break;
+                            }
+                            read_bytes = read_bytes + append_bytes;
+                        }
+                        logcat("READ BYTES : " + read_bytes + "  (" + length_bytes + " bytes, " + waitMs + "ms)");
+                    }
+                    else
+                    {
+                        // ウェイトを短めに入れてマーカーを拾うまで待つ
+                        Thread.sleep(waitMs/4);
+                        continue;
+                    }
+                }
+
+                // 先頭データ(24バイト分)をダンプ
+                dump_bytes(lvHeader, byteArray, lvHeaderDumpBytes);
+
+                if (findJpeg)
+                {
+                    liveViewListener.onUpdateLiveView(Arrays.copyOfRange(byteArray, DATA_HEADER_OFFSET, read_bytes - DATA_HEADER_OFFSET), null);
+                    errorCount = 0;
+                }
+                Thread.sleep(waitMs);
+            }
+            catch (Exception e)
+            {
+                e.printStackTrace();
+                errorCount++;
+            }
+            if (errorCount > ERROR_LIMIT)
+            {
+                // エラーが連続でたくさん出たらループをストップさせる
+                isStart = false;
+            }
+        }
+        try
+        {
+            isr.close();
+            socket.close();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
     }
 
+
     @Override
     public void updateDigitalZoom()
     {
@@ -62,18 +200,82 @@ public class FujiXLiveViewControl  implements ILiveViewControl
     @Override
     public float getMagnifyingLiveViewScale()
     {
-        return 0;
+        return (1.0f);
     }
 
     @Override
-    public float getDigitalZoomScale()
+    public void changeLiveViewSize(String size)
     {
-        return 0;
+
     }
 
+    @Override
+    public float getDigitalZoomScale()
+    {
+        return (1.0f);
+    }
 
     public ILiveViewListener getLiveViewListener()
     {
         return (liveViewListener);
     }
+
+    @Override
+    public boolean connect()
+    {
+        return (true);
+    }
+
+    @Override
+    public void disconnect()
+    {
+        isStart = false;
+    }
+
+    /**
+     *   デバッグ用:ログにバイト列を出力する
+     *
+     */
+    private void dump_bytes(String header, byte[] data, int dumpBytes)
+    {
+        if (!logcat)
+        {
+            // ログ出力しないモードだった
+            return;
+        }
+
+        int index = 0;
+        StringBuffer message;
+        if (dumpBytes <= 0)
+        {
+            dumpBytes = 24;
+        }
+        message = new StringBuffer();
+        for (int point = 0; point < dumpBytes; point++)
+        {
+            byte item = data[point];
+            index++;
+            message.append(String.format("%02x ", item));
+            if (index >= 8)
+            {
+                Log.v(TAG, header + " " + message);
+                index = 0;
+                message = new StringBuffer();
+            }
+        }
+        if (index != 0)
+        {
+            Log.v(TAG, header + " " + message);
+        }
+        System.gc();
+    }
+
+    private void logcat(String message)
+    {
+        if (logcat)
+        {
+            Log.v(TAG, message);
+        }
+    }
+
 }
index 41eee38..f105681 100644 (file)
 package net.osdn.gokigen.gr2control.camera.fuji_x.wrapper;
 
+import android.app.Activity;
+import android.content.SharedPreferences;
+import android.util.Log;
+
 import androidx.annotation.NonNull;
+import androidx.preference.PreferenceManager;
 
 import net.osdn.gokigen.gr2control.camera.ICameraStatus;
 import net.osdn.gokigen.gr2control.camera.ICameraStatusWatcher;
+import net.osdn.gokigen.gr2control.camera.fuji_x.wrapper.command.IFujiXCommandCallback;
+import net.osdn.gokigen.gr2control.camera.fuji_x.wrapper.command.IFujiXCommandPublisher;
+import net.osdn.gokigen.gr2control.camera.fuji_x.wrapper.command.messages.StatusRequestMessage;
 import net.osdn.gokigen.gr2control.liveview.ICameraStatusUpdateNotify;
+import net.osdn.gokigen.gr2control.preference.IPreferencePropertyAccessor;
 
 import java.util.ArrayList;
 import java.util.List;
 
-public class FujiXStatusChecker implements ICameraStatusWatcher, ICameraStatus
+public class FujiXStatusChecker implements ICameraStatusWatcher, ICameraStatus, IFujiXCommandCallback
 {
     private final String TAG = toString();
-    private final int sleepMs;
+    private static final int STATUS_MESSAGE_HEADER_SIZE = 14;
+    private int sleepMs;
+    private final IFujiXCommandPublisher issuer;
+    private ICameraStatusUpdateNotify notifier = null;
+    private FujiXStatusHolder statusHolder;
+    private boolean whileFetching = false;
+    private boolean logcat = false;
+
+
+    FujiXStatusChecker(@NonNull Activity activity, @NonNull IFujiXCommandPublisher issuer)
+    {
+        this.issuer = issuer;
+        this.statusHolder = new FujiXStatusHolder();
+        try
+        {
+            SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
+            String pollingWait = preferences.getString(IPreferencePropertyAccessor.FUJI_X_COMMAND_POLLING_WAIT, IPreferencePropertyAccessor.FUJI_X_COMMAND_POLLING_WAIT_DEFAULT_VALUE);
+            this.sleepMs = Integer.parseInt(pollingWait);
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+            this.sleepMs = 400;
+        }
+        Log.v(TAG, "POLLING WAIT : " + sleepMs);
+    }
 
-    FujiXStatusChecker(int sleepMs)
+    @Override
+    public void onReceiveProgress(int currentBytes, int totalBytes, byte[] body)
     {
-        this.sleepMs = sleepMs;
+        Log.v(TAG, " " + currentBytes + "/" + totalBytes);
+    }
 
+    @Override
+    public boolean isReceiveMulti()
+    {
+        return (false);
     }
 
-    @NonNull
     @Override
-    public List<String> getStatusList(@NonNull String key)
+    public void receivedMessage(int id, byte[] data)
     {
-        List<String> statusList = new ArrayList<>();
+        try
+        {
+            logcat("receivedMessage : " + id + ", length: " + data.length);
+            if (data.length < STATUS_MESSAGE_HEADER_SIZE)
+            {
+                Log.v(TAG, "received status length is short. (" + data.length + " bytes.)");
+                return;
+            }
 
-        return (statusList);
+            int nofStatus = (data[13] * 256) + data[12];
+            int statusCount = 0;
+            int index = STATUS_MESSAGE_HEADER_SIZE;
+            while ((statusCount < nofStatus)&&(index < data.length))
+            {
+                int dataId = ((((int)data[index + 1]) & 0xff) * 256) + (((int) data[index]) & 0xff);
+                statusHolder.updateValue(notifier, dataId, data[index + 2], data[index + 3], data[index +4], data[index + 5]);
+                index = index + 6;
+                statusCount++;
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public @NonNull List<String> getStatusList(@NonNull String key)
+    {
+        try
+        {
+            if (statusHolder == null)
+            {
+                return (new ArrayList<>());
+            }
+            return (statusHolder.getAvailableItemList(key));
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        return (new ArrayList<>());
     }
 
     @Override
     public String getStatus(@NonNull String key)
     {
-        return (null);
+        try
+        {
+            if (statusHolder == null)
+            {
+                return ("");
+            }
+            return (statusHolder.getItemStatus(key));
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        return ("");
     }
 
     @Override
     public void setStatus(@NonNull String key, @NonNull String value)
     {
+        try
+        {
+            if (logcat)
+            {
+                Log.v(TAG, "setStatus(" + key + ", " + value + ")");
+            }
 
+            // ここで設定を行う。
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
     }
 
     @Override
     public void startStatusWatch(@NonNull ICameraStatusUpdateNotify notifier)
     {
-
+        if (whileFetching)
+        {
+            Log.v(TAG, "startStatusWatch() already starting.");
+            return;
+        }
+        try
+        {
+            final IFujiXCommandCallback callback = this;
+            this.notifier = notifier;
+            whileFetching = true;
+            Thread thread = new Thread(new Runnable()
+            {
+                @Override
+                public void run()
+                {
+                    logcat("Start status watch. : " + sleepMs + "ms");
+                    while (whileFetching)
+                    {
+                        try
+                        {
+                            issuer.enqueueCommand(new StatusRequestMessage(callback));
+                            Thread.sleep(sleepMs);
+                        }
+                        catch (Exception e)
+                        {
+                            e.printStackTrace();
+                        }
+                    }
+                    logcat("STATUS WATCH STOPPED.");
+                }
+            });
+            thread.start();
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
     }
 
     @Override
     public void stopStatusWatch()
     {
+        Log.v(TAG, "stoptStatusWatch()");
+        whileFetching = false;
+        this.notifier = null;
+    }
 
+    ICameraStatusUpdateNotify getStatusListener()
+    {
+        return (this.notifier);
+    }
+
+    private void logcat(String message)
+    {
+        if (logcat)
+        {
+            Log.v(TAG, message);
+        }
     }
 }
index bac553e..0b338d1 100644 (file)
@@ -1,7 +1,208 @@
 package net.osdn.gokigen.gr2control.camera.fuji_x.wrapper;
 
-public class FujiXStatusHolder
+import android.util.Log;
+import android.util.SparseIntArray;
+
+import androidx.annotation.NonNull;
+import androidx.collection.SparseArrayCompat;
+
+import net.osdn.gokigen.gr2control.camera.fuji_x.wrapper.values.IFujiXCameraProperties;
+import net.osdn.gokigen.gr2control.liveview.ICameraStatusUpdateNotify;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import static net.osdn.gokigen.gr2control.camera.fuji_x.wrapper.values.IFujiXCameraProperties.FOCUS_LOCK;
+
+class FujiXStatusHolder
 {
+    private final String TAG = toString();
+    private SparseIntArray statusHolder;
+    private SparseArrayCompat<String> statusNameArray;
+
+    FujiXStatusHolder()
+    {
+        statusHolder = new SparseIntArray();
+        statusHolder.clear();
+
+        statusNameArray = new SparseArrayCompat<>();
+        prepareStatusNameArray();
+    }
+
+    private void prepareStatusNameArray()
+    {
+        statusNameArray.clear();
+        statusNameArray.append(IFujiXCameraProperties.BATTERY_LEVEL, IFujiXCameraProperties.BATTERY_LEVEL_STR);
+        statusNameArray.append(IFujiXCameraProperties.WHITE_BALANCE, IFujiXCameraProperties.WHITE_BALANCE_STR);
+        statusNameArray.append(IFujiXCameraProperties.APERTURE, IFujiXCameraProperties.APERTURE_STR);
+        statusNameArray.append(IFujiXCameraProperties.FOCUS_MODE, IFujiXCameraProperties.FOCUS_MODE_STR);
+        statusNameArray.append(IFujiXCameraProperties.SHOOTING_MODE, IFujiXCameraProperties.SHOOTING_MODE_STR);
+        statusNameArray.append(IFujiXCameraProperties.FLASH, IFujiXCameraProperties.FLASH_STR);
+        statusNameArray.append(IFujiXCameraProperties.EXPOSURE_COMPENSATION, IFujiXCameraProperties.EXPOSURE_COMPENSATION_STR);
+        statusNameArray.append(IFujiXCameraProperties.SELF_TIMER, IFujiXCameraProperties.SELF_TIMER_STR);
+        statusNameArray.append(IFujiXCameraProperties.FILM_SIMULATION, IFujiXCameraProperties.FILM_SIMULATION_STR);
+        statusNameArray.append(IFujiXCameraProperties.IMAGE_FORMAT, IFujiXCameraProperties.IMAGE_FORMAT_STR);
+        statusNameArray.append(IFujiXCameraProperties.RECMODE_ENABLE, IFujiXCameraProperties.RECMODE_ENABLE_STR);
+        statusNameArray.append(IFujiXCameraProperties.F_SS_CONTROL, IFujiXCameraProperties.F_SS_CONTROL_STR);
+        statusNameArray.append(IFujiXCameraProperties.ISO, IFujiXCameraProperties.ISO_STR);
+        statusNameArray.append(IFujiXCameraProperties.MOVIE_ISO, IFujiXCameraProperties.MOVIE_ISO_STR);
+        statusNameArray.append(IFujiXCameraProperties.FOCUS_POINT, IFujiXCameraProperties.FOCUS_POINT_STR);
+        statusNameArray.append(IFujiXCameraProperties.DEVICE_ERROR, IFujiXCameraProperties.DEVICE_ERROR_STR);
+        statusNameArray.append(IFujiXCameraProperties.IMAGE_FILE_COUNT, IFujiXCameraProperties.IMAGE_FILE_COUNT_STR);
+        statusNameArray.append(IFujiXCameraProperties.SDCARD_REMAIN_SIZE, IFujiXCameraProperties.SDCARD_REMAIN_SIZE_STR);
+        statusNameArray.append(FOCUS_LOCK, IFujiXCameraProperties.FOCUS_LOCK_STR);
+        statusNameArray.append(IFujiXCameraProperties.MOVIE_REMAINING_TIME, IFujiXCameraProperties.MOVIE_REMAINING_TIME_STR);
+        statusNameArray.append(IFujiXCameraProperties.SHUTTER_SPEED, IFujiXCameraProperties.SHUTTER_SPEED_STR);
+        statusNameArray.append(IFujiXCameraProperties.IMAGE_ASPECT,IFujiXCameraProperties.IMAGE_ASPECT_STR);
+        statusNameArray.append(IFujiXCameraProperties.BATTERY_LEVEL_2, IFujiXCameraProperties.BATTERY_LEVEL_2_STR);
+
+        statusNameArray.append(IFujiXCameraProperties.UNKNOWN_DF00, IFujiXCameraProperties.UNKNOWN_DF00_STR);
+        statusNameArray.append(IFujiXCameraProperties.PICTURE_JPEG_COUNT, IFujiXCameraProperties.PICTURE_JPEG_COUNT_STR);
+        statusNameArray.append(IFujiXCameraProperties.UNKNOWN_D400, IFujiXCameraProperties.UNKNOWN_D400_STR);
+        statusNameArray.append(IFujiXCameraProperties.UNKNOWN_D401, IFujiXCameraProperties.UNKNOWN_D401_STR);
+        statusNameArray.append(IFujiXCameraProperties.UNKNOWN_D52F, IFujiXCameraProperties.UNKNOWN_D52F_STR);
+
+
+    }
+
+
+    void updateValue(ICameraStatusUpdateNotify notifier, int id, byte data0, byte data1, byte data2, byte data3)
+    {
+        try
+        {
+            int value = ((((int) data3) & 0xff) << 24) + ((((int) data2) & 0xff) << 16) + ((((int) data1) & 0xff) << 8) + (((int) data0) & 0xff);
+            int currentValue = statusHolder.get(id, -1);
+            //Log.v(TAG, "STATUS  ID: " + id + "  value : " + value + " (" + currentValue + ")");
+            statusHolder.put(id, value);
+            if (currentValue != value)
+            {
+                //Log.v(TAG, "STATUS  ID: " + id + " value : " + currentValue + " -> " + value);
+                if (notifier != null)
+                {
+                    updateDetected(notifier, id, currentValue, value);
+                }
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    private void updateDetected(@NonNull ICameraStatusUpdateNotify notifier, int id, int previous, int current)
+    {
+        try
+        {
+            String idName = statusNameArray.get(id, "Unknown");
+            Log.v(TAG, String.format(Locale.US,"<< UPDATE STATUS >> id: 0x%04x[%s] 0x%08x(%d) -> 0x%08x(%d)", id, idName, previous, previous, current, current));
+            //Log.v(TAG, "updateDetected(ID: " + id + " [" + idName + "] " + previous + " -> " + current + " )");
+
+            if (id == FOCUS_LOCK)
+            {
+                if (current == 1)
+                {
+                    // focus Lock
+                    notifier.updateFocusedStatus(true, true);
+                }
+                else
+                {
+                    // focus unlock
+                    notifier.updateFocusedStatus(false, false);
+                }
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     *   認識したカメラのステータス名称のリストを応答する
+     *
+     */
+    private List<String> getAvailableStatusNameList()
+    {
+        ArrayList<String> selection = new ArrayList<>();
+        try
+        {
+            for (int index = 0; index < statusHolder.size(); index++)
+            {
+                int key = statusHolder.keyAt(index);
+                selection.add(statusNameArray.get(key, String.format(Locale.US, "0x%04x", key)));
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        return (selection);
+
+    }
+
+    List<String> getAvailableItemList(String listKey)
+    {
+        if (listKey == null)
+        {
+            // アイテム名の一覧を応答する
+            return (getAvailableStatusNameList());
+        }
+
+        /////  選択可能なステータスの一覧を取得する : でも以下はアイテム名の一覧... /////
+        ArrayList<String> selection = new ArrayList<>();
+        try
+        {
+            for (int index = 0; index < statusHolder.size(); index++)
+            {
+                int key = statusHolder.keyAt(index);
+                selection.add(statusNameArray.get(key));
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        return (selection);
+    }
+
+    String getItemStatus(String key)
+    {
+        try
+        {
+            int strIndex = key.indexOf("x");
+            Log.v(TAG, "getItemStatus() : " + key + " [" + strIndex + "]");
+            if (strIndex >= 1)
+            {
+                key = key.substring(strIndex + 1);
+                try
+                {
+                    int id = Integer.parseInt(key, 16);
+                    int value = statusHolder.get(id);
+                    return (String.format(Locale.US,"0x%08x (%d)", value, value));
+                }
+                catch (Exception e)
+                {
+                    e.printStackTrace();
+                }
+            }
 
+            for (int index = 0; index < statusNameArray.size(); index++)
+            {
+                int id = statusNameArray.keyAt(index);
+                String strKey = statusNameArray.valueAt(index);
+                if (key.contentEquals(strKey))
+                {
+                    int value = statusHolder.get(id);
+                    return (String.format(Locale.US,"0x%08x (%d)", value, value));
+                }
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+        return ("? [" + key + "]");
+    }
 
 }
index 0596b68..4ae8136 100644 (file)
@@ -256,7 +256,7 @@ class LiveViewClickTouchListener implements View.OnClickListener, View.OnTouchLi
         {
             // 確認ダイアログの生成と表示
             ConfirmationDialog dialog = ConfirmationDialog.newInstance(context);
-            dialog.show(R.string.dialog_title_confirmation, R.string.dialog_message_exit, new ConfirmationDialog.Callback() {
+            dialog.show(R.string.dialog_title_confirmation, R.string.dialog_message_power_off, new ConfirmationDialog.Callback() {
                 @Override
                 public void confirm()
                 {
index 6ddf8ee..9266a41 100644 (file)
@@ -60,6 +60,9 @@ public interface IPreferencePropertyAccessor
     String FUJI_X_LIVEVIEW_WAIT = "fujix_liveview_wait";
     String FUJI_X_LIVEVIEW_WAIT_DEFAULT_VALUE = "80";
 
+    String FUJI_X_COMMAND_POLLING_WAIT = "fujix_command_polling_wait";
+    String FUJI_X_COMMAND_POLLING_WAIT_DEFAULT_VALUE = "500";
+
 
 /*
     //String GR2_DISPLAY_MODE = "gr2_display_mode";
index 4da6d9a..d3f0300 100644 (file)
@@ -107,31 +107,64 @@ public class FujiXPreferenceFragment  extends PreferenceFragmentCompat implement
         {
             Map<String, ?> items = preferences.getAll();
             SharedPreferences.Editor editor = preferences.edit();
-
-            if (!items.containsKey(IPreferencePropertyAccessor.AUTO_CONNECT_TO_CAMERA)) {
+            if (!items.containsKey(IPreferencePropertyAccessor.RICOH_GET_PICS_LIST_TIMEOUT))
+            {
+                editor.putString(IPreferencePropertyAccessor.RICOH_GET_PICS_LIST_TIMEOUT, IPreferencePropertyAccessor.RICOH_GET_PICS_LIST_TIMEOUT_DEFAULT_VALUE);
+            }
+            if (!items.containsKey(IPreferencePropertyAccessor.LIVE_VIEW_QUALITY))
+            {
+                editor.putString(IPreferencePropertyAccessor.LIVE_VIEW_QUALITY, IPreferencePropertyAccessor.LIVE_VIEW_QUALITY_DEFAULT_VALUE);
+            }
+            if (!items.containsKey(IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL))
+            {
+                editor.putString(IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL, IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL_DEFAULT_VALUE);
+            }
+            if (!items.containsKey(IPreferencePropertyAccessor.RAW))
+            {
+                editor.putBoolean(IPreferencePropertyAccessor.RAW, true);
+            }
+            if (!items.containsKey(IPreferencePropertyAccessor.AUTO_CONNECT_TO_CAMERA))
+            {
                 editor.putBoolean(IPreferencePropertyAccessor.AUTO_CONNECT_TO_CAMERA, true);
             }
-            if (!items.containsKey(IPreferencePropertyAccessor.CAPTURE_BOTH_CAMERA_AND_LIVE_VIEW)) {
+            if (!items.containsKey(IPreferencePropertyAccessor.CAPTURE_BOTH_CAMERA_AND_LIVE_VIEW))
+            {
                 editor.putBoolean(IPreferencePropertyAccessor.CAPTURE_BOTH_CAMERA_AND_LIVE_VIEW, true);
             }
+            if (!items.containsKey(IPreferencePropertyAccessor.CONNECTION_METHOD))
+            {
+                editor.putString(IPreferencePropertyAccessor.CONNECTION_METHOD, IPreferencePropertyAccessor.CONNECTION_METHOD_DEFAULT_VALUE);
+            }
+            if (!items.containsKey(IPreferencePropertyAccessor.SHARE_AFTER_SAVE)) {
+                editor.putBoolean(IPreferencePropertyAccessor.SHARE_AFTER_SAVE, false);
+            }
             if (!items.containsKey(IPreferencePropertyAccessor.USE_PLAYBACK_MENU)) {
                 editor.putBoolean(IPreferencePropertyAccessor.USE_PLAYBACK_MENU, false);
             }
-            if (!items.containsKey(IPreferencePropertyAccessor.CONNECTION_METHOD)) {
-                editor.putString(IPreferencePropertyAccessor.CONNECTION_METHOD, IPreferencePropertyAccessor.CONNECTION_METHOD_DEFAULT_VALUE);
+            if (!items.containsKey(IPreferencePropertyAccessor.GR2_DISPLAY_CAMERA_VIEW)) {
+                editor.putBoolean(IPreferencePropertyAccessor.GR2_DISPLAY_CAMERA_VIEW, true);
+            }
+            if (!items.containsKey(IPreferencePropertyAccessor.GR2_LCD_SLEEP)) {
+                editor.putBoolean(IPreferencePropertyAccessor.GR2_LCD_SLEEP, false);
+            }
+            if (!items.containsKey(IPreferencePropertyAccessor.USE_GR2_SPECIAL_COMMAND)) {
+                editor.putBoolean(IPreferencePropertyAccessor.USE_GR2_SPECIAL_COMMAND, true);
+            }
+            if (!items.containsKey(IPreferencePropertyAccessor.PENTAX_CAPTURE_AFTER_AF)) {
+                editor.putBoolean(IPreferencePropertyAccessor.PENTAX_CAPTURE_AFTER_AF, false);
             }
             if (!items.containsKey(IPreferencePropertyAccessor.FUJI_X_DISPLAY_CAMERA_VIEW)) {
                 editor.putBoolean(IPreferencePropertyAccessor.FUJI_X_DISPLAY_CAMERA_VIEW, false);
             }
-            if (!items.containsKey(IPreferencePropertyAccessor.SHARE_AFTER_SAVE)) {
-                editor.putBoolean(IPreferencePropertyAccessor.SHARE_AFTER_SAVE, false);
-            }
             if (!items.containsKey(IPreferencePropertyAccessor.FUJI_X_FOCUS_XY)) {
                 editor.putString(IPreferencePropertyAccessor.FUJI_X_FOCUS_XY, IPreferencePropertyAccessor.FUJI_X_FOCUS_XY_DEFAULT_VALUE);
             }
             if (!items.containsKey(IPreferencePropertyAccessor.FUJI_X_LIVEVIEW_WAIT)) {
                 editor.putString(IPreferencePropertyAccessor.FUJI_X_LIVEVIEW_WAIT, IPreferencePropertyAccessor.FUJI_X_LIVEVIEW_WAIT_DEFAULT_VALUE);
             }
+            if (!items.containsKey(IPreferencePropertyAccessor.FUJI_X_COMMAND_POLLING_WAIT)) {
+                editor.putString(IPreferencePropertyAccessor.FUJI_X_COMMAND_POLLING_WAIT, IPreferencePropertyAccessor.FUJI_X_COMMAND_POLLING_WAIT_DEFAULT_VALUE);
+            }
             editor.apply();
         }
         catch (Exception e)
index f75e05d..350b17e 100644 (file)
@@ -127,7 +127,10 @@ public class PreferenceFragment extends PreferenceFragmentCompat implements Shar
     {
         Map<String, ?> items = preferences.getAll();
         SharedPreferences.Editor editor = preferences.edit();
-
+        if (!items.containsKey(IPreferencePropertyAccessor.RICOH_GET_PICS_LIST_TIMEOUT))
+        {
+            editor.putString(IPreferencePropertyAccessor.RICOH_GET_PICS_LIST_TIMEOUT, IPreferencePropertyAccessor.RICOH_GET_PICS_LIST_TIMEOUT_DEFAULT_VALUE);
+        }
         if (!items.containsKey(IPreferencePropertyAccessor.LIVE_VIEW_QUALITY))
         {
             editor.putString(IPreferencePropertyAccessor.LIVE_VIEW_QUALITY, IPreferencePropertyAccessor.LIVE_VIEW_QUALITY_DEFAULT_VALUE);
@@ -170,6 +173,18 @@ public class PreferenceFragment extends PreferenceFragmentCompat implements Shar
         if (!items.containsKey(IPreferencePropertyAccessor.PENTAX_CAPTURE_AFTER_AF)) {
             editor.putBoolean(IPreferencePropertyAccessor.PENTAX_CAPTURE_AFTER_AF, false);
         }
+        if (!items.containsKey(IPreferencePropertyAccessor.FUJI_X_DISPLAY_CAMERA_VIEW)) {
+            editor.putBoolean(IPreferencePropertyAccessor.FUJI_X_DISPLAY_CAMERA_VIEW, false);
+        }
+        if (!items.containsKey(IPreferencePropertyAccessor.FUJI_X_FOCUS_XY)) {
+            editor.putString(IPreferencePropertyAccessor.FUJI_X_FOCUS_XY, IPreferencePropertyAccessor.FUJI_X_FOCUS_XY_DEFAULT_VALUE);
+        }
+        if (!items.containsKey(IPreferencePropertyAccessor.FUJI_X_LIVEVIEW_WAIT)) {
+            editor.putString(IPreferencePropertyAccessor.FUJI_X_LIVEVIEW_WAIT, IPreferencePropertyAccessor.FUJI_X_LIVEVIEW_WAIT_DEFAULT_VALUE);
+        }
+        if (!items.containsKey(IPreferencePropertyAccessor.FUJI_X_COMMAND_POLLING_WAIT)) {
+            editor.putString(IPreferencePropertyAccessor.FUJI_X_COMMAND_POLLING_WAIT, IPreferencePropertyAccessor.FUJI_X_COMMAND_POLLING_WAIT_DEFAULT_VALUE);
+        }
         editor.apply();
     }
 
index ced0bb6..0a43269 100644 (file)
@@ -108,35 +108,63 @@ public class RicohGr2PreferenceFragment  extends PreferenceFragmentCompat implem
             Map<String, ?> items = preferences.getAll();
             SharedPreferences.Editor editor = preferences.edit();
 
-            if (!items.containsKey(IPreferencePropertyAccessor.AUTO_CONNECT_TO_CAMERA)) {
+            if (!items.containsKey(IPreferencePropertyAccessor.RICOH_GET_PICS_LIST_TIMEOUT))
+            {
+                editor.putString(IPreferencePropertyAccessor.RICOH_GET_PICS_LIST_TIMEOUT, IPreferencePropertyAccessor.RICOH_GET_PICS_LIST_TIMEOUT_DEFAULT_VALUE);
+            }
+            if (!items.containsKey(IPreferencePropertyAccessor.LIVE_VIEW_QUALITY))
+            {
+                editor.putString(IPreferencePropertyAccessor.LIVE_VIEW_QUALITY, IPreferencePropertyAccessor.LIVE_VIEW_QUALITY_DEFAULT_VALUE);
+            }
+            if (!items.containsKey(IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL))
+            {
+                editor.putString(IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL, IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL_DEFAULT_VALUE);
+            }
+            if (!items.containsKey(IPreferencePropertyAccessor.RAW))
+            {
+                editor.putBoolean(IPreferencePropertyAccessor.RAW, true);
+            }
+            if (!items.containsKey(IPreferencePropertyAccessor.AUTO_CONNECT_TO_CAMERA))
+            {
                 editor.putBoolean(IPreferencePropertyAccessor.AUTO_CONNECT_TO_CAMERA, true);
             }
-            if (!items.containsKey(IPreferencePropertyAccessor.CAPTURE_BOTH_CAMERA_AND_LIVE_VIEW)) {
+            if (!items.containsKey(IPreferencePropertyAccessor.CAPTURE_BOTH_CAMERA_AND_LIVE_VIEW))
+            {
                 editor.putBoolean(IPreferencePropertyAccessor.CAPTURE_BOTH_CAMERA_AND_LIVE_VIEW, true);
             }
+            if (!items.containsKey(IPreferencePropertyAccessor.CONNECTION_METHOD))
+            {
+                editor.putString(IPreferencePropertyAccessor.CONNECTION_METHOD, IPreferencePropertyAccessor.CONNECTION_METHOD_DEFAULT_VALUE);
+            }
+            if (!items.containsKey(IPreferencePropertyAccessor.SHARE_AFTER_SAVE)) {
+                editor.putBoolean(IPreferencePropertyAccessor.SHARE_AFTER_SAVE, false);
+            }
             if (!items.containsKey(IPreferencePropertyAccessor.USE_PLAYBACK_MENU)) {
                 editor.putBoolean(IPreferencePropertyAccessor.USE_PLAYBACK_MENU, false);
             }
-            if (!items.containsKey(IPreferencePropertyAccessor.CONNECTION_METHOD)) {
-                editor.putString(IPreferencePropertyAccessor.CONNECTION_METHOD, IPreferencePropertyAccessor.CONNECTION_METHOD_DEFAULT_VALUE);
-            }
             if (!items.containsKey(IPreferencePropertyAccessor.GR2_DISPLAY_CAMERA_VIEW)) {
                 editor.putBoolean(IPreferencePropertyAccessor.GR2_DISPLAY_CAMERA_VIEW, true);
             }
             if (!items.containsKey(IPreferencePropertyAccessor.GR2_LCD_SLEEP)) {
                 editor.putBoolean(IPreferencePropertyAccessor.GR2_LCD_SLEEP, false);
             }
-            if (!items.containsKey(IPreferencePropertyAccessor.SHARE_AFTER_SAVE)) {
-                editor.putBoolean(IPreferencePropertyAccessor.SHARE_AFTER_SAVE, false);
-            }
             if (!items.containsKey(IPreferencePropertyAccessor.USE_GR2_SPECIAL_COMMAND)) {
                 editor.putBoolean(IPreferencePropertyAccessor.USE_GR2_SPECIAL_COMMAND, true);
             }
             if (!items.containsKey(IPreferencePropertyAccessor.PENTAX_CAPTURE_AFTER_AF)) {
                 editor.putBoolean(IPreferencePropertyAccessor.PENTAX_CAPTURE_AFTER_AF, false);
             }
-            if (!items.containsKey(IPreferencePropertyAccessor.RICOH_GET_PICS_LIST_TIMEOUT)) {
-                editor.putString(IPreferencePropertyAccessor.RICOH_GET_PICS_LIST_TIMEOUT, IPreferencePropertyAccessor.RICOH_GET_PICS_LIST_TIMEOUT_DEFAULT_VALUE);
+            if (!items.containsKey(IPreferencePropertyAccessor.FUJI_X_DISPLAY_CAMERA_VIEW)) {
+                editor.putBoolean(IPreferencePropertyAccessor.FUJI_X_DISPLAY_CAMERA_VIEW, false);
+            }
+            if (!items.containsKey(IPreferencePropertyAccessor.FUJI_X_FOCUS_XY)) {
+                editor.putString(IPreferencePropertyAccessor.FUJI_X_FOCUS_XY, IPreferencePropertyAccessor.FUJI_X_FOCUS_XY_DEFAULT_VALUE);
+            }
+            if (!items.containsKey(IPreferencePropertyAccessor.FUJI_X_LIVEVIEW_WAIT)) {
+                editor.putString(IPreferencePropertyAccessor.FUJI_X_LIVEVIEW_WAIT, IPreferencePropertyAccessor.FUJI_X_LIVEVIEW_WAIT_DEFAULT_VALUE);
+            }
+            if (!items.containsKey(IPreferencePropertyAccessor.FUJI_X_COMMAND_POLLING_WAIT)) {
+                editor.putString(IPreferencePropertyAccessor.FUJI_X_COMMAND_POLLING_WAIT, IPreferencePropertyAccessor.FUJI_X_COMMAND_POLLING_WAIT_DEFAULT_VALUE);
             }
             editor.apply();
         }
index fc69746..332cc84 100644 (file)
     <string name="pref_summary_fujix_focus_xy">フォーカス点数を指定します</string>
     <string name="pref_fujix_liveview_wait">LV画像受信待ち間隔(default: 80)</string>
     <string name="pref_summary_fujix_liveview_wait">ライブビュー画像受信間隔を指定します</string>
+    <string name="pref_fujix_command_polling_wait">コマンド間隔(default: 500)</string>
+    <string name="pref_summary_fujix_command_polling_wait">カメラ状態の確認間隔を調整します</string>
     <string name="pref_special_thanks">Special Thanks to</string>
 
     <string name="dialog_http_command_title_command">HTTPmessage送信</string>
index aba411e..8fbdf4e 100644 (file)
@@ -48,6 +48,9 @@
     <string name="pref_fujix_liveview_wait">Liveview receive wait (default: 80)</string>
     <string name="pref_summary_fujix_liveview_wait"> </string>
 
+    <string name="pref_fujix_command_polling_wait">Status polling wait (default: 500)</string>
+    <string name="pref_summary_fujix_command_polling_wait"> </string>
+
     <string name="pref_special_thanks">Special Thanks to</string>
 
     <string name="pref_capture_both_camera_and_live_view">Capture both camera and Live View</string>
index 116a68f..f128942 100644 (file)
             android:summary="@string/pref_summary_fujix_focus_xy" />
 
         <EditTextPreference
+            android:key="fujix_command_polling_wait"
+            android:title="@string/pref_fujix_command_polling_wait"
+            android:defaultValue="500"
+            android:summary="@string/pref_summary_fujix_command_polling_wait" />
+
+        <EditTextPreference
             android:key="fujix_liveview_wait"
             android:title="@string/pref_fujix_liveview_wait"
             android:defaultValue="80"