OSDN Git Service

FUJIFILM機のビデオ撮影機能を追加。
authorMRSa <mrsa@myad.jp>
Sat, 9 May 2020 13:20:45 +0000 (22:20 +0900)
committerMRSa <mrsa@myad.jp>
Sat, 9 May 2020 13:20:45 +0000 (22:20 +0900)
app/src/main/java/net/osdn/gokigen/gr2control/camera/fuji_x/wrapper/command/IFujiXMessages.java
app/src/main/java/net/osdn/gokigen/gr2control/camera/fuji_x/wrapper/command/messages/FinishRecordingMovie.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/gr2control/camera/fuji_x/wrapper/command/messages/StartRecordingMovie.java [new file with mode: 0644]
app/src/main/java/net/osdn/gokigen/gr2control/liveview/LiveViewFragment.java
app/src/main/java/net/osdn/gokigen/gr2control/liveview/LiveViewFujiXKeyPanelClickListener.java
app/src/main/res/drawable/ic_stop_black_24dp.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_videocam_black__24dp.xml [new file with mode: 0644]
app/src/main/res/drawable/ic_videocam_off_black_24dp.xml [new file with mode: 0644]
app/src/main/res/layout-land/fragment_live_view.xml
app/src/main/res/layout/fragment_live_view.xml

index 54c0820..185c5b6 100644 (file)
@@ -42,4 +42,7 @@ public interface IFujiXMessages
     int SEQ_IMAGE_INFO = 104;
     int SEQ_THUMBNAIL = 105;
     int SEQ_FULL_IMAGE = 106;
+
+    int SEQ_START_MOVIE = 107;
+    int SEQ_FINISH_MOVIE = 108;
 }
diff --git a/app/src/main/java/net/osdn/gokigen/gr2control/camera/fuji_x/wrapper/command/messages/FinishRecordingMovie.java b/app/src/main/java/net/osdn/gokigen/gr2control/camera/fuji_x/wrapper/command/messages/FinishRecordingMovie.java
new file mode 100644 (file)
index 0000000..08c050f
--- /dev/null
@@ -0,0 +1,55 @@
+package net.osdn.gokigen.gr2control.camera.fuji_x.wrapper.command.messages;
+
+import androidx.annotation.NonNull;
+
+import net.osdn.gokigen.gr2control.camera.fuji_x.wrapper.command.IFujiXCommandCallback;
+import net.osdn.gokigen.gr2control.camera.fuji_x.wrapper.command.IFujiXMessages;
+
+public class FinishRecordingMovie extends FujiXCommandBase
+{
+    private final IFujiXCommandCallback callback;
+    private final byte data0;
+    private final byte data1;
+    private final byte data2;
+    private final byte data3;
+
+    public FinishRecordingMovie(@NonNull IFujiXCommandCallback callback, int startSequenceNumber)
+    {
+        this.callback = callback;
+
+        data0 = ((byte) (0x000000ff & startSequenceNumber));
+        data1 = ((byte)((0x0000ff00 & startSequenceNumber) >> 8));
+        data2 = ((byte)((0x00ff0000 & startSequenceNumber) >> 16));
+        data3 = ((byte)((0xff000000 & startSequenceNumber) >> 24));
+    }
+
+    @Override
+    public IFujiXCommandCallback responseCallback()
+    {
+        return (callback);
+    }
+
+    @Override
+    public int getId()
+    {
+        return (IFujiXMessages.SEQ_FINISH_MOVIE);
+    }
+
+    @Override
+    public byte[] commandBody()
+    {
+        return (new byte[] {
+                // message_header.index : uint16 (0: terminate, 2: two_part_message, 1: other)
+                (byte)0x01, (byte)0x00,
+
+                // message_header.type : stop_recording_movie (0x9021)
+                (byte)0x21, (byte)0x90,
+
+                // sequence number
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+
+                // data...
+                data0, data1, data2, data3,
+        });
+    }
+}
diff --git a/app/src/main/java/net/osdn/gokigen/gr2control/camera/fuji_x/wrapper/command/messages/StartRecordingMovie.java b/app/src/main/java/net/osdn/gokigen/gr2control/camera/fuji_x/wrapper/command/messages/StartRecordingMovie.java
new file mode 100644 (file)
index 0000000..0cb44e2
--- /dev/null
@@ -0,0 +1,48 @@
+package net.osdn.gokigen.gr2control.camera.fuji_x.wrapper.command.messages;
+
+import androidx.annotation.NonNull;
+
+import net.osdn.gokigen.gr2control.camera.fuji_x.wrapper.command.IFujiXCommandCallback;
+import net.osdn.gokigen.gr2control.camera.fuji_x.wrapper.command.IFujiXMessages;
+
+public class StartRecordingMovie extends FujiXCommandBase
+{
+    private final IFujiXCommandCallback callback;
+
+    public StartRecordingMovie(@NonNull IFujiXCommandCallback callback)
+    {
+        this.callback = callback;
+    }
+
+    @Override
+    public IFujiXCommandCallback responseCallback()
+    {
+        return (callback);
+    }
+
+    @Override
+    public int getId()
+    {
+        return (IFujiXMessages.SEQ_START_MOVIE);
+    }
+
+    @Override
+    public byte[] commandBody()
+    {
+        return (new byte[] {
+                // message_header.index : uint16 (0: terminate, 2: two_part_message, 1: other)
+                (byte)0x01, (byte)0x00,
+
+                // message_header.type : start_movie_recording (0x9020)
+                (byte)0x20, (byte)0x90,
+
+                // sequence number
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+
+                // data
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+
+        });
+    }
+}
index f8aa972..354425a 100644 (file)
@@ -236,6 +236,7 @@ public class LiveViewFragment extends Fragment implements IStatusViewDrawer, IFo
             setFujiXKeyPanelClickListener(view, R.id.button_fuji_x_xv_plus);
             setFujiXKeyPanelClickListener(view, R.id.button_fuji_x_flash);
             setFujiXKeyPanelClickListener(view, R.id.button_fuji_x_timer);
+            setFujiXKeyPanelClickListener(view, R.id.button_fuji_x_video_on_off);
 
             connectStatus = view.findViewById(R.id.connect_disconnect_button);
             if (connectStatus != null)
index 93c9c9d..e234f3f 100644 (file)
@@ -4,10 +4,12 @@ import android.content.DialogInterface;
 import android.os.Vibrator;
 import android.util.Log;
 import android.view.View;
+import android.widget.ImageView;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.appcompat.app.AlertDialog;
+import androidx.core.content.ContextCompat;
 import androidx.fragment.app.FragmentActivity;
 
 import net.osdn.gokigen.gr2control.R;
@@ -16,7 +18,9 @@ import net.osdn.gokigen.gr2control.camera.IInterfaceProvider;
 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.CommandGeneric;
+import net.osdn.gokigen.gr2control.camera.fuji_x.wrapper.command.messages.FinishRecordingMovie;
 import net.osdn.gokigen.gr2control.camera.fuji_x.wrapper.command.messages.IFujiXCameraCommands;
+import net.osdn.gokigen.gr2control.camera.fuji_x.wrapper.command.messages.StartRecordingMovie;
 import net.osdn.gokigen.gr2control.camera.utils.SimpleLogDumper;
 
 import java.util.List;
@@ -28,6 +32,9 @@ public class LiveViewFujiXKeyPanelClickListener implements View.OnClickListener,
     private static final boolean isDumpLog = false;
     private final IInterfaceProvider interfaceProvider;
     private final Vibrator vibrator;
+    private boolean isRecordingVideoMovie = false;
+    private boolean commandIssued = false;
+    private int startMovieSequenceNumber = 0;
 
     LiveViewFujiXKeyPanelClickListener(@NonNull FragmentActivity activity, @NonNull IInterfaceProvider interfaceProvider, @Nullable Vibrator vibrator)
     {
@@ -71,7 +78,9 @@ public class LiveViewFujiXKeyPanelClickListener implements View.OnClickListener,
                     updateSelection(ICameraStatus.SELF_TIMER);
                     isVibrate = false;
                     break;
-
+                case R.id.button_fuji_x_video_on_off:
+                    startFinishMovie();
+                    break;
                 default:
                     isVibrate = false;
                     break;
@@ -196,6 +205,120 @@ public class LiveViewFujiXKeyPanelClickListener implements View.OnClickListener,
     }
 
     /**
+     *   ビデオ撮影開始と終了
+     *
+     */
+    private void startFinishMovie()
+    {
+        try
+        {
+            if (commandIssued)
+            {
+                // すでにコマンド発行中。コマンドの発行は抑止する
+                Log.v(TAG, " COMMAND IS ALREADY ISSUED...");
+                return;
+            }
+            commandIssued = true;
+
+            IFujiXCommandPublisher publisher = interfaceProvider.getFujiXInterfaceProvider().getCommandPublisher();
+            if (isRecordingVideoMovie)
+            {
+                // 撮影中の場合には、撮影を止める
+                publisher.enqueueCommand(new FinishRecordingMovie(new IFujiXCommandCallback() {
+                    @Override
+                    public void receivedMessage(int id, byte[] rx_body)
+                    {
+                        commandIssued = false;
+                        isRecordingVideoMovie = false;
+                        updateMovieRecordingIcon();
+                        SimpleLogDumper.dump_bytes(" STOP MOVIE REPLY (" + startMovieSequenceNumber + ") ", rx_body);
+                        startMovieSequenceNumber = 0;
+                    }
+
+                    @Override
+                    public void onReceiveProgress(int currentBytes, int totalBytes, byte[] rx_body)
+                    {
+                        // 何もしない
+                    }
+
+                    @Override
+                    public boolean isReceiveMulti()
+                    {
+                        return (false);
+                    }
+                }, startMovieSequenceNumber));
+            }
+            else
+            {
+                // 撮影を開始する
+                publisher.enqueueCommand(new StartRecordingMovie(new IFujiXCommandCallback() {
+                    @Override
+                    public void receivedMessage(int id, byte[] rx_body)
+                    {
+                        commandIssued = false;
+                        if ((rx_body[7] == (byte) 0x20)&&(rx_body[6] == (byte) 0x01))
+                        {
+                            // 応答コード OKの場合... SequenceNumberを記憶する
+                            startMovieSequenceNumber = ((((int) rx_body[11]) & 0xff) << 24) + ((((int) rx_body[10]) & 0xff) << 16) + ((((int) rx_body[9]) & 0xff) << 8) + (((int) rx_body[8]) & 0xff);
+                            isRecordingVideoMovie = true;
+                        }
+                        updateMovieRecordingIcon();
+                        SimpleLogDumper.dump_bytes(" START MOVIE REPLY (" + startMovieSequenceNumber + ") ", rx_body);
+                    }
+
+                    @Override
+                    public void onReceiveProgress(int currentBytes, int totalBytes, byte[] rx_body)
+                    {
+                        // 何もしない
+                    }
+
+                    @Override
+                    public boolean isReceiveMulti()
+                    {
+                        return (false);
+                    }
+                }));
+            }
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+            commandIssued = false;
+        }
+    }
+
+    private void updateMovieRecordingIcon()
+    {
+        try
+        {
+            activity.runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    ImageView imageView = activity.findViewById(R.id.button_fuji_x_video_on_off);
+                    if (isRecordingVideoMovie)
+                    {
+                        //imageView.setImageDrawable(ContextCompat.getDrawable(activity,R.drawable.ic_videocam_off_black_24dp));
+                        imageView.setImageDrawable(ContextCompat.getDrawable(activity,R.drawable.ic_stop_black_24dp));
+                    }
+                    else
+                    {
+                        imageView.setImageDrawable(ContextCompat.getDrawable(activity,R.drawable.ic_videocam_black__24dp));
+                    }
+                    imageView.invalidate();
+                }
+            });
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+
+
+
+
+    /**
      *   ぶるぶるさせる
      *
      */
diff --git a/app/src/main/res/drawable/ic_stop_black_24dp.xml b/app/src/main/res/drawable/ic_stop_black_24dp.xml
new file mode 100644 (file)
index 0000000..c428d72
--- /dev/null
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M6,6h12v12H6z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_videocam_black__24dp.xml b/app/src/main/res/drawable/ic_videocam_black__24dp.xml
new file mode 100644 (file)
index 0000000..ea656cc
--- /dev/null
@@ -0,0 +1,5 @@
+<vector android:height="24dp" android:tint="#121212"
+    android:viewportHeight="24.0" android:viewportWidth="24.0"
+    android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="#FF000000" android:pathData="M17,10.5V7c0,-0.55 -0.45,-1 -1,-1H4c-0.55,0 -1,0.45 -1,1v10c0,0.55 0.45,1 1,1h12c0.55,0 1,-0.45 1,-1v-3.5l4,4v-11l-4,4z"/>
+</vector>
diff --git a/app/src/main/res/drawable/ic_videocam_off_black_24dp.xml b/app/src/main/res/drawable/ic_videocam_off_black_24dp.xml
new file mode 100644 (file)
index 0000000..b7d0b1b
--- /dev/null
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M21,6.5l-4,4V7c0,-0.55 -0.45,-1 -1,-1H9.82L21,17.18V6.5zM3.27,2L2,3.27 4.73,6H4c-0.55,0 -1,0.45 -1,1v10c0,0.55 0.45,1 1,1h12c0.21,0 0.39,-0.08 0.54,-0.18L19.73,21 21,19.73 3.27,2z"/>
+</vector>
index c8f15f7..ceabf2c 100644 (file)
             android:gravity="center" />
 
         <ImageView
-            android:id="@+id/button_fuji_x_dummy"
-            android:layout_width="34pt"
-            android:layout_height="9pt"
-            android:layout_below="@id/label_fuji_x_xv_center"
-            android:layout_alignLeft="@id/label_fuji_x_xv_center"
-            android:layout_alignStart="@id/label_fuji_x_xv_center"
+            android:id="@+id/button_fuji_x_video_on_off"
+            android:layout_width="20pt"
+            android:layout_height="14pt"
+            android:layout_below="@id/button_fuji_x_xv_minus"
+            android:layout_alignLeft="@id/button_fuji_x_xv_minus"
+            android:layout_alignStart="@id/button_fuji_x_xv_minus"
             android:scaleType="fitCenter"
-            android:visibility="invisible"
+            android:visibility="visible"
             android:clickable="true"
             android:focusable="true"
-            android:src="@drawable/ic_camera_roll_black_24dp"
+            android:src="@drawable/ic_videocam_black__24dp"
             android:layout_marginTop="6pt"
             android:gravity="center" />
 
             android:id="@+id/button_fuji_x_flash"
             android:layout_width="20pt"
             android:layout_height="14pt"
-            android:layout_below="@id/button_fuji_x_dummy"
+            android:layout_below="@id/button_fuji_x_video_on_off"
             android:layout_alignLeft="@id/button_fuji_x_tv_minus"
             android:layout_alignStart="@id/button_fuji_x_tv_minus"
             android:scaleType="fitCenter"
             android:id="@+id/button_fuji_x_timer"
             android:layout_width="34pt"
             android:layout_height="14pt"
-            android:layout_below="@id/button_fuji_x_dummy"
-            android:layout_alignLeft="@id/button_fuji_x_dummy"
-            android:layout_alignStart="@id/button_fuji_x_dummy"
+            android:layout_below="@id/button_fuji_x_video_on_off"
+            android:layout_alignLeft="@id/label_fuji_x_xv_center"
+            android:layout_alignStart="@id/label_fuji_x_xv_center"
             android:scaleType="fitCenter"
             android:visibility="visible"
             android:clickable="true"
index 14ab6a9..07f8275 100644 (file)
             android:gravity="center" />
 
         <ImageView
-            android:id="@+id/button_fuji_x_dummy"
-            android:layout_width="34pt"
-            android:layout_height="9pt"
-            android:layout_below="@id/label_fuji_x_xv_center"
-            android:layout_alignLeft="@id/label_fuji_x_xv_center"
-            android:layout_alignStart="@id/label_fuji_x_xv_center"
+            android:id="@+id/button_fuji_x_video_on_off"
+            android:layout_width="20pt"
+            android:layout_height="14pt"
+            android:layout_below="@id/button_fuji_x_xv_minus"
+            android:layout_alignLeft="@id/button_fuji_x_xv_minus"
+            android:layout_alignStart="@id/button_fuji_x_xv_minus"
             android:scaleType="fitCenter"
-            android:visibility="invisible"
+            android:visibility="visible"
             android:clickable="true"
             android:focusable="true"
-            android:src="@drawable/ic_camera_roll_black_24dp"
+            android:src="@drawable/ic_videocam_black__24dp"
             android:layout_marginTop="6pt"
             android:gravity="center" />
 
             android:id="@+id/button_fuji_x_flash"
             android:layout_width="20pt"
             android:layout_height="14pt"
-            android:layout_below="@id/button_fuji_x_dummy"
+            android:layout_below="@id/button_fuji_x_video_on_off"
             android:layout_alignLeft="@id/button_fuji_x_tv_minus"
             android:layout_alignStart="@id/button_fuji_x_tv_minus"
             android:scaleType="fitCenter"
             android:id="@+id/button_fuji_x_timer"
             android:layout_width="34pt"
             android:layout_height="14pt"
-            android:layout_below="@id/button_fuji_x_dummy"
-            android:layout_alignLeft="@id/button_fuji_x_dummy"
-            android:layout_alignStart="@id/button_fuji_x_dummy"
+            android:layout_below="@id/button_fuji_x_video_on_off"
+            android:layout_alignLeft="@id/label_fuji_x_xv_center"
+            android:layout_alignStart="@id/label_fuji_x_xv_center"
             android:scaleType="fitCenter"
             android:visibility="visible"
             android:clickable="true"