--- /dev/null
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+.externalNativeBuild
--- /dev/null
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 26
+ buildToolsVersion "26.0.1"
+ defaultConfig {
+ applicationId "net.osdn.gokigen.a01d"
+ minSdkVersion 14
+ targetSdkVersion 26
+ versionCode 100
+ versionName "1.0.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ compile 'com.android.support:appcompat-v7:26.+'
+ compile 'com.android.support.constraint:constraint-layout:1.0.2'
+ compile 'com.android.support:preference-v14:26.+'
+ //provided 'com.google.android.things:androidthings:0.4.1-devpreview'
+ compile 'com.android.support:preference-v7:26.+'
+ compile 'com.android.support:exifinterface:26.+'
+ compile files('libs/olycamerakit.jar')
+}
--- /dev/null
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in C:\APL\Android\sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="net.osdn.gokigen.a01d">
+
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
+ <uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+ <uses-permission android:name="android.permission.CAMERA" />
+
+ <uses-feature android:name="android.hardware.camera" />
+ <uses-feature android:name="android.hardware.camera.autofocus" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:roundIcon="@mipmap/ic_launcher_round"
+ android:supportsRtl="true"
+ android:theme="@style/AppTheme">
+ <activity android:name=".A01dMain">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ <meta-data android:name="android.max_aspect" android:value="ratio_float"/>
+ </application>
+</manifest>
+
--- /dev/null
+package net.osdn.gokigen.a01d;
+
+import android.Manifest;
+import android.content.pm.PackageManager;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.view.WindowManager;
+
+import net.osdn.gokigen.a01d.camera.olympus.IOlympusInterfaceProvider;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.OlympusInterfaceProvider;
+import net.osdn.gokigen.a01d.liveview.LiveViewFragment;
+import net.osdn.gokigen.a01d.preference.PreferenceFragment;
+
+/**
+ *
+ *
+ */
+public class A01dMain extends AppCompatActivity implements IChangeScene
+{
+ private IOlympusInterfaceProvider interfaceProvider = null;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ final int REQUEST_NEED_PERMISSIONS = 1010;
+
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_a01d_main);
+
+ ActionBar bar = getSupportActionBar();
+ if (bar != null)
+ {
+ // タイトルバーは表示しない
+ bar.hide();
+ }
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+ // 外部メモリアクセス権のオプトイン
+ if ((ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)||
+ (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED)||
+ (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_WIFI_STATE) != PackageManager.PERMISSION_GRANTED)||
+ (ContextCompat.checkSelfPermission(this, Manifest.permission.INTERNET) != PackageManager.PERMISSION_GRANTED))
+ {
+ ActivityCompat.requestPermissions(this,
+ new String[]{
+ Manifest.permission.WRITE_EXTERNAL_STORAGE,
+ Manifest.permission.ACCESS_NETWORK_STATE,
+ Manifest.permission.ACCESS_WIFI_STATE,
+ Manifest.permission.INTERNET,
+ },
+ REQUEST_NEED_PERMISSIONS);
+ }
+ initializeClass();
+ initializeFragment();
+ onReadyClass();
+ }
+
+ /**
+ * クラスの初期化
+ *
+ */
+ private void initializeClass()
+ {
+ try
+ {
+ interfaceProvider = new OlympusInterfaceProvider();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 初期化終了時の処理
+ *
+ */
+ private void onReadyClass()
+ {
+
+
+ }
+
+ /**
+ * フラグメントの初期化
+ *
+ */
+ private void initializeFragment()
+ {
+ LiveViewFragment fragment = new LiveViewFragment();
+ fragment.prepare(this);
+ fragment.setRetainInstance(true);
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ transaction.replace(R.id.fragment1, fragment);
+ transaction.commitAllowingStateLoss();
+ }
+
+ /**
+ * カメラのプロパティ一覧画面を開く
+ * (カメラと接続中のときのみ)
+ *
+ */
+ @Override
+ public void changeSceneToCameraPropertyList()
+ {
+
+ }
+
+ /**
+ * 設定画面を開く
+ *
+ */
+ @Override
+ public void changeSceneToConfiguration()
+ {
+ PreferenceFragment fragment = new PreferenceFragment();
+ fragment.setInterface(this, interfaceProvider, this);
+ FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
+ transaction.replace(R.id.fragment1, fragment);
+ // backstackに追加
+ transaction.addToBackStack(null);
+ transaction.commit();
+
+ }
+
+ /**
+ * カメラとの接続・切断のシーケンス
+ *
+ */
+ @Override
+ public void changeCameraConnection()
+ {
+
+ }
+
+ /**
+ * アプリを抜ける
+ *
+ */
+ @Override
+ public void exitApplication()
+ {
+
+ }
+}
--- /dev/null
+package net.osdn.gokigen.a01d;
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.support.v7.app.AlertDialog;
+
+public class ConfirmationDialog
+{
+ private final Context context;
+
+ public ConfirmationDialog(Context context)
+ {
+ this.context = context;
+ }
+
+ public void show(int titleResId, int messageResId, final Callback callback)
+ {
+ String title = "";
+ String message = "";
+
+ // タイトルとメッセージをのダイアログを表示する
+ if (context != null)
+ {
+ title = context.getString(titleResId);
+ message = context.getString(messageResId);
+ }
+ show(title, message, callback);
+ }
+
+ public void show(String title, String message, final Callback callback)
+ {
+ // 確認ダイアログの生成
+ final AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);
+ alertDialog.setTitle(title);
+ alertDialog.setIcon(android.R.drawable.ic_dialog_alert);
+ alertDialog.setMessage(message);
+ alertDialog.setCancelable(true);
+
+ // ボタンを設定する(実行ボタン)
+ alertDialog.setPositiveButton(context.getString(R.string.dialog_positive_execute),
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which)
+ {
+ callback.confirm();
+ dialog.dismiss();
+ }
+ });
+
+ // ボタンを設定する (キャンセルボタン)
+ alertDialog.setNegativeButton(context.getString(R.string.dialog_negative_cancel),
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which)
+ {
+ dialog.cancel();
+ }
+ });
+
+ // 確認ダイアログを表示する
+ alertDialog.show();
+ }
+
+ // コールバックインタフェース
+ public interface Callback
+ {
+ void confirm();
+ }
+}
--- /dev/null
+package net.osdn.gokigen.a01d;
+
+/**
+ *
+ */
+public interface IChangeScene
+{
+ void changeSceneToCameraPropertyList();
+ void changeSceneToConfiguration();
+ void changeCameraConnection();
+ void exitApplication();
+}
--- /dev/null
+package net.osdn.gokigen.a01d.camera;
+
+import net.osdn.gokigen.a01d.camera.olympus.IOlympusInterfaceProvider;
+
+/**
+ *
+ */
+public interface IInterfaceProvider
+{
+ IOlympusInterfaceProvider getOlympusInterface();
+}
--- /dev/null
+package net.osdn.gokigen.a01d.camera.olympus;
+
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.ICameraHardwareStatus;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.ICameraRunMode;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.IOlyCameraPropertyProvider;
+
+/**
+ *
+ */
+public interface IOlympusInterfaceProvider
+{
+ ICameraHardwareStatus getHardwareStatus();
+ IOlyCameraPropertyProvider getCameraPropertyProvider();
+ ICameraRunMode getCameraRunMode();
+
+}
--- /dev/null
+package net.osdn.gokigen.a01d.camera.olympus.cameraproperty;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.util.List;
+
+public class CameraPropertyArrayAdapter extends ArrayAdapter<CameraPropertyArrayItem>
+{
+ private LayoutInflater inflater = null;
+ private final int textViewResourceId;
+ private List<CameraPropertyArrayItem> listItems = null;
+
+ public CameraPropertyArrayAdapter(Context context, int textId, List<CameraPropertyArrayItem> items)
+ {
+ super(context, textId, items);
+
+ textViewResourceId = textId;
+ listItems = items;
+
+ inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ }
+
+ /**
+ *
+ */
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent)
+ {
+ View view;
+ if(convertView != null)
+ {
+ view = convertView;
+ }
+ else
+ {
+ view = inflater.inflate(textViewResourceId, null);
+ }
+
+ CameraPropertyArrayItem item = listItems.get(position);
+
+ ImageView imageView = view.findViewWithTag("icon");
+ imageView.setImageResource(item.getIconResource());
+
+ TextView titleView = view.findViewWithTag("name");
+ titleView.setText(item.getPropertyName());
+
+ TextView detailView = view.findViewWithTag("title");
+ detailView.setText(item.getPropertyTitle());
+
+ TextView optionView = view.findViewWithTag("value");
+ optionView.setText(item.getPropertyValueTitle());
+
+ return (view);
+ }
+}
--- /dev/null
+package net.osdn.gokigen.a01d.camera.olympus.cameraproperty;
+
+
+public class CameraPropertyArrayItem
+{
+ private int iconResource = 0;
+ private final String propertyName;
+ private final String propertyTitle;
+ private final String initialValue;
+ private final String initialValueTitle;
+ private final int initialIconResource;
+ private String propertyValue = "";
+ private String propertyValueTitle = "";
+
+ public CameraPropertyArrayItem(String name, String title, String valueTitle, String value, int iconId1)
+ {
+ iconResource = iconId1;
+ propertyName = name;
+ propertyTitle = title;
+ propertyValueTitle = valueTitle;
+ propertyValue = value;
+ initialValueTitle = valueTitle;
+ initialValue = value;
+ initialIconResource = iconId1;
+ }
+
+ public boolean isChanged()
+ {
+ return (!propertyValue.equals(initialValue));
+ }
+
+ public String getPropertyName()
+ {
+ return (propertyName);
+ }
+
+ public String getPropertyTitle()
+ {
+ return (propertyTitle);
+ }
+
+ public String getInitialValue()
+ {
+ return (initialValue);
+ }
+
+ public int getIconResource()
+ {
+ return (iconResource);
+ }
+
+ public void setIconResource(int iconId)
+ {
+ iconResource = iconId;
+ }
+
+ public String getPropertyValueTitle()
+ {
+ return (propertyValueTitle);
+ }
+
+ public String getPropertyValue()
+ {
+ return (propertyValue);
+ }
+
+ public void setPropertyValue(String valueTitle, String value)
+ {
+ propertyValueTitle = valueTitle;
+ propertyValue = value;
+ }
+
+ public void resetValue()
+ {
+ propertyValue = initialValue;
+ propertyValueTitle = initialValueTitle;
+ iconResource = initialIconResource;
+ }
+}
--- /dev/null
+package net.osdn.gokigen.a01d.camera.olympus.cameraproperty;
+
+
+import android.util.Log;
+
+import net.osdn.gokigen.a01d.R;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.IOlyCameraPropertyProvider;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Set;
+
+public class CameraPropertyLoader implements Runnable
+{
+ private final String TAG = toString();
+ private final IOlyCameraPropertyProvider propertyInterface;
+ private final IPropertyLoaderCallback callback;
+ private ArrayList<CameraPropertyArrayItem> propertyItems = null;
+
+ public CameraPropertyLoader(IOlyCameraPropertyProvider propertyInterface, IPropertyLoaderCallback callback)
+ {
+ this.propertyInterface = propertyInterface;
+ this.callback = callback;
+ }
+
+ @Override
+ public void run()
+ {
+ Log.v(TAG, "CameraPropertyLoader::run() START");
+
+ propertyItems = new ArrayList<>();
+
+ // カメラプロパティを設定する
+ Set<String> names = propertyInterface.getCameraPropertyNames();
+ for (String name : names)
+ {
+ String title = propertyInterface.getCameraPropertyTitle(name);
+ String value = propertyInterface.getCameraPropertyValue(name);
+ String rawValue = propertyInterface.getCameraPropertyValueTitle(value);
+ int iconId = (propertyInterface.canSetCameraProperty(name)) ? R.drawable.ic_web_asset_black_24dp : R.drawable.ic_block_black_24dp;
+
+ propertyItems.add(new CameraPropertyArrayItem(name, title, rawValue, value, iconId));
+ }
+
+ // プロパティ名でソートしてしまおう。。。
+ Collections.sort(propertyItems, new Comparator<CameraPropertyArrayItem>() {
+ public int compare(CameraPropertyArrayItem o1, CameraPropertyArrayItem o2) {
+ return o1.getPropertyName().compareTo(o2.getPropertyName());
+ }
+ });
+
+
+
+ // 終了通知
+ callback.finished();
+
+ Log.v(TAG, "CameraPropertyLoader::run() END");
+ }
+
+ public void resetProperty()
+ {
+ Log.v(TAG, "CameraPropertyLoader::resetProperty() START");
+
+ for (CameraPropertyArrayItem item : propertyItems)
+ {
+ item.resetValue();
+ }
+ callback.resetProperty();
+ Log.v(TAG, "CameraPropertyLoader::resetProperty() END");
+
+ }
+
+ /**
+ * プロパティ一覧を応答
+ *
+ */
+ public ArrayList<CameraPropertyArrayItem> getItemList()
+ {
+ return (propertyItems);
+ }
+
+ public interface IPropertyLoaderCallback
+ {
+ void finished();
+ void resetProperty();
+ }
+}
--- /dev/null
+package net.osdn.gokigen.a01d.camera.olympus.cameraproperty;
+
+
+import android.content.Context;
+import android.util.Log;
+import android.view.View;
+
+import net.osdn.gokigen.a01d.ConfirmationDialog;
+import net.osdn.gokigen.a01d.R;
+
+public class CameraPropertyOperator implements View.OnClickListener
+{
+ private final String TAG = toString();
+
+ private final Context context;
+ private final CameraPropertyLoader loader;
+
+
+ public CameraPropertyOperator(Context context, CameraPropertyLoader loader)
+ {
+ this.context = context;
+ this.loader = loader;
+ }
+
+ @Override
+ public void onClick(View view)
+ {
+ int id = view.getId();
+ Log.v(TAG, "onClick() : " + id);
+ switch (id)
+ {
+ case R.id.propertySettings_restore:
+ processRestoreCameraProperty();
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ private void processRestoreCameraProperty()
+ {
+ try
+ {
+ final ConfirmationDialog dialog = new ConfirmationDialog(context);
+ dialog.show(R.string.dialog_title_confirmation,
+ R.string.dialog_message_restore_camera_property,
+ new ConfirmationDialog.Callback() {
+ @Override
+ public void confirm()
+ {
+ loader.resetProperty();
+ }
+ });
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+}
--- /dev/null
+package net.osdn.gokigen.a01d.camera.olympus.cameraproperty;
+
+
+
+import android.content.Context;
+import android.content.DialogInterface;
+import android.support.v7.app.AlertDialog;
+import android.util.Log;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListView;
+
+import net.osdn.gokigen.a01d.R;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.IOlyCameraPropertyProvider;
+
+import java.util.List;
+
+public class CameraPropertyValueSelector implements ListView.OnItemClickListener, ListView.OnLongClickListener, DialogInterface.OnClickListener
+{
+ private final String TAG = toString();
+ private final Context context;
+ private final IOlyCameraPropertyProvider propertyInterface;
+ private final ICametaPropertyUpdateNotify updater;
+
+ private List<String> valueList = null;
+ private CameraPropertyArrayItem item = null;
+
+ /**
+ * 選択されたアイテムの更新を行う
+ *
+ *
+ */
+ public CameraPropertyValueSelector(Context context, IOlyCameraPropertyProvider propertyInterface, ICametaPropertyUpdateNotify updater)
+ {
+ this.context = context;
+ this.propertyInterface = propertyInterface;
+ this.updater = updater;
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> adapterView, View view, int i, long l)
+ {
+ Log.v(TAG, "onItemClick() : " + i);
+ CameraPropertyArrayAdapter arrayAdapter = (CameraPropertyArrayAdapter) adapterView.getAdapter();
+ item = arrayAdapter.getItem(i);
+ //item = (CameraPropertyArrayItem) listView.getSelectedItem();
+ if ((item == null)||(propertyInterface == null))
+ {
+ Log.i(TAG, "----- selectedItem is NULL. -----");
+ return;
+ }
+
+ String propertyName = item.getPropertyName();
+ String propertyValue = propertyInterface.getCameraPropertyValue(propertyName);
+ Log.v(TAG, "TARGET PROPERTY : " + propertyName + " " + propertyValue);
+
+ valueList = propertyInterface.getCameraPropertyValueList(propertyName);
+ if ((valueList == null)||(valueList.size() == 0))
+ {
+ Log.v(TAG, "Value List is NULL : " + item.getPropertyName() + " " + propertyValue);
+ return;
+ }
+ String[] items;
+ if (item.getIconResource() == R.drawable.ic_block_black_24dp)
+ {
+ // Read only, 値の変更はできない
+ items = new String[1];
+ items[0] = propertyInterface.getCameraPropertyValueTitle(propertyValue);
+ }
+ else
+ {
+ // 設定可能な選択肢を一覧表示する
+ items = new String[valueList.size()];
+ for (int index = 0; index < valueList.size(); index++)
+ {
+ String propValue = valueList.get(index);
+ if (propValue.equals(item.getInitialValue()))
+ {
+ Log.v(TAG, "INIT: " + propValue);
+
+ // 初期値には、(*) マークを表示したい
+ items[index] = propertyInterface.getCameraPropertyValueTitle(propValue) + " (*)";
+ }
+ else
+ {
+ items[index] = propertyInterface.getCameraPropertyValueTitle(propValue);
+ }
+ }
+ }
+ AlertDialog.Builder builder = new AlertDialog.Builder(context);
+ builder.setSingleChoiceItems(items, valueList.indexOf(item.getPropertyValue()), this);
+ builder.setCancelable(true);
+ builder.show();
+ }
+
+ @Override
+ public boolean onLongClick(View view)
+ {
+ return (false);
+ }
+
+ @Override
+ public void onClick(DialogInterface dialogInterface, int which)
+ {
+ dialogInterface.dismiss();
+ if (propertyInterface == null)
+ {
+ Log.i(TAG, "----- PROPERTY CHANGE INTERFACE IS NULL -----");
+ return;
+ }
+
+ String propertyValue = valueList.get(which);
+ String rawValue = propertyInterface.getCameraPropertyValueTitle(propertyValue);
+
+ // パラメータ設定 (アイテムを個別に設定する場合は有効に...)
+ //propertyInterface.setCameraPropertyValue(propertyName, propertyValue);
+
+ if (item.getIconResource() == R.drawable.ic_block_black_24dp)
+ {
+ // Read Only パラメータは設定しない。
+ return;
+ }
+
+ item.setPropertyValue(rawValue, propertyValue);
+ String initialValue = item.getInitialValue();
+ if (!initialValue.equals(propertyValue))
+ {
+ // 値を変更したマークにする
+ item.setIconResource(R.drawable.ic_mode_edit_black_24dp);
+ }
+ else
+ {
+ // デフォルト値なので、アイコンを初期アイコンに戻す
+ item.setIconResource(R.drawable.ic_web_asset_black_24dp);
+ }
+ if (updater != null)
+ {
+ updater.onCameraPropertyUpdate(which);
+ }
+ }
+}
--- /dev/null
+package net.osdn.gokigen.a01d.camera.olympus.cameraproperty;
+
+
+public interface ICametaPropertyUpdateNotify
+{
+ void onCameraPropertyUpdate(int which);
+}
--- /dev/null
+package net.osdn.gokigen.a01d.camera.olympus.cameraproperty;
+
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+
+import java.util.HashMap;
+
+import net.osdn.gokigen.a01d.R;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.IOlyCameraPropertyProvider;
+
+public class OlyCameraPropertyListFragment extends Fragment implements CameraPropertyLoader.IPropertyLoaderCallback
+{
+ private final String TAG = toString();
+ private IOlyCameraPropertyProvider propertyInterface = null;
+
+ private CameraPropertyLoader propertyLoader = null;
+ private CameraPropertyOperator propertyOperator = null;
+ private ProgressDialog busyDialog = null;
+ private ListView listView = null;
+
+ /**
+ * カメラプロパティをやり取りするインタフェースを生成する
+ *
+ */
+ public void setInterface(Context context, IOlyCameraPropertyProvider propertyInterface)
+ {
+ Log.v(TAG, "setInterface()");
+ this.propertyInterface = propertyInterface;
+ if (propertyLoader == null)
+ {
+ propertyLoader = new CameraPropertyLoader(propertyInterface, this);
+ }
+ if (propertyOperator == null)
+ {
+ propertyOperator = new CameraPropertyOperator(context, propertyLoader);
+ }
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ Log.v(TAG, "onCreate()");
+
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public void onAttach(Context context)
+ {
+ super.onAttach(context);
+ Log.v(TAG, "onAttach()");
+ }
+ /**
+ *
+ *
+ */
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
+ {
+ Log.v(TAG, "onCreateView()");
+
+ View view = inflater.inflate(R.layout.fragmant_camera_property, container, false);
+ setHasOptionsMenu(true);
+
+ listView = view.findViewById(R.id.CameraPropertyListView);
+
+ ImageView restore_properties = view.findViewById(R.id.propertySettings_restore);
+ restore_properties.setOnClickListener(propertyOperator);
+
+ return (view);
+ }
+
+ /**
+ *
+ */
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
+ {
+ AppCompatActivity activity = (AppCompatActivity)getActivity();
+ ActionBar bar = activity.getSupportActionBar();
+ if (bar != null)
+ {
+ bar.setTitle(getString(R.string.app_name));
+ }
+ }
+
+ /**
+ *
+ *
+ *
+ */
+ @Override
+ public void onStart()
+ {
+ super.onStart();
+ Log.v(TAG, "onStart()");
+
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public void onResume()
+ {
+ super.onResume();
+ Log.v(TAG, "onResume() Start");
+
+ loadCameraPropertyItems(true);
+
+ Log.v(TAG, "onResume() End");
+ }
+ /**
+ *
+ *
+ */
+ @Override
+ public void onPause()
+ {
+ super.onPause();
+ Log.v(TAG, "onPause() Start");
+
+ try
+ {
+ commitCameraPropertyItems();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+ Log.v(TAG, "onPause() End");
+ }
+
+ private void runOnUiThread(Runnable action)
+ {
+ Activity activity = getActivity();
+ if (activity == null)
+ {
+ return;
+ }
+ activity.runOnUiThread(action);
+ }
+
+ private void loadCameraPropertyItems(boolean isPropertyLoad)
+ {
+ // 実行中ダイアログを取得する
+ busyDialog = new ProgressDialog(getActivity());
+ busyDialog.setTitle(getString(R.string.dialog_title_loading_properties));
+ busyDialog.setMessage(getString(R.string.dialog_message_loading_properties));
+ busyDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
+ busyDialog.setCancelable(false);
+ busyDialog.show();
+
+ // データ読み込み処理(別スレッドで実行)
+ if (isPropertyLoad)
+ {
+ new Thread(propertyLoader).start();
+ }
+ }
+
+ private void commitCameraPropertyItems()
+ {
+ ListAdapter adapter = listView.getAdapter();
+ int count = adapter.getCount();
+ Log.v(TAG, "----- CHANGED CAMERA PROPERTIES { -----");
+ final HashMap<String, String> propertiesToChange = new HashMap<>();
+ for (int index = 0; index < count; index++)
+ {
+ CameraPropertyArrayItem item = (CameraPropertyArrayItem) adapter.getItem(index);
+ if (item.isChanged())
+ {
+ Log.v(TAG, ">> " + item.getPropertyName() + " " + item.getPropertyValue());
+ propertiesToChange.put(item.getPropertyName(), item.getPropertyValue());
+ }
+ }
+ Log.v(TAG, "----- } CHANGED CAMERA PROPERTIES -----");
+ if (!propertiesToChange.isEmpty())
+ {
+ if (propertyInterface != null)
+ {
+ propertyInterface.setCameraPropertyValues(propertiesToChange);
+ }
+ else
+ {
+ Log.i(TAG, "----- PROPERTY CHANGE INTERFACE IS NULL -----");
+ }
+ }
+ }
+
+ @Override
+ public void finished()
+ {
+ runOnUiThread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ // アイテムをListに反映
+ if (listView != null)
+ {
+ final CameraPropertyArrayAdapter adapter = new CameraPropertyArrayAdapter(getContext(), R.layout.listarrayitems, propertyLoader.getItemList());
+ CameraPropertyValueSelector selector = new CameraPropertyValueSelector(getContext(), propertyInterface, new ICametaPropertyUpdateNotify() {
+ @Override
+ public void onCameraPropertyUpdate(int which)
+ {
+ Log.v(TAG, "onCameraPropertyUpdate()");
+ adapter.notifyDataSetChanged();
+ }
+ });
+ listView.setAdapter(adapter);
+ listView.setOnItemClickListener(selector);
+ listView.setOnLongClickListener(selector);
+ }
+
+ if (busyDialog != null)
+ {
+ busyDialog.dismiss();
+ busyDialog = null;
+ }
+ System.gc();
+ }
+ });
+ }
+
+ @Override
+ public void resetProperty()
+ {
+ try
+ {
+ Log.v(TAG, "resetProperty()");
+ CameraPropertyArrayAdapter adapter = (CameraPropertyArrayAdapter)listView.getAdapter();
+ adapter.notifyDataSetChanged();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+}
--- /dev/null
+package net.osdn.gokigen.a01d.camera.olympus.operation;
+
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+
+import net.osdn.gokigen.a01d.ConfirmationDialog;
+import net.osdn.gokigen.a01d.IChangeScene;
+import net.osdn.gokigen.a01d.R;
+import net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor;
+
+/**
+ * Preferenceがクリックされた時に処理するクラス
+ *
+ */
+public class CameraPowerOff implements Preference.OnPreferenceClickListener, ConfirmationDialog.Callback
+{
+ private final Context context;
+ private final IChangeScene changeScene;
+ private String preferenceKey = null;
+
+ /**
+ * コンストラクタ
+ *
+ */
+ public CameraPowerOff(Context context, IChangeScene changeScene)
+ {
+ this.context = context;
+ this.changeScene = changeScene;
+ }
+
+ /**
+ * クラスの準備
+ *
+ */
+ public void prepare()
+ {
+ // 何もしない
+ }
+
+ /**
+ *
+ *
+ * @param preference クリックしたpreference
+ * @return false : ハンドルしない / true : ハンドルした
+ */
+ @Override
+ public boolean onPreferenceClick(Preference preference)
+ {
+ if (!preference.hasKey())
+ {
+ return (false);
+ }
+
+ preferenceKey = preference.getKey();
+ if (preferenceKey.contains(IPreferencePropertyAccessor.EXIT_APPLICATION))
+ {
+
+ // 確認ダイアログの生成と表示
+ ConfirmationDialog dialog = new ConfirmationDialog(context);
+ dialog.show(R.string.dialog_title_confirmation, R.string.dialog_message_power_off, this);
+ return (true);
+ }
+ return (false);
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public void confirm()
+ {
+ if (preferenceKey.contains(IPreferencePropertyAccessor.EXIT_APPLICATION))
+ {
+ // カメラの電源をOFFにしたうえで、アプリケーションを終了する。
+ changeScene.exitApplication();
+ }
+ }
+}
--- /dev/null
+package net.osdn.gokigen.a01d.camera.olympus.wrapper;
+
+import jp.co.olympus.camerakit.OLYCamera;
+
+/**
+ * カメラプロパティに関する雑多な処理...
+ *
+ */
+public class CameraPropertyUtilities
+{
+ /**
+ * toLiveViewSize() : スクリーンサイズの文字列から、OLYCamera.LiveViewSize型へ変換する
+ *
+ * @param quality スクリーンサイズ文字列
+ * @return OLYCamera.LiveViewSize型
+ */
+ public static OLYCamera.LiveViewSize toLiveViewSizeType(String quality)
+ {
+ if (quality == null)
+ {
+ return OLYCamera.LiveViewSize.QVGA;
+ }
+ if (quality.equalsIgnoreCase("QVGA"))
+ {
+ return OLYCamera.LiveViewSize.QVGA;
+ }
+ else if (quality.equalsIgnoreCase("VGA"))
+ {
+ return OLYCamera.LiveViewSize.VGA;
+ } else if (quality.equalsIgnoreCase("SVGA"))
+ {
+ return OLYCamera.LiveViewSize.SVGA;
+ } else if (quality.equalsIgnoreCase("XGA"))
+ {
+ return OLYCamera.LiveViewSize.XGA;
+ } else if (quality.equalsIgnoreCase("QUAD_VGA"))
+ {
+ return OLYCamera.LiveViewSize.QUAD_VGA;
+ }
+ return OLYCamera.LiveViewSize.QVGA;
+ }
+
+ public static String getPropertyValue(String value)
+ {
+ if (value == null)
+ {
+ return ("");
+ }
+ String[] keyValue = OLYCamera.decodeCameraPropertyValue(value);
+ return (keyValue[1]);
+ }
+ }
--- /dev/null
+package net.osdn.gokigen.a01d.camera.olympus.wrapper;
+
+import java.util.Map;
+
+/**
+ *
+ *
+ */
+public interface ICameraHardwareStatus
+{
+ String getLensMountStatus();
+ String getMediaMountStatus();
+
+ float getMinimumFocalLength();
+ float getMaximumFocalLength();
+ float getActualFocalLength();
+
+ Map<String, Object> inquireHardwareInformation();
+}
--- /dev/null
+package net.osdn.gokigen.a01d.camera.olympus.wrapper;
+
+public interface ICameraRunMode
+{
+ /** カメラの動作モード変更 **/
+ void changeRunMode(boolean isRecording);
+ boolean isRecordingMode();
+}
--- /dev/null
+package net.osdn.gokigen.a01d.camera.olympus.wrapper;
+
+/**
+ * 使用するカメラプロパティのキー一覧
+ *
+ *
+ */
+public interface IOlyCameraProperty
+{
+ String TAKE_MODE = "TAKEMODE";
+ String SOUND_VOLUME_LEVEL = "SOUND_VOLUME_LEVEL";
+ String RAW = "RAW";
+
+ //String TAKE_MODE_MOVIE = "<TAKEMODE/movie>";
+ //String DRIVE_MODE_SINGLE = "<TAKE_DRIVE/DRIVE_NORMAL>";
+}
--- /dev/null
+package net.osdn.gokigen.a01d.camera.olympus.wrapper;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public interface IOlyCameraPropertyProvider
+{
+ // 現在利用可能なカメラプロパティ名のリスト
+ Set<String> getCameraPropertyNames();
+
+ // カメラプロパティに設定されている値を取得 : 戻りは "<WB/WB_AUTO>" な感じ
+ String getCameraPropertyValue(String name);
+
+ // カメラプロパティに設定されている値を一括取得
+ Map<String, String> getCameraPropertyValues(Set<String> names);
+
+ // カメラプロパティの名称
+ String getCameraPropertyTitle(String name);
+
+ // 設定可能なカメラプロパティ値のリストを取得する
+ List<String> getCameraPropertyValueList(String name);
+
+ // カメラプロパティの表示値
+ String getCameraPropertyValueTitle(String propertyValue);
+
+ // カメラプロパティに値を設定
+ void setCameraPropertyValue (String name, String value);
+
+ // カメラプロパティに値を一括設定
+ void setCameraPropertyValues(Map<String, String> values);
+
+ // カメラプロパティに値を設定できるかを検査
+ boolean canSetCameraProperty(String name);
+}
--- /dev/null
+package net.osdn.gokigen.a01d.camera.olympus.wrapper;
+
+import net.osdn.gokigen.a01d.camera.olympus.IOlympusInterfaceProvider;
+
+
+/**
+ *
+ *
+ */
+public class OlympusInterfaceProvider implements IOlympusInterfaceProvider
+{
+ public OlympusInterfaceProvider()
+ {
+
+ }
+
+ @Override
+ public ICameraHardwareStatus getHardwareStatus()
+ {
+ return null;
+ }
+
+ @Override
+ public IOlyCameraPropertyProvider getCameraPropertyProvider()
+ {
+ return null;
+ }
+
+ @Override
+ public ICameraRunMode getCameraRunMode()
+ {
+ return null;
+ }
+}
--- /dev/null
+package net.osdn.gokigen.a01d.camera.olympus.wrapper.connection;
+
+import android.content.Context;
+import android.util.Log;
+
+import net.osdn.gokigen.a01d.R;
+
+import jp.co.olympus.camerakit.OLYCamera;
+import jp.co.olympus.camerakit.OLYCameraKitException;
+
+/**
+ * Olympusカメラとの接続処理
+ *
+ */
+class CameraConnectSequence implements Runnable
+{
+ private final String TAG = this.toString();
+ private final Context context;
+ private final OLYCamera camera;
+ private final ICameraStatusReceiver cameraStatusReceiver;
+
+ /**
+ * コンストラクタ
+ */
+ CameraConnectSequence(Context context, OLYCamera camera, ICameraStatusReceiver statusReceiver)
+ {
+ Log.v(TAG, "CameraConnectSequence");
+ this.context = context;
+ this.camera =camera;
+ this.cameraStatusReceiver = statusReceiver;
+ }
+
+ /**
+ * カメラとの接続実処理
+ *
+ */
+ @Override
+ public void run()
+ {
+ String statusMessage = context.getString(R.string.connect_start);
+ try
+ {
+ statusMessage = context.getString(R.string.connect_check_wifi);
+ cameraStatusReceiver.onStatusNotify(statusMessage);
+ camera.connect(OLYCamera.ConnectionType.WiFi);
+
+ // ライブビューの自動スタート設定の場合、自動スタートをやめる
+ if (camera.isAutoStartLiveView())
+ {
+ camera.setAutoStartLiveView(false);
+ }
+
+ // 一度カメラの動作モードを確認する
+ OLYCamera.RunMode runMode = camera.getRunMode();
+ if (runMode == OLYCamera.RunMode.Unknown)
+ {
+ // UNKNOWNモードは動作しない、メッセージを作って応答する
+ statusMessage = context.getString(R.string.fatal_cannot_use_camera);
+ cameraStatusReceiver.onCameraOccursException(statusMessage, new IllegalStateException(context.getString(R.string.camera_reset_required)));
+ Log.w(TAG, "DETECT : OLYCamera.RunMode.Unknown");
+ }
+ if (runMode != OLYCamera.RunMode.Recording)
+ {
+ // Recordingモードでない場合は切り替える
+ statusMessage = context.getString(R.string.connect_change_run_mode);
+ cameraStatusReceiver.onStatusNotify(statusMessage);
+ camera.changeRunMode(OLYCamera.RunMode.Recording);
+ }
+ }
+ catch (OLYCameraKitException e)
+ {
+ cameraStatusReceiver.onCameraOccursException(statusMessage, e);
+ e.printStackTrace();
+ return;
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ return;
+ }
+ Log.v(TAG, "CameraConnectSequence:: connected.");
+
+ // カメラとの接続確立を通知する
+ cameraStatusReceiver.onStatusNotify(context.getString(R.string.connect_connected));
+ cameraStatusReceiver.onCameraConnected();
+ }
+}
--- /dev/null
+package net.osdn.gokigen.a01d.camera.olympus.wrapper.connection;
+
+import android.util.Log;
+import jp.co.olympus.camerakit.OLYCamera;
+import jp.co.olympus.camerakit.OLYCameraKitException;
+
+/**
+ * Olympusカメラとの切断処理
+ *
+ */
+class CameraDisconnectSequence implements Runnable
+{
+ private final String TAG = this.toString();
+
+ private final OLYCamera camera;
+ private final boolean powerOff;
+
+ /**
+ * コンストラクタ
+ *
+ */
+ CameraDisconnectSequence(OLYCamera camera, boolean isOff)
+ {
+ this.camera = camera;
+ this.powerOff = isOff;
+ }
+
+ @Override
+ public void run()
+ {
+ // カメラをPowerOffして接続を切る
+ try
+ {
+ camera.disconnectWithPowerOff(powerOff);
+ }
+ catch (OLYCameraKitException e)
+ {
+ // エラー情報をログに出力する
+ Log.w(TAG, "To disconnect from the camera is failed. : " + e.getLocalizedMessage());
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+}
--- /dev/null
+package net.osdn.gokigen.a01d.camera.olympus.wrapper.connection;
+
+/**
+ *
+ *
+ */
+public interface ICameraStatusReceiver
+{
+ void onStatusNotify(String message);
+ void onCameraConnected();
+ void onCameraDisconnected();
+ void onCameraOccursException(String message, Exception e);
+}
--- /dev/null
+package net.osdn.gokigen.a01d.camera.olympus.wrapper.connection;
+
+import android.content.Context;
+
+/**
+ * カメラの接続/切断
+ *
+ */
+public interface IOlyCameraConnection
+{
+ // WIFI 接続系
+ void startWatchWifiStatus(Context context);
+ void stopWatchWifiStatus(Context context);
+ boolean isWatchWifiStatus();
+
+ /** カメラ接続系 **/
+ void disconnect(final boolean powerOff);
+ void connect();
+
+}
--- /dev/null
+package net.osdn.gokigen.a01d.camera.olympus.wrapper.connection;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.os.Message;
+import android.provider.Settings;
+import android.support.v7.app.AlertDialog;
+import android.util.Log;
+
+import net.osdn.gokigen.a01d.R;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+import jp.co.olympus.camerakit.OLYCamera;
+import jp.co.olympus.camerakit.OLYCameraConnectionListener;
+import jp.co.olympus.camerakit.OLYCameraKitException;
+
+
+/**
+ * カメラの接続・切断処理クラス
+ *
+ *
+ * Created by MRSa on 2017/02/28.
+ */
+class OlyCameraConnection implements IOlyCameraConnection, OLYCameraConnectionListener
+{
+ private final String TAG = toString();
+ private final Activity context;
+ private final OLYCamera camera;
+ private final Executor cameraExecutor = Executors.newFixedThreadPool(1);
+ private final BroadcastReceiver connectionReceiver;
+ private final ICameraStatusReceiver statusReceiver;
+
+ private boolean isWatchingWifiStatus = false;
+
+ private ConnectivityManager connectivityManager;
+ //private ConnectivityManager.NetworkCallback networkCallback = null;
+
+ // Handler for dealing with network connection timeouts.
+ private Handler networkConnectionTimeoutHandler;
+
+
+ // Message to notify the network request timout handler that too much time has passed.
+ private static final int MESSAGE_CONNECTIVITY_TIMEOUT = 1;
+
+ /**
+ * コンストラクタ
+ *
+ */
+ OlyCameraConnection(final Activity context, OLYCamera camera, ICameraStatusReceiver statusReceiver)
+ {
+ Log.v(TAG, "OlyCameraConnection()");
+ this.context = context;
+ this.camera = camera;
+ connectivityManager = (ConnectivityManager) context.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+ networkConnectionTimeoutHandler = new Handler()
+ {
+ @Override
+ public void handleMessage(Message msg)
+ {
+ switch (msg.what)
+ {
+ case MESSAGE_CONNECTIVITY_TIMEOUT:
+ Log.d(TAG, "Network connection timeout");
+ alertConnectingFailed(context.getString(R.string.network_connection_timeout));
+ break;
+ }
+ }
+ };
+ this.statusReceiver = statusReceiver;
+ connectionReceiver = new BroadcastReceiver()
+ {
+ @Override
+ public void onReceive(Context context, Intent intent)
+ {
+ onReceiveBroadcastOfConnection(context, intent);
+ }
+ };
+
+ }
+
+ /**
+ * Wifiが使える状態だったら、カメラと接続して動作するよ
+ *
+ */
+ private void onReceiveBroadcastOfConnection(Context context, Intent intent)
+ {
+ statusReceiver.onStatusNotify(context.getString(R.string.connect_check_wifi));
+ Log.v(TAG,context.getString(R.string.connect_check_wifi));
+
+ String action = intent.getAction();
+ if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION))
+ {
+ WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+ WifiInfo info = wifiManager.getConnectionInfo();
+ if (wifiManager.isWifiEnabled() && info != null && info.getNetworkId() != -1)
+ {
+ // カメラとの接続処理を行う
+ connectToCamera();
+ }
+ }
+ }
+
+ /**
+ * Wifi接続状態の監視
+ * (接続の実処理は onReceiveBroadcastOfConnection() で実施)
+ */
+ @Override
+ public void startWatchWifiStatus(Context context)
+ {
+ Log.v(TAG, "startWatchWifiStatus()");
+ statusReceiver.onStatusNotify("prepare");
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+ filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+ context.registerReceiver(connectionReceiver, filter);
+ isWatchingWifiStatus = true;
+ }
+
+ /**
+ * Wifi接続状態の監視終了
+ */
+ @Override
+ public void stopWatchWifiStatus(Context context)
+ {
+ Log.v(TAG, "stopWatchWifiStatus()");
+ context.unregisterReceiver(connectionReceiver);
+ isWatchingWifiStatus = false;
+ disconnect(false);
+ }
+
+ /**
+ * Wifi接続状態の監視処理を行っているかどうか
+ *
+ * @return true : 監視中 / false : 停止中
+ */
+ @Override
+ public boolean isWatchWifiStatus() {
+ return (isWatchingWifiStatus);
+ }
+
+ /**
+ * カメラとの接続を解除する
+ *
+ * @param powerOff 真ならカメラの電源オフを伴う
+ */
+ @Override
+ public void disconnect(final boolean powerOff)
+ {
+ Log.v(TAG, "disconnect()");
+ disconnectFromCamera(powerOff);
+ statusReceiver.onCameraDisconnected();
+ }
+
+ /**
+ * カメラとの再接続を指示する
+ */
+ @Override
+ public void connect() {
+ connectToCamera();
+ }
+
+ /**
+ * カメラの通信状態変化を監視するためのインターフェース
+ *
+ * @param camera 例外が発生した OLYCamera
+ * @param e カメラクラスの例外
+ */
+ @Override
+ public void onDisconnectedByError(OLYCamera camera, OLYCameraKitException e)
+ {
+ // カメラが切れた時に通知する
+ statusReceiver.onCameraDisconnected();
+ }
+
+ /**
+ * カメラとの切断処理
+ */
+ private void disconnectFromCamera(final boolean powerOff)
+ {
+ Log.v(TAG, "disconnectFromCamera()");
+ try
+ {
+ cameraExecutor.execute(new CameraDisconnectSequence(camera, powerOff));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * カメラとの接続処理
+ */
+ private void connectToCamera()
+ {
+ Log.v(TAG, "connectToCamera()");
+ try
+ {
+ cameraExecutor.execute(new CameraConnectSequence(context, camera, statusReceiver));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+ /**
+ * 接続リトライのダイアログを出す
+ *
+ * @param message 表示用のメッセージ
+ */
+ private void alertConnectingFailed(String message)
+ {
+ final AlertDialog.Builder builder = new AlertDialog.Builder(context)
+ .setTitle(context.getString(R.string.dialog_title_connect_failed))
+ .setMessage(message)
+ .setPositiveButton(context.getString(R.string.dialog_title_button_retry), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which)
+ {
+ connect();
+ }
+ })
+ .setNeutralButton(R.string.dialog_title_button_network_settings, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which)
+ {
+ try
+ {
+ // Wifi 設定画面を表示する
+ context.startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
+ }
+ catch (android.content.ActivityNotFoundException ex)
+ {
+ // Activity が存在しなかった...設定画面が起動できなかった
+ Log.v(TAG, "android.content.ActivityNotFoundException...");
+
+ // この場合は、再試行と等価な動きとする
+ connect();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+ });
+ context.runOnUiThread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ builder.show();
+ }
+ });
+ }
+}
--- /dev/null
+package net.osdn.gokigen.a01d.liveview;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.media.ExifInterface;
+import android.os.Looper;
+import android.preference.PreferenceManager;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.ImageView;
+
+import net.osdn.gokigen.a01d.R;
+import net.osdn.gokigen.a01d.liveview.bitmapconvert.IPreviewImageConverter;
+import net.osdn.gokigen.a01d.liveview.bitmapconvert.ImageConvertFactory;
+import net.osdn.gokigen.a01d.liveview.gridframe.GridFrameFactory;
+import net.osdn.gokigen.a01d.liveview.gridframe.IGridFrameDrawer;
+import net.osdn.gokigen.a01d.liveview.message.IMessageDrawer;
+import net.osdn.gokigen.a01d.liveview.message.IMessageHolder;
+import net.osdn.gokigen.a01d.liveview.message.ShowMessageHolder;
+import net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor;
+
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import jp.co.olympus.camerakit.OLYCamera;
+
+/**
+ * CameraLiveImageView :
+ * (OLYMPUS の ImageCaptureSample そのまま)
+ *
+ */
+public class CameraLiveImageView extends View implements CameraLiveViewListenerImpl.IImageDataReceiver, IAutoFocusFrameDisplay, ILiveImageStatusNotify
+{
+ private final String TAG = this.toString();
+
+ private static final String EXIF_ORIENTATION = "Orientation";
+
+ private boolean focusAssistFeature = false;
+ private boolean showGridFeature = false;
+ private ImageView.ScaleType imageScaleType;
+ private Bitmap imageBitmap;
+ private int imageRotationDegrees;
+ private boolean showingFocusFrame = false;
+ private IAutoFocusFrameDisplay.FocusFrameStatus focusFrameStatus;
+ private RectF focusFrameRect;
+ private Timer focusFrameHideTimer;
+
+ private IGridFrameDrawer gridFrameDrawer = null;
+ private IPreviewImageConverter bitmapConverter = null;
+ private IMessageHolder messageHolder;
+
+ public CameraLiveImageView(Context context)
+ {
+ super(context);
+ initComponent(context);
+ }
+
+ public CameraLiveImageView(Context context, AttributeSet attrs)
+ {
+ super(context, attrs);
+ initComponent(context);
+ }
+
+ public CameraLiveImageView(Context context, AttributeSet attrs, int defStyleAttr)
+ {
+ super(context, attrs, defStyleAttr);
+ initComponent(context);
+ }
+
+ private void initComponent(Context context)
+ {
+ messageHolder = new ShowMessageHolder();
+ imageScaleType = ImageView.ScaleType.FIT_CENTER;
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
+
+ // Gridの表示/非表示
+ int framingGridStatus = 0;
+ gridFrameDrawer = GridFrameFactory.getGridFrameDrawer(framingGridStatus);
+ showGridFeature = preferences.getBoolean(IPreferencePropertyAccessor.SHOW_GRID_STATUS, false);
+
+ int converterType = 0;
+ bitmapConverter = ImageConvertFactory.getImageConverter(converterType);
+
+ // ダミーのビットマップデータ読み込み...画面表示のテスト用ロジック
+ try
+ {
+ imageBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.a01d_default);
+ }
+ catch (Throwable t)
+ {
+ t.printStackTrace();
+ imageBitmap = null;
+ }
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ }
+
+ @Override
+ protected void onDetachedFromWindow()
+ {
+ super.onDetachedFromWindow();
+
+ imageBitmap = null;
+ if (focusFrameHideTimer != null)
+ {
+ focusFrameHideTimer.cancel();
+ focusFrameHideTimer = null;
+ }
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas)
+ {
+ super.onDraw(canvas);
+ drawCanvas(canvas);
+
+ // メッセージの表示 (Overwrite)
+ drawInformationMessages(canvas);
+
+ // レベルゲージの表示
+ if (messageHolder.isLevel())
+ {
+ drawLevelGauge(canvas);
+ }
+ }
+
+ @Override
+ public float getContentSizeWidth() {
+ return getIntrinsicContentSizeWidth();
+ }
+
+ @Override
+ public float getContentSizeHeight() {
+ return getIntrinsicContentSizeHeight();
+ }
+
+
+ private float getIntrinsicContentSizeWidth()
+ {
+ if (imageBitmap == null)
+ {
+ return (1.0f);
+ }
+ return (imageBitmap.getWidth());
+ }
+
+ private float getIntrinsicContentSizeHeight()
+ {
+ if (imageBitmap == null)
+ {
+ return (1.0f);
+ }
+ return (imageBitmap.getHeight());
+ }
+
+ /**
+ * Sets a image to view.
+ * (CameraLiveViewListenerImpl.IImageDataReceiver の実装)
+ *
+ * @param data A image of live-view.
+ * @param metadata A metadata of the image.
+ */
+ public void setImageData(byte[] data, Map<String, Object> metadata) {
+ Bitmap bitmap;
+ int rotationDegrees;
+
+ if (data != null && metadata != null) {
+ // Create a bitmap.
+ try {
+ bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
+ } catch (OutOfMemoryError e) {
+ e.printStackTrace();
+ return;
+ }
+
+ // Acquire a rotation degree of image.
+ int orientation = ExifInterface.ORIENTATION_UNDEFINED;
+ if (metadata.containsKey(EXIF_ORIENTATION)) {
+ orientation = Integer.parseInt((String) metadata.get(EXIF_ORIENTATION));
+ }
+ switch (orientation) {
+ case ExifInterface.ORIENTATION_NORMAL:
+ rotationDegrees = 0;
+ break;
+ case ExifInterface.ORIENTATION_ROTATE_90:
+ rotationDegrees = 90;
+ break;
+ case ExifInterface.ORIENTATION_ROTATE_180:
+ rotationDegrees = 180;
+ break;
+ case ExifInterface.ORIENTATION_ROTATE_270:
+ rotationDegrees = 270;
+ break;
+ default:
+ rotationDegrees = 0;
+ break;
+ }
+ imageBitmap = bitmap;
+ imageRotationDegrees = rotationDegrees;
+ }
+
+ refreshCanvas();
+ }
+
+ /**
+ * Returns a point which is detected by a motion event.
+ *
+ * @param event A motion event.
+ * @return A point in the view finder. if a point is equal to null, the point is out of the view finder.
+ */
+ public PointF getPointWithEvent(MotionEvent event)
+ {
+ if (event == null || imageBitmap == null)
+ {
+ return null;
+ }
+
+ PointF pointOnView = new PointF(event.getX(), event.getY());
+ PointF pointOnImage = convertPointFromViewArea(pointOnView);
+ float imageWidth;
+ float imageHeight;
+ if (imageRotationDegrees == 0 || imageRotationDegrees == 180) {
+ imageWidth = imageBitmap.getWidth();
+ imageHeight = imageBitmap.getHeight();
+ } else {
+ imageWidth = imageBitmap.getHeight();
+ imageHeight = imageBitmap.getWidth();
+ }
+ return (OLYCamera.convertPointOnLiveImageIntoViewfinder(pointOnImage, imageWidth, imageHeight, imageRotationDegrees));
+ }
+
+ /**
+ * Returns whether a image area contains a specified point.
+ *
+ * @param point The point to examine.
+ * @return true if the image is not null or empty and the point is located within the rectangle; otherwise, false.
+ */
+ public boolean isContainsPoint(PointF point)
+ {
+ return ((point != null) && (new RectF(0, 0, 1, 1)).contains(point.x, point.y));
+ }
+
+ /**
+ * Hides the forcus frame.
+ */
+ public void hideFocusFrame()
+ {
+ if (focusFrameHideTimer != null)
+ {
+ focusFrameHideTimer.cancel();
+ focusFrameHideTimer = null;
+ }
+ showingFocusFrame = false;
+
+ refreshCanvas();
+ }
+
+ /**
+ * Shows the focus frame.
+ *
+ * @param rect A rectangle of the focus frame on view area.
+ * @param status A status of the focus frame.
+ * @param duration A duration of the focus frame showing.
+ */
+ @Override
+ public void showFocusFrame(RectF rect, FocusFrameStatus status, double duration)
+ {
+ if (focusFrameHideTimer != null)
+ {
+ focusFrameHideTimer.cancel();
+ focusFrameHideTimer = null;
+ }
+
+ showingFocusFrame = true;
+ focusFrameStatus = status;
+ focusFrameRect = rect;
+
+ refreshCanvas();
+
+ if (duration > 0)
+ {
+ focusFrameHideTimer = new Timer();
+ focusFrameHideTimer.schedule(new TimerTask() {
+ @Override
+ public void run() {
+ hideFocusFrame();
+ }
+ }, (long) (duration * 1000));
+ }
+ }
+
+ private void refreshCanvas()
+ {
+ if (Looper.getMainLooper().getThread() == Thread.currentThread())
+ {
+ invalidate();
+ }
+ else
+ {
+ postInvalidate();
+ }
+ }
+
+ /**
+ * ビットマップの表示
+ *
+ * @param canvas キャンバス
+ */
+ private void drawCanvas(Canvas canvas)
+ {
+ // Clears the canvas.
+ canvas.drawARGB(255, 0, 0, 0);
+
+ // ビットマップの取得
+ Bitmap bitmapToShow;
+ if ((focusAssistFeature)&&(bitmapConverter != null))
+ {
+ // フォーカスアシスト実行時の処理...
+ bitmapToShow = bitmapConverter.getModifiedBitmap(imageBitmap);
+ }
+ else
+ {
+ bitmapToShow = imageBitmap;
+ }
+ if (bitmapToShow == null)
+ {
+ // 表示するビットマップがないときは、すぐに折り返す
+ return;
+ }
+
+ // Rotates the image.
+ int centerX = canvas.getWidth() / 2;
+ int centerY = canvas.getHeight() / 2;
+ canvas.rotate(imageRotationDegrees, centerX, centerY);
+
+ RectF viewRect = null;
+
+ // Calculate the viewport of bitmap.
+ if (imageScaleType == ImageView.ScaleType.FIT_CENTER)
+ {
+ viewRect = decideViewRect(canvas, bitmapToShow, imageRotationDegrees);
+
+ // Draws the bitmap.
+ Rect imageRect = new Rect(0, 0, bitmapToShow.getWidth(), bitmapToShow.getHeight());
+ canvas.drawBitmap(bitmapToShow, imageRect, viewRect, null);
+ }
+ else
+ {
+ // Sorry, other scale types are not supported.
+ Log.v(TAG, "Sorry, other scale types are not supported. " + imageScaleType);
+ }
+
+ // Cancels rotation of the canvas.
+ canvas.rotate(-imageRotationDegrees, centerX, centerY);
+
+ // フォーカスフレームを表示する
+ if ((focusFrameRect != null) && (showingFocusFrame))
+ {
+ if (imageRotationDegrees == 0 || imageRotationDegrees == 180) {
+ drawFocusFrame(canvas, bitmapToShow.getWidth(), bitmapToShow.getHeight());
+ } else {
+ drawFocusFrame(canvas, bitmapToShow.getHeight(), bitmapToShow.getWidth());
+ }
+ }
+
+ // グリッド(撮影補助線)の表示
+ if ((viewRect != null)&&(showGridFeature)&&(gridFrameDrawer != null))
+ {
+ drawGridFrame(canvas, viewRect);
+ }
+ }
+
+ private RectF decideViewRect(Canvas canvas, Bitmap bitmapToShow, int degrees)
+ {
+ final int srcWidth;
+ final int srcHeight;
+ if ((degrees == 0) || (degrees == 180))
+ {
+ srcWidth = bitmapToShow.getWidth();
+ srcHeight = bitmapToShow.getHeight();
+ }
+ else
+ {
+ // Replaces width and height.
+ srcWidth = bitmapToShow.getHeight();
+ srcHeight = bitmapToShow.getWidth();
+ }
+
+ int maxWidth = canvas.getWidth();
+ int maxHeight = canvas.getHeight();
+
+ int centerX = canvas.getWidth() / 2;
+ int centerY = canvas.getHeight() / 2;
+
+ float widthRatio = maxWidth / (float) srcWidth;
+ float heightRatio = maxHeight / (float) srcHeight;
+ float smallRatio = Math.min(widthRatio, heightRatio);
+
+ final int dstWidth;
+ final int dstHeight;
+ if (widthRatio < heightRatio)
+ {
+ // Fits to maxWidth with keeping aspect ratio.
+ dstWidth = maxWidth;
+ dstHeight = (int)(smallRatio * srcHeight);
+ }
+ else
+ {
+ // Fits to maxHeight with keeping aspect ratio.
+ dstHeight = maxHeight;
+ dstWidth = (int)(smallRatio * srcWidth);
+ }
+
+ final float halfWidth = dstWidth * 0.5f;
+ final float halfHeight = dstHeight * 0.5f;
+ if ((degrees == 0) || (degrees == 180))
+ {
+ return (new RectF(
+ centerX - halfWidth,
+ centerY - halfHeight,
+ centerX - halfWidth + dstWidth,
+ centerY - halfHeight + dstHeight));
+ }
+
+ // Replaces the width and height.
+ return (new RectF(
+ centerX - halfHeight,
+ centerY - halfWidth,
+ centerX - halfHeight + dstHeight,
+ centerY - halfWidth + dstWidth));
+ }
+
+ /**
+ * AF枠の表示
+ *
+ * @param canvas キャンバス
+ * @param imageWidth 幅
+ * @param imageHeight 高さ
+ */
+ private void drawFocusFrame(Canvas canvas, float imageWidth, float imageHeight)
+ {
+ //Log.v(TAG, "drawFocusFrame() :" + focusFrameStatus);
+
+ // Calculate the rectangle of focus.
+ RectF focusRectOnImage = OLYCamera.convertRectOnViewfinderIntoLiveImage(focusFrameRect, imageWidth, imageHeight, imageRotationDegrees);
+ RectF focusRectOnView = convertRectFromImageArea(focusRectOnImage);
+
+ // Draw a rectangle to the canvas.
+ Paint focusFramePaint = new Paint();
+ focusFramePaint.setStyle(Paint.Style.STROKE);
+ switch (focusFrameStatus)
+ {
+ case Running:
+ focusFramePaint.setColor(Color.WHITE);
+ break;
+
+ case Focused:
+ focusFramePaint.setColor(Color.GREEN);
+ break;
+
+ case Failed:
+ focusFramePaint.setColor(Color.RED);
+ break;
+
+ case Errored:
+ focusFramePaint.setColor(Color.YELLOW);
+ break;
+ }
+ float focusFrameStrokeWidth = 2.0f;
+ DisplayMetrics dm = getResources().getDisplayMetrics();
+ float strokeWidth = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, focusFrameStrokeWidth, dm);
+ focusFramePaint.setStrokeWidth(strokeWidth);
+ canvas.drawRect(focusRectOnView, focusFramePaint);
+ }
+
+ /**
+ * グリッドの表示
+ *
+ * @param canvas キャンバスエリア
+ * @param viewRect 表示領域
+ */
+ private void drawGridFrame(Canvas canvas, RectF viewRect)
+ {
+ RectF gridRect;
+ if ((imageRotationDegrees == 0) || (imageRotationDegrees == 180)) {
+ gridRect = new RectF(viewRect);
+ } else {
+ float height = viewRect.right - viewRect.left;
+ float width = viewRect.bottom - viewRect.top;
+ float left = (canvas.getWidth() / 2.0f) - (width / 2.0f);
+ float top = (canvas.getHeight() / 2.0f) - (height / 2.0f);
+ gridRect = new RectF(left, top, left + width, top + height);
+ }
+
+ Paint framePaint = new Paint();
+ framePaint.setStyle(Paint.Style.STROKE);
+ framePaint.setAntiAlias(true);
+ framePaint.setStrokeWidth(0.0f);
+ framePaint.setColor(gridFrameDrawer.getDrawColor());
+ gridFrameDrawer.drawFramingGrid(canvas, gridRect, framePaint);
+ }
+
+ /**
+ * 画面にメッセージを表示する
+ */
+ private void drawInformationMessages(Canvas canvas)
+ {
+ String message;
+ RectF viewRect;
+ if (imageBitmap != null)
+ {
+ // ビットマップの表示エリアに合わせて位置をチューニングする
+ viewRect = decideViewRect(canvas, imageBitmap, 0);
+ }
+ else
+ {
+ // 適当なサイズ...
+ viewRect = new RectF(5.0f, 0.0f, canvas.getWidth() - 5.0f, canvas.getHeight() - 55.0f);
+ }
+
+ // 画面の中心に表示する
+ message = messageHolder.getMessage(ShowMessageHolder.MessageArea.CENTER);
+ if ((message != null)&&(message.length() > 0))
+ {
+ Paint paint = new Paint();
+ paint.setColor(messageHolder.getColor(ShowMessageHolder.MessageArea.CENTER));
+ paint.setTextSize(messageHolder.getSize(ShowMessageHolder.MessageArea.CENTER));
+ paint.setAntiAlias(true);
+ Paint.FontMetrics fontMetrics = paint.getFontMetrics();
+ float cx = (canvas.getWidth() / 2.0f) - (paint.measureText(message) / 2.0f);
+ float cy = (canvas.getHeight() / 2.0f) - ((fontMetrics.ascent + fontMetrics.descent) / 2.0f);
+ canvas.drawText(message, cx, cy, paint);
+ }
+
+ // 画面上部左側に表示する
+ message = messageHolder.getMessage(ShowMessageHolder.MessageArea.UPLEFT);
+ if ((message != null)&&(message.length() > 0))
+ {
+ Paint paintUp = new Paint();
+ paintUp.setColor(messageHolder.getColor(ShowMessageHolder.MessageArea.UPLEFT));
+ paintUp.setTextSize(messageHolder.getSize(ShowMessageHolder.MessageArea.UPLEFT));
+ paintUp.setAntiAlias(true);
+ Paint.FontMetrics fontMetrics = paintUp.getFontMetrics();
+ canvas.drawText(message, viewRect.left + 3.0f, viewRect.top + (fontMetrics.descent - fontMetrics.ascent), paintUp);
+ }
+
+ // 画面上部右側に表示する
+ message = messageHolder.getMessage(ShowMessageHolder.MessageArea.UPRIGHT);
+ if ((message != null)&&(message.length() > 0))
+ {
+ Paint paintUp = new Paint();
+ paintUp.setColor(messageHolder.getColor(ShowMessageHolder.MessageArea.UPRIGHT));
+ paintUp.setTextSize(messageHolder.getSize(ShowMessageHolder.MessageArea.UPRIGHT));
+ paintUp.setAntiAlias(true);
+ float width = paintUp.measureText(message);
+ Paint.FontMetrics fontMetrics = paintUp.getFontMetrics();
+ canvas.drawText(message, (viewRect.right - 3.0f) - width, viewRect.top + (fontMetrics.descent - fontMetrics.ascent), paintUp);
+ }
+
+ // 画面下部左側に表示する
+ message = messageHolder.getMessage(ShowMessageHolder.MessageArea.LOWLEFT);
+ if ((message != null)&&(message.length() > 0))
+ {
+ Paint paint = new Paint();
+ paint.setColor(messageHolder.getColor(ShowMessageHolder.MessageArea.LOWLEFT));
+ paint.setTextSize(messageHolder.getSize(ShowMessageHolder.MessageArea.LOWLEFT));
+ paint.setAntiAlias(true);
+ Paint.FontMetrics fontMetrics = paint.getFontMetrics();
+ canvas.drawText(message, viewRect.left + 3.0f, viewRect.bottom - fontMetrics.bottom, paint);
+ }
+
+ // 画面下部右側に表示する
+ message = messageHolder.getMessage(ShowMessageHolder.MessageArea.LOWRIGHT);
+ if ((message != null)&&(message.length() > 0))
+ {
+ Paint paint = new Paint();
+ paint.setColor(messageHolder.getColor(ShowMessageHolder.MessageArea.LOWRIGHT));
+ paint.setTextSize(messageHolder.getSize(ShowMessageHolder.MessageArea.LOWRIGHT));
+ paint.setAntiAlias(true);
+ float width = paint.measureText(message);
+ Paint.FontMetrics fontMetrics = paint.getFontMetrics();
+ canvas.drawText(message, (viewRect.right - 3.0f) - width, viewRect.bottom - fontMetrics.bottom, paint);
+ }
+
+ // 画面上部中央に表示する
+ message = messageHolder.getMessage(ShowMessageHolder.MessageArea.UPCENTER);
+ if ((message != null)&&(message.length() > 0))
+ {
+ Paint paintUp = new Paint();
+ paintUp.setColor(messageHolder.getColor(ShowMessageHolder.MessageArea.UPCENTER));
+ paintUp.setTextSize(messageHolder.getSize(ShowMessageHolder.MessageArea.UPCENTER));
+ paintUp.setAntiAlias(true);
+ float width = paintUp.measureText(message) / 2.0f;
+ Paint.FontMetrics fontMetrics = paintUp.getFontMetrics();
+ canvas.drawText(message, (viewRect.centerX()) - width, viewRect.top + (fontMetrics.descent - fontMetrics.ascent), paintUp);
+ }
+
+ // 画面下部中央に表示する
+ message = messageHolder.getMessage(ShowMessageHolder.MessageArea.LOWCENTER);
+ if ((message != null)&&(message.length() > 0))
+ {
+ Paint paint = new Paint();
+ paint.setColor(messageHolder.getColor(ShowMessageHolder.MessageArea.LOWCENTER));
+ paint.setTextSize(messageHolder.getSize(ShowMessageHolder.MessageArea.LOWCENTER));
+ paint.setAntiAlias(true);
+ float width = paint.measureText(message) / 2.0f;
+ Paint.FontMetrics fontMetrics = paint.getFontMetrics();
+ canvas.drawText(message, (viewRect.centerX()) - width, viewRect.bottom - fontMetrics.bottom, paint);
+ }
+
+ // 画面中央左に表示する
+ message = messageHolder.getMessage(ShowMessageHolder.MessageArea.LEFTCENTER);
+ if ((message != null)&&(message.length() > 0))
+ {
+ Paint paint = new Paint();
+ paint.setColor(messageHolder.getColor(ShowMessageHolder.MessageArea.LEFTCENTER));
+ paint.setTextSize(messageHolder.getSize(ShowMessageHolder.MessageArea.LEFTCENTER));
+ paint.setAntiAlias(true);
+ paint.setShadowLayer(5.0f, 3.0f, 3.0f, Color.BLACK); // これで文字に影をつけたい
+ Paint.FontMetrics fontMetrics = paint.getFontMetrics();
+ float cy = (canvas.getHeight() / 2.0f) - ((fontMetrics.ascent + fontMetrics.descent) / 2.0f);
+ canvas.drawText(message, viewRect.left + 3.0f, cy, paint);
+ }
+
+ // 画面中央右に表示する
+ message = messageHolder.getMessage(ShowMessageHolder.MessageArea.RIGHTCENTER);
+ if ((message != null)&&(message.length() > 0))
+ {
+ Paint paint = new Paint();
+ paint.setColor(messageHolder.getColor(ShowMessageHolder.MessageArea.RIGHTCENTER));
+ paint.setTextSize(messageHolder.getSize(ShowMessageHolder.MessageArea.RIGHTCENTER));
+ paint.setAntiAlias(true);
+ paint.setShadowLayer(5.0f, 3.0f, 3.0f, Color.BLACK); // これで文字に影をつけたい
+ float width = paint.measureText(message);
+ Paint.FontMetrics fontMetrics = paint.getFontMetrics();
+ float cy = (canvas.getHeight() / 2.0f) - ((fontMetrics.ascent + fontMetrics.descent) / 2.0f);
+ canvas.drawText(message, (viewRect.right - 3.0f) - width, cy, paint);
+ }
+
+ }
+
+ /**
+ * レベルゲージ(デジタル水準器)の表示
+ *
+ */
+ private void drawLevelGauge(Canvas canvas)
+ {
+ // レベルゲージの表示位置
+ int height = canvas.getHeight();
+ int width = canvas.getWidth();
+ int centerX = width / 2;
+ int centerY = height / 2;
+
+ float maxBandWidth = width / 3.0f; // ゲージの最大長 (画面の 1/3 ぐらい)
+ float maxBandHeight = height / 3.0f; // ゲージの最大長 (画面の 1/3 ぐらい)
+ int barWidthInitial = 5; // 表示するゲージの幅(の初期値)
+ int barWidth; // 実際に表示するゲージの幅
+
+ Paint paint = new Paint();
+
+ // 垂直線
+ float verticalValue = messageHolder.getLevel(IMessageDrawer.LevelArea.LEVEL_VERTICAL);
+ float verticalSize = verticalValue / 60.0f * maxBandHeight; // 45度で切り替わるはずだが、一応...
+ if (Math.abs(verticalSize) < 1.0f)
+ {
+ // 線引き限界以下、水平検出とする (この時の線は倍の長さにする)
+ verticalSize = 1.0f;
+ barWidth = barWidthInitial * 2;
+ }
+ else
+ {
+ barWidth = barWidthInitial;
+ }
+ paint.setStrokeWidth(barWidth);
+ paint.setColor(messageHolder.getLevelColor(verticalValue));
+ canvas.drawLine((width - barWidth), centerY, (width - barWidth), (centerY + verticalSize), paint);
+
+ // 水平線
+ float horizontalValue = messageHolder.getLevel(IMessageDrawer.LevelArea.LEVEL_HORIZONTAL);
+ float horizontalSize = horizontalValue / 60.0f * maxBandWidth; // 45度ぐらいで切り替わるはずだが、一応...
+ if (Math.abs(horizontalSize) < 1.0f)
+ {
+ // 線引き限界以下、水平検出とする (この時の線は倍の長さにする)
+ horizontalSize = 1.0f;
+ barWidth = barWidthInitial * 2;
+ }
+ else
+ {
+ barWidth = barWidthInitial;
+ }
+ paint.setStrokeWidth(barWidth);
+ paint.setColor(messageHolder.getLevelColor(horizontalValue));
+ canvas.drawLine(centerX, (height - barWidth), (centerX + horizontalSize), (height - barWidth), paint);
+
+ // 水平線 (スクリーン内の線)
+ float horizontalValue0 = messageHolder.getLevel(IMessageDrawer.LevelArea.LEVEL_HORIZONTAL);
+ paint.setStrokeWidth(2.0f);
+ paint.setAntiAlias(true);
+ paint.setColor(messageHolder.getLevelColor(horizontalValue0));
+ if ((imageRotationDegrees == 0) || (imageRotationDegrees == 180))
+ {
+ // 通常状態
+ float YY = canvas.getHeight() / 2.0f; // centerY
+ float diffY = (float) Math.sin(Math.toRadians(horizontalValue0)) * (float) centerX;
+ canvas.drawLine(0, (YY + diffY), width, (YY - diffY), paint);
+ }
+ else
+ {
+ // 縦持ち状態
+ float XX = canvas.getWidth() / 2.0f; // centerX
+ float diffX = (float) Math.sin(Math.toRadians(horizontalValue0)) * (float) centerY;
+ canvas.drawLine((XX + diffX), 0, (XX - diffX), canvas.getHeight(), paint);
+
+ }
+ }
+
+ /**
+ * Converts a point on image area to a point on view area.
+ *
+ * @param point A point on image area. (e.g. a live preview image)
+ * @return A point on view area. (e.g. a touch panel view)
+ */
+ private PointF convertPointFromImageArea(PointF point) {
+ if (imageBitmap == null) {
+ return new PointF();
+ }
+
+ float viewPointX = point.x;
+ float viewPointY = point.y;
+ float imageSizeWidth;
+ float imageSizeHeight;
+ if (imageRotationDegrees == 0 || imageRotationDegrees == 180)
+ {
+ imageSizeWidth = imageBitmap.getWidth();
+ imageSizeHeight = imageBitmap.getHeight();
+ }
+ else
+ {
+ imageSizeWidth = imageBitmap.getHeight();
+ imageSizeHeight = imageBitmap.getWidth();
+ }
+ float viewSizeWidth = this.getWidth();
+ float viewSizeHeight = this.getHeight();
+ float ratioX = viewSizeWidth / imageSizeWidth;
+ float ratioY = viewSizeHeight / imageSizeHeight;
+ float scale;
+
+ switch (imageScaleType) {
+ case FIT_XY:
+ viewPointX *= ratioX;
+ viewPointY *= ratioY;
+ break;
+ case FIT_CENTER: // go to next label.
+ case CENTER_INSIDE:
+ scale = Math.min(ratioX, ratioY);
+ viewPointX *= scale;
+ viewPointY *= scale;
+ viewPointX += (viewSizeWidth - imageSizeWidth * scale) / 2.0f;
+ viewPointY += (viewSizeHeight - imageSizeHeight * scale) / 2.0f;
+ break;
+ case CENTER_CROP:
+ scale = Math.max(ratioX, ratioY);
+ viewPointX *= scale;
+ viewPointY *= scale;
+ viewPointX += (viewSizeWidth - imageSizeWidth * scale) / 2.0f;
+ viewPointY += (viewSizeHeight - imageSizeHeight * scale) / 2.0f;
+ break;
+ case CENTER:
+ viewPointX += viewSizeWidth / 2.0 - imageSizeWidth / 2.0f;
+ viewPointY += viewSizeHeight / 2.0 - imageSizeHeight / 2.0f;
+ break;
+ default:
+ break;
+ }
+
+ return new PointF(viewPointX, viewPointY);
+ }
+
+ /**
+ * Converts a point on view area to a point on image area.
+ *
+ * @param point A point on view area. (e.g. a touch panel view)
+ * @return A point on image area. (e.g. a live preview image)
+ */
+ private PointF convertPointFromViewArea(PointF point)
+ {
+ if (imageBitmap == null)
+ {
+ return new PointF();
+ }
+
+ float imagePointX = point.x;
+ float imagePointY = point.y;
+ float imageSizeWidth;
+ float imageSizeHeight;
+ if (imageRotationDegrees == 0 || imageRotationDegrees == 180) {
+ imageSizeWidth = imageBitmap.getWidth();
+ imageSizeHeight = imageBitmap.getHeight();
+ } else {
+ imageSizeWidth = imageBitmap.getHeight();
+ imageSizeHeight = imageBitmap.getWidth();
+ }
+ float viewSizeWidth = this.getWidth();
+ float viewSizeHeight = this.getHeight();
+ float ratioX = viewSizeWidth / imageSizeWidth;
+ float ratioY = viewSizeHeight / imageSizeHeight;
+ float scale;
+
+ switch (imageScaleType) {
+ case FIT_XY:
+ imagePointX /= ratioX;
+ imagePointY /= ratioY;
+ break;
+ case FIT_CENTER: // go to next label.
+ case CENTER_INSIDE:
+ scale = Math.min(ratioX, ratioY);
+ imagePointX -= (viewSizeWidth - imageSizeWidth * scale) / 2.0f;
+ imagePointY -= (viewSizeHeight - imageSizeHeight * scale) / 2.0f;
+ imagePointX /= scale;
+ imagePointY /= scale;
+ break;
+ case CENTER_CROP:
+ scale = Math.max(ratioX, ratioY);
+ imagePointX -= (viewSizeWidth - imageSizeWidth * scale) / 2.0f;
+ imagePointY -= (viewSizeHeight - imageSizeHeight * scale) / 2.0f;
+ imagePointX /= scale;
+ imagePointY /= scale;
+ break;
+ case CENTER:
+ imagePointX -= (viewSizeWidth - imageSizeWidth) / 2.0f;
+ imagePointY -= (viewSizeHeight - imageSizeHeight) / 2.0f;
+ break;
+ default:
+ break;
+ }
+
+ return new PointF(imagePointX, imagePointY);
+ }
+
+ /**
+ * Converts a rectangle on image area to a rectangle on view area.
+ *
+ * @param rect A rectangle on image area. (e.g. a live preview image)
+ * @return A rectangle on view area. (e.g. a touch panel view)
+ */
+ private RectF convertRectFromImageArea(RectF rect)
+ {
+ if (imageBitmap == null)
+ {
+ return new RectF();
+ }
+
+ PointF imageTopLeft = new PointF(rect.left, rect.top);
+ PointF imageBottomRight = new PointF(rect.right, rect.bottom);
+
+ PointF viewTopLeft = convertPointFromImageArea(imageTopLeft);
+ PointF viewBottomRight = convertPointFromImageArea(imageBottomRight);
+
+ return (new RectF(viewTopLeft.x, viewTopLeft.y, viewBottomRight.x, viewBottomRight.y));
+ }
+
+ @Override
+ public void toggleFocusAssist()
+ {
+ focusAssistFeature = !focusAssistFeature;
+ }
+
+ @Override
+ public void toggleShowGridFrame()
+ {
+ showGridFeature = !showGridFeature;
+ SharedPreferences preferences = android.support.v7.preference.PreferenceManager.getDefaultSharedPreferences(getContext());
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putBoolean(IPreferencePropertyAccessor.SHOW_GRID_STATUS, showGridFeature);
+ editor.apply();
+ }
+
+ public boolean isShowGrid()
+ {
+ return (showGridFeature);
+ }
+
+ @Override
+ public IMessageDrawer getMessageDrawer()
+ {
+ return (messageHolder.getMessageDrawer());
+ }
+
+}
--- /dev/null
+package net.osdn.gokigen.a01d.liveview;
+
+import java.util.Map;
+
+import jp.co.olympus.camerakit.OLYCamera;
+import jp.co.olympus.camerakit.OLYCameraLiveViewListener;
+
+/**
+ * OLYCameraLiveViewListener の実装
+ * (LiveViewFragment用)
+ *
+ */
+public class CameraLiveViewListenerImpl implements OLYCameraLiveViewListener
+{
+ private IImageDataReceiver imageView = null;
+
+ /**
+ * コンストラクタ
+ */
+ public CameraLiveViewListenerImpl()
+ {
+ //
+ }
+
+ /**
+ * 更新するImageViewを拾う
+ *
+ */
+ public void setCameraLiveImageView(IImageDataReceiver target)
+ {
+ this.imageView = target;
+ }
+
+ /**
+ * LiveViewの画像データを更新する
+ *
+ */
+ @Override
+ public void onUpdateLiveView(OLYCamera camera, byte[] data, Map<String, Object> metadata)
+ {
+ if (imageView != null)
+ {
+ imageView.setImageData(data, metadata);
+ }
+ }
+
+ /**
+ * CameraLiveImageView
+ */
+ public interface IImageDataReceiver
+ {
+ void setImageData(byte[] data, Map<String, Object> metadata);
+ }
+}
--- /dev/null
+package net.osdn.gokigen.a01d.liveview;
+
+import android.graphics.PointF;
+import android.graphics.RectF;
+import android.view.MotionEvent;
+
+/**
+ * フォーカスフレームの表示クラス
+ *
+ */
+public interface IAutoFocusFrameDisplay
+{
+ // フォーカスフレームの状態
+ enum FocusFrameStatus
+ {
+ Running,
+ Focused,
+ Failed,
+ Errored,
+ }
+
+ float getContentSizeWidth();
+ float getContentSizeHeight();
+
+ PointF getPointWithEvent(MotionEvent event);
+ boolean isContainsPoint(PointF point);
+
+ void showFocusFrame(RectF rect, FocusFrameStatus status, double duration);
+ void hideFocusFrame();
+}
--- /dev/null
+package net.osdn.gokigen.a01d.liveview;
+
+import android.graphics.Canvas;
+
+/**
+ * カメラパネルの描画
+ *
+ */
+public interface ICameraPanelDrawer
+{
+ void drawCameraPanel(Canvas canvas);
+}
--- /dev/null
+package net.osdn.gokigen.a01d.liveview;
+
+/**
+ *
+ */
+public interface ICameraStatusDisplay
+{
+ void updateTakeMode();
+ void updateDriveMode();
+ void updateWhiteBalance();
+ void updateBatteryLevel();
+ void updateAeMode();
+ void updateAeLockState();
+ void updateCameraStatus();
+ void updateCameraStatus(String message);
+ void updateLevelGauge(String orientation, float roll, float pitch);
+}
--- /dev/null
+package net.osdn.gokigen.a01d.liveview;
+
+import net.osdn.gokigen.a01d.liveview.message.IMessageDrawer;
+
+/**
+ *
+ *
+ */
+interface ILiveImageStatusNotify
+{
+ void toggleFocusAssist();
+ void toggleShowGridFrame();
+ IMessageDrawer getMessageDrawer();
+}
--- /dev/null
+package net.osdn.gokigen.a01d.liveview;
+
+interface IStatusViewDrawer
+{
+ void updateGridIcon();
+ void updateConnectionStatus();
+ /*
+ void updateStatusView(String message);
+ void updateFocusAssistStatus();
+ void updateGridFrameStatus();
+ void showFavoriteSettingDialog();
+
+ void toggleTimerStatus();
+
+ void toggleGpsTracking();
+ void updateGpsTrackingStatus();
+
+ IMessageDrawer getMessageDrawer();
+*/
+}
--- /dev/null
+package net.osdn.gokigen.a01d.liveview;
+
+import android.util.Log;
+import android.view.View;
+
+import net.osdn.gokigen.a01d.IChangeScene;
+import net.osdn.gokigen.a01d.R;
+
+/**
+ *
+ *
+ */
+
+class LiveViewClickListener implements View.OnClickListener
+{
+ final String TAG = toString();
+ final ILiveImageStatusNotify statusNotify;
+ final IStatusViewDrawer statusViewDrawer;
+ final IChangeScene changeScene;
+
+
+ LiveViewClickListener(ILiveImageStatusNotify imageStatusNotify, IStatusViewDrawer statusView, IChangeScene changeScene)
+ {
+ this.statusNotify = imageStatusNotify;
+ this.statusViewDrawer = statusView;
+ this.changeScene = changeScene;
+ }
+
+
+ @Override
+ public void onClick(View view)
+ {
+ int id = view.getId();
+ try
+ {
+ switch (id)
+ {
+ case R.id.show_hide_grid_button:
+ // グリッドの ON/OFF
+ statusNotify.toggleShowGridFrame();
+ statusViewDrawer.updateGridIcon();
+ break;
+
+ case R.id.show_preference_button:
+ // カメラの設定
+ changeScene.changeSceneToConfiguration();
+ break;
+
+ case R.id.camera_property_settings_button:
+ // カメラのプロパティ設定
+ changeScene.changeSceneToCameraPropertyList();
+ break;
+
+ case R.id.connect_disconnect_button:
+ // カメラと接続・切断のボタンが押された
+ changeScene.changeCameraConnection();
+ break;
+
+ default:
+ Log.v(TAG, "onClick() : " + id);
+ break;
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+}
--- /dev/null
+package net.osdn.gokigen.a01d.liveview;
+
+import android.app.Activity;
+import android.content.Context;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.content.res.ResourcesCompat;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import net.osdn.gokigen.a01d.IChangeScene;
+import net.osdn.gokigen.a01d.R;
+
+import java.io.File;
+
+
+/**
+ * 撮影用ライブビュー画面
+ *
+ */
+public class LiveViewFragment extends Fragment implements IStatusViewDrawer
+{
+ private final String TAG = this.toString();
+ private static final int COMMAND_MY_PROPERTY = 0x00000100;
+
+// private IOlyCameraCoordinator camera = null;
+// private MyInterfaceProvider factory = null;
+// private ICameraRunMode changeRunModeExecutor = null;
+// private OlyCameraLiveViewOnTouchListener onTouchListener = null;
+ private CameraLiveViewListenerImpl liveViewListener = null;
+// private CameraStatusListenerImpl statusListener = null;
+// private IGpsLocationPicker locationPicker = null;
+
+ private IChangeScene changeScene = null;
+
+ private LiveViewClickListener onClickListener = null;
+
+
+ private TextView statusArea = null;
+ private CameraLiveImageView imageView = null;
+ //private CameraControlPanel cameraPanel = null;
+
+/*
+ private ImageView manualFocus = null;
+ private ImageView afLock = null;
+ private ImageView aeLock = null;
+ private ImageView focusAssist = null;
+*/
+ private ImageButton showGrid = null;
+ private ImageButton connectStatus = null;
+
+ private boolean imageViewCreated = false;
+ private View myView = null;
+ private String messageValue = "";
+
+
+ /**
+ *
+ *
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ Log.v(TAG, "onCreate()");
+
+ if (liveViewListener == null)
+ {
+ liveViewListener = new CameraLiveViewListenerImpl();
+ }
+
+
+/*
+
+ if (onTouchListener == null)
+ {
+ onTouchListener = new OlyCameraLiveViewOnTouchListener(getContext().getApplicationContext());
+ }
+ if (statusListener == null)
+ {
+ statusListener = new CameraStatusListenerImpl(getContext().getApplicationContext(), this);
+ }
+ if (locationPicker == null)
+ {
+ locationPicker = new GpsLocationPicker(getContext().getApplicationContext(), onTouchListener);
+ }
+*/
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public void onAttach(Context context)
+ {
+ super.onAttach(context);
+ Log.v(TAG, "onAttach()");
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
+ {
+ super.onCreateView(inflater, container, savedInstanceState);
+
+ Log.v(TAG, "onCreateView()");
+
+ if ((imageViewCreated)&&(myView != null))
+ {
+ // Viewを再利用。。。
+ Log.v(TAG, "onCreateView() : called again, so do nothing...");
+ return (myView);
+ }
+ View view = inflater.inflate(R.layout.fragment_live_view, container, false);
+ myView = view;
+ imageViewCreated = true;
+
+ imageView = view.findViewById(R.id.cameraLiveImageView);
+
+ if (onClickListener == null)
+ {
+ onClickListener = new LiveViewClickListener(imageView, this, changeScene);
+ }
+
+ /*
+ imageView.setOnClickListener(onTouchListener);
+ imageView.setOnTouchListener(onTouchListener);
+*/
+/*
+ liveViewListener.setCameraLiveImageView(imageView);
+ if (factory != null)
+ {
+ factory.setAutoFocusFrameDisplay(imageView);
+ }
+*/
+/*
+ // 画面下部のスマホカメラ領域
+ PhoneCameraView phoneCameraView = (PhoneCameraView) view.findViewById(R.id.phoneCameraView);
+
+ // カメラ画像の大きさを動的に調整(したい)
+ //phoneCameraView.getViewTreeObserver().addOnGlobalLayoutListener(phoneCameraView);
+
+ ImageView shutter = (ImageView) view.findViewById(R.id.shutterImageView);
+ shutter.setOnClickListener(onTouchListener);
+
+ ImageView config = (ImageView) view.findViewById(R.id.configImageView);
+ config.setOnClickListener(onTouchListener);
+
+ ImageView build = (ImageView) view.findViewById(R.id.buildImageView);
+ build.setOnClickListener(onTouchListener);
+
+ ImageButton gps = (ImageButton) view.findViewById(R.id.gpsLocationButton);
+ if ((locationPicker.prepare(camera.getCameraPropertyProvider()))&&(locationPicker.hasGps()))
+ {
+ // GPSボタンの状態を更新しておく
+ updateGpsTrackingStatus();
+
+ // GPSが使用可能な状態のとき...ボタンを押せるようにする
+ gps.setOnClickListener(onTouchListener);
+ }
+ else
+ {
+ // GPSが利用不可のとき、、、ボタンは無効(非表示)にする
+ gps.setEnabled(false);
+ gps.setVisibility(View.INVISIBLE);
+ }
+
+ manualFocus = (ImageView) view.findViewById(R.id.manualFocusImageView);
+ manualFocus.setOnClickListener(onTouchListener);
+
+ afLock = (ImageView) view.findViewById(R.id.AutoFocusLockImageView);
+ afLock.setOnClickListener(onTouchListener);
+
+ aeLock = (ImageView) view.findViewById(R.id.AutoExposureLockImageView);
+ aeLock.setOnClickListener(onTouchListener);
+
+ focusAssist = (ImageView) view.findViewById(R.id.FocusAssistImageView);
+ focusAssist.setOnClickListener(onTouchListener);
+*/
+ try
+ {
+ view.findViewById(R.id.show_preference_button).setOnClickListener(onClickListener);
+ view.findViewById(R.id.camera_property_settings_button).setOnClickListener(onClickListener);
+
+ showGrid = view.findViewById(R.id.show_hide_grid_button);
+ showGrid.setOnClickListener(onClickListener);
+ updateGridIcon();
+
+ connectStatus = view.findViewById(R.id.connect_disconnect_button);
+ connectStatus.setOnClickListener(onClickListener);
+ updateConnectionStatus();
+
+ statusArea = view.findViewById(R.id.informationMessageTextView);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return (view);
+ }
+
+ /**
+ *
+ */
+ public void prepare(IChangeScene sceneSelector)
+ {
+ this.changeScene = sceneSelector;
+ }
+
+
+ /**
+ * カメラとの接続状態の更新
+ *
+ */
+ @Override
+ public void updateConnectionStatus()
+ {
+ try
+ {
+ int id = R.drawable.ic_cloud_off_black_24dp;
+ connectStatus.setImageDrawable(ResourcesCompat.getDrawable(getResources(), id, null));
+ connectStatus.invalidate();
+ imageView.invalidate();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * グリッドの表示・非表示の更新
+ *
+ */
+ @Override
+ public void updateGridIcon()
+ {
+ try
+ {
+ int id = (imageView.isShowGrid()) ? R.drawable.ic_grid_off_black_24dp : R.drawable.ic_grid_on_black_24dp;
+ showGrid.setImageDrawable(ResourcesCompat.getDrawable(getResources(), id, null));
+ showGrid.invalidate();
+ imageView.invalidate();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 作例表示モードの画像のURIを応答する
+ *
+ * @return Uri : 作例表示する画像のURI
+ */
+ private Uri isSetupSampleImageFile(String fileName)
+ {
+ try
+ {
+ File file = new File(fileName);
+ if (file.exists())
+ {
+ Log.v(TAG, "isSetupSampleImageFile() : " + file.toString());
+ return (Uri.fromFile(file));
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+ Log.v(TAG, "isSetupSampleImageFile() : nothing");
+ return (null);
+ }
+
+ /**
+ * 画面下部の表示エリアの用途を切り替える
+ *
+ */
+ private void setupLowerDisplayArea()
+ {
+/*
+ ScalableImageViewPanel sampleImageView = (ScalableImageViewPanel) getActivity().findViewById(R.id.favoriteImageView);
+ PhoneCameraView phoneCameraView = (PhoneCameraView) getActivity().findViewById(R.id.phoneCameraView);
+
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
+ String value = preferences.getString(IPreferencePropertyAccessor.SHOW_SAMPLE_IMAGE, IPreferencePropertyAccessor.SHOW_SAMPLE_IMAGE_DEFAULT_VALUE);
+ if (value.equals("2"))
+ {
+ // 操作パネル表示モード
+ try
+ {
+ phoneCameraView.setVisibility(View.GONE);
+ sampleImageView.setVisibility(View.VISIBLE);
+ CameraControlPanel cameraPanel = new CameraControlPanel(sampleImageView, camera.getCameraPropertyProvider());
+ statusListener.setDelegateListener(cameraPanel);
+ sampleImageView.setOnClickListener(cameraPanel);
+ sampleImageView.setOnTouchListener(cameraPanel);
+ sampleImageView.setOnLongClickListener(cameraPanel);
+ sampleImageView.setCameraPanelDrawer(true, cameraPanel);
+ sampleImageView.invalidate();
+ return;
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ statusListener.setDelegateListener(null);
+ sampleImageView.setOnClickListener(null);
+ sampleImageView.setOnTouchListener(null);
+ sampleImageView.setOnLongClickListener(null);
+ sampleImageView.setCameraPanelDrawer(false, null);
+
+ Uri uri = null;
+ if (value.equals("1"))
+ {
+ // 作例表示用の画像を取得
+ uri = isSetupSampleImageFile(preferences.getString(IPreferencePropertyAccessor.SELECT_SAMPLE_IMAGE, ""));
+ }
+ if (uri != null)
+ {
+ // 作例表示モード
+ phoneCameraView.setVisibility(View.GONE);
+ sampleImageView.setVisibility(View.VISIBLE);
+ sampleImageView.setImageURI(uri);
+ sampleImageView.invalidate();
+ }
+ else
+ {
+ // デュアルカメラモード
+ phoneCameraView.setVisibility(View.VISIBLE);
+ sampleImageView.setVisibility(View.GONE);
+
+ // カメラの画像にタッチリスナを付与
+ phoneCameraView.setOnClickListener(onTouchListener);
+ phoneCameraView.setOnTouchListener(onTouchListener);
+ }
+*/
+ }
+
+ /**
+ *
+ *
+ *
+ */
+ @Override
+ public void onStart()
+ {
+ super.onStart();
+ Log.v(TAG, "onStart()");
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public void onResume()
+ {
+ super.onResume();
+ Log.v(TAG, "onResume() Start");
+/*
+ // 撮影モードかどうかを確認して、撮影モードではなかったら撮影モードに切り替える
+ if ((changeRunModeExecutor != null)&&(!changeRunModeExecutor.isRecordingMode()))
+ {
+ // Runモードを切り替える。(でも切り替えると、設定がクリアされてしまう...。
+ changeRunModeExecutor.changeRunMode(true);
+ }
+
+ // ステータスの変更を通知してもらう
+ camera.setCameraStatusListener(statusListener);
+
+ // 画面下部の表示エリアの用途を切り替える
+ setupLowerDisplayArea();
+
+ // propertyを取得
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getContext());
+
+ // グリッド・フォーカスアシストの情報を戻す
+ imageView.setShowGridFrame(preferences.getBoolean(IPreferencePropertyAccessor.SHOW_GRID_STATUS, false));
+ imageView.setFocusAssist(preferences.getBoolean(IPreferencePropertyAccessor.SHOW_FOCUS_ASSIST_STATUS, false));
+ updateCameraPropertyStatus();
+
+ // ステータスの初期情報を表示する
+ updateStatusView(camera.getCameraStatusSummary(statusListener));
+
+ // ライブビューの開始
+ camera.changeLiveViewSize(preferences.getString(IPreferencePropertyAccessor.LIVE_VIEW_QUALITY, IPreferencePropertyAccessor.LIVE_VIEW_QUALITY_DEFAULT_VALUE));
+ camera.setLiveViewListener(liveViewListener);
+ liveViewListener.setCameraLiveImageView(imageView);
+ camera.startLiveView();
+
+ // GPSボタンの更新
+ updateGpsTrackingStatus();
+
+ // デジタル水準器を有効にするかどうか
+ if (statusListener != null)
+ {
+ statusListener.updateLevelGaugeChecking();
+ }
+*/
+ Log.v(TAG, "onResume() End");
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public void onPause()
+ {
+ super.onPause();
+ Log.v(TAG, "onPause() Start");
+
+/*
+ // ライブビューの停止
+ camera.stopLiveView();
+ camera.setLiveViewListener(null);
+ liveViewListener.setCameraLiveImageView(null);
+
+ if (locationPicker != null)
+ {
+ // GPS監視の終了
+ locationPicker.controlGps(false);
+ camera.clearGeolocation();
+ }
+*/
+ Log.v(TAG, "onPause() End");
+ }
+
+ /**
+ * カメラクラスをセットする
+ *
+ */
+/*
+ public void setInterfaces(IOlyCameraCoordinator camera, MyInterfaceProvider factory)
+ {
+ Log.v(TAG, "setInterfaces()");
+ this.camera = camera;
+ this.factory = factory;
+ this.changeRunModeExecutor = camera.getChangeRunModeExecutor();
+
+ factory.setStatusInterface(this);
+ factory.setStatusViewDrawer(this);
+ //if (imageView != null)
+ {
+ // factory.setAutoFocusFrameDisplay(imageView);
+ }
+ }
+*/
+/*
+ @Override
+ public void updateFocusAssistStatus()
+ {
+ updateCameraPropertyStatus();
+ }
+
+ @Override
+ public void updateGridFrameStatus()
+ {
+ updateCameraPropertyStatus();
+ }
+
+ @Override
+ public void updateTakeMode()
+ {
+ updateCameraPropertyStatus();
+ }
+
+ @Override
+ public void updateDriveMode()
+ {
+ updateCameraPropertyStatus();
+ }
+
+ @Override
+ public void updateWhiteBalance()
+ {
+ updateCameraPropertyStatus();
+ }
+
+ @Override
+ public void updateBatteryLevel()
+ {
+ updateCameraPropertyStatus();
+ }
+
+ @Override
+ public void updateAeMode()
+ {
+ updateCameraPropertyStatus();
+ }
+
+ @Override
+ public void updateAeLockState()
+ {
+ updateCameraPropertyStatus();
+ }
+
+ @Override
+ public void updateCameraStatus()
+ {
+ updateCameraPropertyStatus();
+ }
+
+ @Override
+ public void updateCameraStatus(String message)
+ {
+ updateStatusView(message);
+ }
+*/
+/*
+ @Override
+ public void updateLevelGauge(String orientation, float roll, float pitch)
+ {
+ if (imageView == null)
+ {
+ return;
+ }
+
+ // レベルゲージ(デジタル水準器の情報)が更新されたとき
+ //Log.v(TAG, String.format(Locale.getDefault(), "LEVEL GAUGE : %s roll: %3.3f pitch: %3.3f", orientation, roll, pitch));
+ try
+ {
+ if ((Float.isNaN(roll))||(Float.isNaN(pitch)))
+ {
+ // roll と pitch のどちらかがNaNなら、表示を消す
+ imageView.getMessageDrawer().setMessageToShow(IMessageDrawer.MessageArea.LOWRIGHT, Color.argb(0xff, 0x6e, 0x6e, 0x6e), IMessageDrawer.SIZE_STD, "");
+ imageView.getMessageDrawer().setLevelToShow(IMessageDrawer.LevelArea.LEVEL_HORIZONTAL, Float.NaN);
+ imageView.getMessageDrawer().setLevelToShow(IMessageDrawer.LevelArea.LEVEL_VERTICAL, Float.NaN);
+ return;
+ }
+
+ // 傾きのデータを設定する
+ String message = String.format(Locale.getDefault(), "[%3.1f, %3.1f]", roll, pitch);
+ imageView.getMessageDrawer().setMessageToShow(IMessageDrawer.MessageArea.LOWRIGHT, Color.argb(0xff, 0x6e, 0x6e, 0x6e), IMessageDrawer.SIZE_STD, message);
+ imageView.getMessageDrawer().setLevelToShow(IMessageDrawer.LevelArea.LEVEL_HORIZONTAL, roll);
+ imageView.getMessageDrawer().setLevelToShow(IMessageDrawer.LevelArea.LEVEL_VERTICAL, pitch);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+*/
+/*
+ @Override
+ public void showFavoriteSettingDialog()
+ {
+ LoadSaveMyCameraPropertyDialog dialog = new LoadSaveMyCameraPropertyDialog();
+ dialog.setTargetFragment(this, COMMAND_MY_PROPERTY);
+ dialog.setPropertyOperationsHolder(new CameraPropertyLoadSaveOperations(getActivity(), camera.getLoadSaveCameraProperties(), this));
+ dialog.show(getChildFragmentManager(), "my_dialog");
+ }
+*/
+/*
+ @Override
+ public void toggleTimerStatus()
+ {
+ boolean isBracketing = !isBracketing();
+ SharedPreferences preferences = android.support.v7.preference.PreferenceManager.getDefaultSharedPreferences(getContext());
+ SharedPreferences.Editor editor = preferences.edit();
+ editor.putBoolean(IPreferencePropertyAccessor.USE_BRACKETING, isBracketing);
+ editor.apply();
+ if (bracketing != null)
+ {
+ bracketing.setSelected(isBracketing);
+ }
+ }
+
+ private boolean isBracketing()
+ {
+ SharedPreferences preferences = android.support.v7.preference.PreferenceManager.getDefaultSharedPreferences(getContext());
+ boolean isBracketing = false;
+ if (preferences != null)
+ {
+ isBracketing = preferences.getBoolean(IPreferencePropertyAccessor.USE_BRACKETING, false);
+ }
+ return (isBracketing);
+ }
+*/
+ /**
+ *
+ *
+ */
+/*
+ private void updateCameraPropertyStatus()
+ {
+ try
+ {
+ final boolean isManualFocus = camera.isManualFocus();
+ final boolean isAfLock = camera.isAFLock();
+ final boolean isAeLock = camera.isAELock();
+ final boolean isTimerOn = isBracketing();
+ boolean checkFocusAssist = false;
+ boolean checkShowGrid = false;
+ if (imageView != null)
+ {
+ checkFocusAssist = imageView.isFocusAssist();
+ checkShowGrid = imageView.isShowGrid();
+ }
+ final boolean isFocusAssist = checkFocusAssist;
+ final boolean isShowGrid = checkShowGrid;
+
+ runOnUiThread(new Runnable()
+ {
+ //カメラの状態(インジケータ)を更新する
+ @Override
+ public void run() {
+ if (camera == null) {
+ return;
+ }
+ Log.v(TAG, "--- UPDATE CAMERA PROPERTY (START) ---");
+ if (manualFocus != null) {
+ manualFocus.setSelected(isManualFocus);
+ }
+ if (afLock != null) {
+ afLock.setSelected(isAfLock);
+ }
+ if (aeLock != null) {
+ aeLock.setSelected(isAeLock);
+ }
+ if ((focusAssist != null) && (imageView != null)) {
+ focusAssist.setSelected(isFocusAssist);
+ }
+ if ((showGrid != null) && (imageView != null)) {
+ showGrid.setSelected(isShowGrid);
+ }
+ if (bracketing != null)
+ {
+ bracketing.setSelected(isTimerOn);
+ }
+ Log.v(TAG, "--- UPDATE CAMERA PROPERTY (END) ---");
+ }
+ });
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+*/
+
+ /**
+ *
+ *
+ */
+/*
+ @Override
+ public IMessageDrawer getMessageDrawer()
+ {
+ return (imageView.getMessageDrawer());
+ }
+*/
+ /**
+ * 表示エリアに文字を表示する
+ *
+ */
+ public void updateStatusView(String message)
+ {
+ messageValue = message;
+ runOnUiThread(new Runnable()
+ {
+ /**
+ * カメラの状態(ステータステキスト)を更新する
+ * (ステータステキストは、プライベート変数で保持して、書き換える)
+ */
+ @Override
+ public void run()
+ {
+ if (statusArea != null)
+ {
+ statusArea.setText(messageValue);
+ }
+ }
+ });
+ }
+/*
+ @Override
+ public void toggleGpsTracking()
+ {
+ if (locationPicker == null)
+ {
+ return;
+ }
+ locationPicker.controlGps(!locationPicker.isTracking());
+ updateGpsTrackingStatus();
+ }
+
+ @Override
+ public void updateGpsTrackingStatus()
+ {
+ Log.v(TAG, "updateGpsTrackingStatus()");
+ if ((myView == null)||(locationPicker == null))
+ {
+ Log.v(TAG, "updateGpsTrackingStatus() : null");
+ return;
+ }
+
+ ImageButton gps = (ImageButton) myView.findViewById(R.id.gpsLocationButton);
+ int id = R.drawable.btn_location_off;
+ if (locationPicker.isTracking())
+ {
+ if (locationPicker.isFixedLocation())
+ {
+ // 位置が確定している
+ id = R.drawable.btn_location_on;
+ }
+ else
+ {
+ // 位置検索中だが未確定...
+ id = R.drawable.btn_gps_not_fixed;
+ }
+ }
+ else
+ {
+ // 位置情報をクリアする
+ camera.clearGeolocation();
+ }
+ try
+ {
+ // ボタンの表示を変える
+ gps.setImageResource(id);
+ //gps.setImageDrawable(getContext().getResources().getDrawable(id));
+ gps.invalidate();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+*/
+
+
+ private void runOnUiThread(Runnable action)
+ {
+ Activity activity = getActivity();
+ if (activity == null)
+ {
+ return;
+ }
+ activity.runOnUiThread(action);
+ }
+}
--- /dev/null
+package net.osdn.gokigen.a01d.liveview;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.support.v7.widget.AppCompatImageView;
+import android.util.AttributeSet;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.View;
+
+/**
+ * イメージを表示する ... ImageViewerSampleから持ってくる
+ *
+ */
+public class ScalableImageViewPanel extends AppCompatImageView
+{
+
+ private static enum GestureMode {
+ None,
+ Move,
+ Zoom,
+ }
+
+ private ICameraPanelDrawer cameraPanelDrawer;
+ private boolean overrideDrawer;
+ private Context mContext;
+ private GestureDetector mDoubleTapDetector;
+ private GestureMode mGestureMode;
+
+ /** The affine transformation matrix. */
+ private Matrix mMatrix;
+
+ /** The horizontal moving factor after scaling. */
+ private float mMoveX;
+ /** The vertical moving factor after scaling. */
+ private float mMoveY;
+ /** The X-coordinate origin for calculating the amount of movement. */
+ private float mMovingBaseX;
+ /** The Y-coordinate origin for calculating the amount of movement. */
+ private float mMovingBaseY;
+
+ /** The scaling factor. */
+ private float mScale;
+ /** The minimum value of scaling factor. */
+ private float mScaleMin;
+ /** The maximum value of scaling factor. */
+ private float mScaleMax;
+ /** The distance from the center for determining the amount of scaling. */
+ private float mScalingBaseDistance;
+ /** The center X-coordinate to determine the amount of scaling. */
+ private float mScalingCenterX;
+ /** The center Y-coordinate to determine the amount of scaling. */
+ private float mScalingCenterY;
+
+ /** The width of the view. */
+ private int mViewWidth;
+ /** The height of the view. */
+ private int mViewHeight;
+ /** The width of the image. */
+ private int mImageWidth;
+ /** The height of the image. */
+ private int mImageHeight;
+
+
+ @Override
+ public void setImageDrawable(Drawable drawable) {
+ super.setImageDrawable(drawable);
+ reset();
+ };
+
+ @Override
+ public void setImageBitmap(Bitmap bm) {
+ super.setImageBitmap(bm);
+ reset();
+ };
+
+ @Override
+ public void setImageURI(Uri uri) {
+ super.setImageURI(uri);
+ reset();
+ }
+
+ /**
+ *
+ *
+ */
+ public void setCameraPanelDrawer(boolean isOverrideDrawer, ICameraPanelDrawer drawer)
+ {
+ this.overrideDrawer = isOverrideDrawer;
+ this.cameraPanelDrawer = drawer;
+ }
+
+ /**
+ * Constructs a new CapturedImageView.
+ *
+ * @param context
+ */
+ public ScalableImageViewPanel(Context context) {
+ super(context);
+ mContext = context;
+ init();
+ }
+
+ /**
+ * Constructs a new CapturedImageView.
+ *
+ * @param context
+ * @param attrs
+ */
+ public ScalableImageViewPanel(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mContext = context;
+ init();
+ }
+
+ /**
+ * Constructs a new CapturedImageView.
+ *
+ * @param context
+ * @param attrs
+ * @param defStyle
+ */
+ public ScalableImageViewPanel(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ mContext = context;
+ init();
+ }
+
+ /**
+ * Initializes this instance.
+ */
+ private void init() {
+ this.cameraPanelDrawer = null;
+ this.overrideDrawer = false;
+ this.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+ this.setScaleType(ScaleType.MATRIX);
+ mMatrix = new Matrix();
+ mViewWidth = 0;
+ mViewHeight = 0;
+ mImageWidth = 0;
+ mImageHeight = 0;
+ mGestureMode = GestureMode.None;
+ mMoveX = 0;
+ mMoveY = 0;
+ mScale = 1.f;
+ mScaleMin = 1.f;
+ mScaleMax = 4.f;
+
+ // Setups touch gesture.
+ mDoubleTapDetector = new GestureDetector(mContext, new GestureDetector.SimpleOnGestureListener() {
+ @Override
+ public boolean onDoubleTap(MotionEvent e) {
+ if (mScale != 1.0f) {
+ // Zooms at tapped point.
+ updateScaleWithBasePoint(1.0f, e.getX(), e.getY());
+ } else {
+ // Zooms out.
+ fitScreen();
+ }
+ updateMatrix();
+ return true;
+ }
+ });
+ }
+
+ /**
+ * Resets current scaling.
+ */
+ private void reset() {
+ Drawable drawable = this.getDrawable();
+ if (drawable != null) {
+ mImageWidth = drawable.getIntrinsicWidth();
+ mImageHeight = drawable.getIntrinsicHeight();
+ fitScreen();
+ updateMatrix();
+ }
+ }
+
+ @Override
+ protected boolean setFrame(int l, int t, int r, int b) {
+ mViewWidth = r - l;
+ mViewHeight = b - t;
+ if (this.getDrawable() != null) {
+ fitScreen();
+ }
+ updateMatrix();
+ return super.setFrame(l, t, r, b);
+ }
+
+ /**
+ * Returns a scaled X offset.
+ *
+ * @param scale A scaling factor.
+ * @param moveX A horizontal moving factor.
+ * @return A scaled X offset.
+ */
+ private float computeOffsetX(float scale, float moveX) {
+ // Offsets in order to center the image.
+ float scaledWidth = scale * mImageWidth;
+ float offsetX = (mViewWidth - scaledWidth) / 2;
+ // Moves specified offset.
+ offsetX += moveX;
+ return offsetX;
+ }
+
+ /**
+ * Returns a scaled Y offset.
+ *
+ * @param scale A scaling factor.
+ * @param moveY A vertical moving factor.
+ * @return A scaled Y offset.
+ */
+ private float computeOffsetY(float scale, float moveY) {
+ // Offsets in order to center the image.
+ float scaledHeight = scale * mImageHeight;
+ float offsetY = (mViewHeight - scaledHeight) / 2;
+ // Moves specified offset.
+ offsetY += moveY;
+ return offsetY;
+ }
+
+ /**
+ * Updates affine transformation matrix to display the image.
+ */
+ private void updateMatrix() {
+ // Creates new matrix.
+ mMatrix.reset();
+ mMatrix.postScale(mScale, mScale);
+ mMatrix.postTranslate(computeOffsetX(mScale, mMoveX), computeOffsetY(mScale, mMoveY));
+
+ // Updates the matrix.
+ this.setImageMatrix(mMatrix);
+ this.invalidate();
+ }
+
+ /**
+ * Calculates zoom scale. (for the image size to fit screen size).
+ */
+ private void fitScreen() {
+ if ((mImageWidth == 0) || (mImageHeight == 0) || (mViewWidth == 0) || (mViewHeight == 0)) {
+ return;
+ }
+
+ // Clears the moving factors.
+ updateMove(0, 0);
+
+ // Gets scaling ratio.
+ float scaleX = (float)mViewWidth / mImageWidth;
+ float scaleY = (float)mViewHeight / mImageHeight;
+
+ // Updates the scaling factor so that the image will not be larger than the screen size.
+ mScale = Math.min(scaleX, scaleY);
+ mScaleMin = mScale;
+ // 4 times of original image size or 4 times of the screen size.
+ mScaleMax = Math.max(4.f, mScale * 4);
+ }
+
+ /**
+ * Updates the moving factors.
+ *
+ * @param moveX A horizontal moving factor.
+ * @param moveY A vertical moving factor.
+ */
+ protected void updateMove(float moveX, float moveY) {
+ mMoveX = moveX;
+ mMoveY = moveY;
+
+ // Gets scaled size.
+ float scaledWidth = mImageWidth * mScale;
+ float scaledHeight = mImageHeight * mScale;
+
+ // Clips the moving factors.
+ if (scaledWidth <= mViewWidth) {
+ mMoveX = 0;
+ } else {
+ float minMoveX = -(scaledWidth - mViewWidth) / 2;
+ float maxMoveX = +(scaledWidth - mViewWidth) / 2;
+ mMoveX = Math.min(Math.max(mMoveX, minMoveX), maxMoveX);
+ }
+ if (scaledHeight <= mViewHeight) {
+ mMoveY = 0;
+ } else {
+ float minMoveY = -(scaledHeight - mViewHeight) / 2;
+ float maxMoveY = +(scaledHeight - mViewHeight) / 2;
+ mMoveY = Math.min(Math.max(mMoveY, minMoveY), maxMoveY);
+ }
+ }
+
+ /**
+ * Updates the scaling factor. The specified point doesn't change in appearance.
+ *
+ * @param newScale The new scaling factor.
+ * @param baseX The center position of scaling.
+ * @param baseY The center position of scaling.
+ */
+ protected void updateScaleWithBasePoint(float newScale, float baseX, float baseY) {
+ float lastScale = mScale;
+ float lastOffsetX = computeOffsetX(mScale, mMoveX);
+ float lastOffsetY = computeOffsetY(mScale, mMoveY);
+
+ // Updates the scale with clipping.
+ mScale = Math.min(Math.max(newScale, mScaleMin), mScaleMax);
+ mScalingCenterX = baseX;
+ mScalingCenterY = baseY;
+
+ // Gets scaling base point on the image world.
+ float scalingCenterXOnImage = (mScalingCenterX - lastOffsetX) / lastScale;
+ float scalingCenterYOnImage = (mScalingCenterY - lastOffsetY) / lastScale;
+ // Gets scaling base point on the scaled image world.
+ float scalingCenterXOnScaledImage = scalingCenterXOnImage * mScale;
+ float scalingCenterYOnScaledImage = scalingCenterYOnImage * mScale;
+ // Gets scaling base point on the view world.
+ float scalingCenterXOnView = computeOffsetX(mScale, 0) + scalingCenterXOnScaledImage;
+ float scalingCenterYOnView = computeOffsetY(mScale, 0) + scalingCenterYOnScaledImage;
+
+ // Updates moving.
+ updateMove(mScalingCenterX - scalingCenterXOnView, mScalingCenterY - scalingCenterYOnView);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (mDoubleTapDetector.onTouchEvent(event)) {
+ return true;
+ }
+
+ int action = event.getAction() & MotionEvent.ACTION_MASK;
+ int touchCount = event.getPointerCount();
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ if (mScale > mScaleMin) {
+ // Starts to move the image and takes in the start point.
+ mGestureMode = GestureMode.Move;
+ mMovingBaseX = event.getX();
+ mMovingBaseY = event.getY();
+ }
+ break;
+ case MotionEvent.ACTION_POINTER_DOWN:
+ if (touchCount >= 2) {
+ // Starts zooming and takes in the center point.
+ mGestureMode = GestureMode.Zoom;
+ float distance = (float)Math.hypot(event.getX(0) - event.getX(1), event.getY(0) - event.getY(1));
+ mScalingBaseDistance = distance;
+ mScalingCenterX = (event.getX(0) + event.getX(1)) / 2;
+ mScalingCenterY = (event.getY(0) + event.getY(1)) / 2;
+ }
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (mGestureMode == GestureMode.Move) {
+ // Moves the image and updates the start point.
+ float moveX = event.getX() - mMovingBaseX;
+ float moveY = event.getY() - mMovingBaseY;
+ mMovingBaseX = event.getX();
+ mMovingBaseY = event.getY();
+ updateMove(mMoveX + moveX, mMoveY + moveY);
+ updateMatrix();
+ } else if ((mGestureMode == GestureMode.Zoom) && (touchCount >= 2)) {
+ // Zooms the image and updates the distance from the center point.
+ float distance = (float)Math.hypot(event.getX(0) - event.getX(1), event.getY(0) - event.getY(1));
+ float scale = distance / mScalingBaseDistance;
+ mScalingBaseDistance = distance;
+ updateScaleWithBasePoint(mScale * scale, mScalingCenterX, mScalingCenterY);
+ updateMatrix();
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_POINTER_UP:
+ // Finishes all gestures.
+ mGestureMode = GestureMode.None;
+ break;
+ }
+ return true;
+ }
+
+ // The content in view can scroll to horizontal.
+ public boolean canHorizontalScroll()
+ {
+ if (mScale == mScaleMin) {
+ return false;
+ }
+ if (mGestureMode == GestureMode.None)
+ {
+ return false;
+ }
+
+ // TODO: Please improve UX.
+ // If the view rectangle is touching to the edge of the image, the view cannot be scrolled.
+
+ return true;
+ }
+
+ /**
+ * Draw on Canvas
+ *
+ */
+ @Override
+ public void onDraw(Canvas canvas)
+ {
+ if (!overrideDrawer)
+ {
+ super.onDraw(canvas);
+ }
+ if (cameraPanelDrawer != null)
+ {
+ cameraPanelDrawer.drawCameraPanel(canvas);
+ }
+ }
+}
--- /dev/null
+package net.osdn.gokigen.a01d.liveview.bitmapconvert;
+
+import android.graphics.Bitmap;
+
+/**
+ *
+ *
+ */
+class ConvertNothing implements IPreviewImageConverter
+{
+ /**
+ * 変換後のビットマップを応答する
+ *
+ * @return 変換後のビットマップ
+ */
+ @Override
+ public Bitmap getModifiedBitmap(Bitmap src)
+ {
+ return (src);
+ }
+}
--- /dev/null
+package net.osdn.gokigen.a01d.liveview.bitmapconvert;
+
+import android.graphics.Bitmap;
+
+/**
+ * ビットマップ変換
+ */
+public interface IPreviewImageConverter
+{
+ Bitmap getModifiedBitmap(Bitmap src);
+}
--- /dev/null
+package net.osdn.gokigen.a01d.liveview.bitmapconvert;
+
+/**
+ *
+ *
+ */
+public class ImageConvertFactory
+{
+ private static final int CONVERT_TYPE_0 = 0;
+ private static final int CONVERT_TYPE_1 = 1;
+ private static final int CONVERT_TYPE_2 = 2;
+ private static final int CONVERT_TYPE_3 = 3;
+ private static final int CONVERT_TYPE_4 = 4;
+ private static final int CONVERT_TYPE_5 = 5;
+ private static final int CONVERT_TYPE_6 = 6;
+
+ public static IPreviewImageConverter getImageConverter(int id)
+ {
+ IPreviewImageConverter drawer = new ConvertNothing();
+ return (drawer);
+ }
+}
--- /dev/null
+package net.osdn.gokigen.a01d.liveview.gridframe;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.RectF;
+
+/**
+ * 対角線のグリッド表示
+ */
+public class GridFrameDrawerDefault implements IGridFrameDrawer
+{
+ /**
+ *
+ *
+ */
+ @Override
+ public void drawFramingGrid(Canvas canvas, RectF rect, Paint paint)
+ {
+ float w = (rect.right - rect.left) / 3.0f;
+ float h = (rect.bottom - rect.top) / 3.0f;
+
+ canvas.drawLine(rect.left + w, rect.top, rect.left + w, rect.bottom, paint);
+ canvas.drawLine(rect.left + 2.0f * w, rect.top, rect.left + 2.0f * w, rect.bottom, paint);
+ canvas.drawLine(rect.left, rect.top + h, rect.right, rect.top + h, paint);
+ canvas.drawLine(rect.left, rect.top + 2.0f * h, rect.right, rect.top + 2.0f * h, paint);
+ canvas.drawRect(rect, paint);
+ }
+
+ @Override
+ public int getDrawColor()
+ {
+ return (Color.argb(130,235,235,235));
+ }
+}
--- /dev/null
+package net.osdn.gokigen.a01d.liveview.gridframe;
+
+/**
+ *
+ *
+ */
+public class GridFrameFactory
+{
+ private static final int GRID_FRAME_0 = 0;
+ private static final int GRID_FRAME_1 = 1;
+ private static final int GRID_FRAME_2 = 2;
+ private static final int GRID_FRAME_3 = 3;
+ private static final int GRID_FRAME_4 = 4;
+ private static final int GRID_FRAME_5 = 5;
+ private static final int GRID_FRAME_6 = 6;
+
+ public static IGridFrameDrawer getGridFrameDrawer(int id)
+ {
+ return (new GridFrameDrawerDefault());
+ }
+}
--- /dev/null
+package net.osdn.gokigen.a01d.liveview.gridframe;
+
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RectF;
+
+/**
+ * 撮影補助線の描画クラス
+ *
+ */
+public interface IGridFrameDrawer
+{
+ void drawFramingGrid(Canvas canvas, RectF rect, Paint paint);
+ int getDrawColor();
+}
--- /dev/null
+package net.osdn.gokigen.a01d.liveview.message;
+
+public interface IMessageDrawer
+{
+ // メッセージを表示する位置
+ enum MessageArea
+ {
+ UPLEFT,
+ UPRIGHT,
+ CENTER,
+ LOWLEFT,
+ LOWRIGHT,
+ UPCENTER,
+ LOWCENTER,
+ LEFTCENTER,
+ RIGHTCENTER,
+ }
+
+ enum LevelArea
+ {
+ LEVEL_HORIZONTAL,
+ LEVEL_VERTICAL,
+ }
+
+ int SIZE_STD = 16;
+ int SIZE_LARGE = 24;
+ int SIZE_BIG = 32;
+
+ void setMessageToShow(MessageArea area, int color, int size, String message);
+ void setLevelToShow(LevelArea area, float value);
+
+}
--- /dev/null
+package net.osdn.gokigen.a01d.liveview.message;
+
+public interface IMessageHolder
+{
+ int getSize(IMessageDrawer.MessageArea area);
+ int getColor(IMessageDrawer.MessageArea area);
+ String getMessage(IMessageDrawer.MessageArea area);
+
+ boolean isLevel();
+ float getLevel(IMessageDrawer.LevelArea area);
+ int getLevelColor(float value);
+ IMessageDrawer getMessageDrawer();
+}
--- /dev/null
+package net.osdn.gokigen.a01d.liveview.message;
+
+import android.graphics.Color;
+import android.view.ViewDebug;
+
+/**
+ *
+ *
+ * Created by MRSa on 2017/03/01.
+ */
+public class ShowMessageHolder implements IMessageDrawer, IMessageHolder
+{
+ /**
+ *
+ */
+ private class messageHolder
+ {
+ private String message = "";
+ private int color = Color.BLUE;
+ private int textSize = 16;
+
+ String getMessage()
+ {
+ return message;
+ }
+
+ void setMessage(String message)
+ {
+ this.message = message;
+ }
+
+ int getColor()
+ {
+ return color;
+ }
+
+ void setColor(int color)
+ {
+ this.color = color;
+ }
+
+ int getTextSize()
+ {
+ return textSize;
+ }
+
+ void setTextSize(int textSize)
+ {
+ this.textSize = textSize;
+ }
+ }
+
+ private messageHolder upperLeft = new messageHolder();
+ private messageHolder upperRight = new messageHolder();
+ private messageHolder center = new messageHolder();
+ private messageHolder lowerLeft = new messageHolder();
+ private messageHolder lowerRight = new messageHolder();
+ private messageHolder upperCenter = new messageHolder();
+ private messageHolder lowerCenter = new messageHolder();
+ private messageHolder leftCenter = new messageHolder();
+ private messageHolder rightCenter = new messageHolder();
+ private float level_horizontal = Float.NaN;
+ private float level_vertical = Float.NaN;
+
+ private float LEVELGAUGE_THRESHOLD_MIDDLE = 2.0f;
+ private float LEVELGAUGE_THRESHOLD_OVER = 15.0f;
+
+ /**
+ * コンストラクタ
+ *
+ */
+ public ShowMessageHolder()
+ {
+ center.setTextSize(24);
+ }
+
+ /**
+ *
+ *
+ */
+ private messageHolder decideHolder(MessageArea area)
+ {
+ messageHolder target;
+ switch (area)
+ {
+ case CENTER:
+ target = center;
+ break;
+
+ case UPLEFT:
+ target = upperLeft;
+ break;
+
+ case UPRIGHT:
+ target = upperRight;
+ break;
+
+ case LOWLEFT:
+ target = lowerLeft;
+ break;
+
+ case LOWRIGHT:
+ target = lowerRight;
+ break;
+
+ case UPCENTER:
+ target = upperCenter;
+ break;
+
+ case LOWCENTER:
+ target = lowerCenter;
+ break;
+
+ case LEFTCENTER:
+ target = leftCenter;
+ break;
+
+ case RIGHTCENTER:
+ target = rightCenter;
+ break;
+
+ default:
+ target = null;
+ break;
+ }
+ return (target);
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public void setMessageToShow(MessageArea area, int color, int size, String message)
+ {
+ messageHolder target = decideHolder(area);
+ if (target != null)
+ {
+ target.setColor(color);
+ target.setTextSize(size);
+ target.setMessage(message);
+ }
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public void setLevelToShow(LevelArea area, float value)
+ {
+ if (area == LevelArea.LEVEL_HORIZONTAL)
+ {
+ level_horizontal = value;
+ }
+ else if (area == LevelArea.LEVEL_VERTICAL)
+ {
+ level_vertical = value;
+ }
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public int getSize(MessageArea area)
+ {
+ messageHolder target = decideHolder(area);
+ if (target != null)
+ {
+ return (target.getTextSize());
+ }
+ return (0);
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public int getColor(MessageArea area)
+ {
+ messageHolder target = decideHolder(area);
+ if (target != null)
+ {
+ return (target.getColor());
+ }
+ return (0);
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public String getMessage(MessageArea area)
+ {
+ messageHolder target = decideHolder(area);
+ if (target != null)
+ {
+ return (target.getMessage());
+ }
+ return ("");
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public boolean isLevel()
+ {
+ return (!((Float.isNaN(level_horizontal))||(Float.isNaN(level_vertical))));
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public float getLevel(LevelArea area)
+ {
+ float value;
+ if (area == LevelArea.LEVEL_HORIZONTAL)
+ {
+ value = level_horizontal;
+ }
+ else // if (area == LevelArea.LEVEL_VERTICAL)
+ {
+ value = level_vertical;
+ }
+ return (value);
+ }
+
+ /**
+ * 傾きの色を取得する
+ *
+ */
+ @Override
+ public int getLevelColor(float value)
+ {
+ value = Math.abs(value);
+
+ if (value < LEVELGAUGE_THRESHOLD_MIDDLE)
+ {
+ return (Color.GREEN);
+ }
+ if (value > LEVELGAUGE_THRESHOLD_OVER)
+ {
+ return (Color.RED);
+ }
+ return (Color.YELLOW);
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public IMessageDrawer getMessageDrawer()
+ {
+ return (this);
+ }
+}
--- /dev/null
+package net.osdn.gokigen.a01d.preference;
+
+/**
+ *
+ *
+ *
+ */
+public interface IPreferencePropertyAccessor
+{
+ String EXIT_APPLICATION = "exit_application";
+
+ String AUTO_CONNECT_TO_CAMERA = "auto_connect_to_camera";
+
+ String TAKE_MODE = "take_mode";
+ String TAKE_MODE_DEFAULT_VALUE = "P";
+
+ String SOUND_VOLUME_LEVEL = "sound_volume_level";
+ String SOUND_VOLUME_LEVEL_DEFAULT_VALUE = "OFF";
+
+ String RAW = "raw";
+
+ String LIVE_VIEW_QUALITY = "live_view_quality";
+ String LIVE_VIEW_QUALITY_DEFAULT_VALUE = "QVGA";
+
+ String CAMERAKIT_VERSION = "camerakit_version";
+
+ String SHOW_GRID_STATUS = "show_grid";
+/*****
+ int CHOICE_SPLASH_SCREEN = 10;
+
+ int SELECT_SAMPLE_IMAGE_CODE = 110;
+ int SELECT_SPLASH_IMAGE_CODE = 120;
+
+ String getLiveViewSize();
+ void restoreCameraSettings(Callback callback);
+ void storeCameraSettings(Callback callback);
+
+ interface Callback
+ {
+ void stored(boolean result);
+ void restored(boolean result);
+ }
+*****/
+
+}
--- /dev/null
+package net.osdn.gokigen.a01d.preference;
+
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.support.v7.preference.CheckBoxPreference;
+import android.support.v7.preference.ListPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceFragmentCompat;
+import android.support.v7.preference.PreferenceManager;
+import android.util.Log;
+
+import net.osdn.gokigen.a01d.IChangeScene;
+import net.osdn.gokigen.a01d.R;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.ICameraHardwareStatus;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.ICameraRunMode;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.IOlyCameraProperty;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.IOlyCameraPropertyProvider;
+import net.osdn.gokigen.a01d.camera.olympus.IOlympusInterfaceProvider;
+import net.osdn.gokigen.a01d.camera.olympus.operation.CameraPowerOff;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import jp.co.olympus.camerakit.OLYCamera;
+
+
+/**
+ * SettingFragment
+ *
+ */
+public class PreferenceFragment extends PreferenceFragmentCompat implements SharedPreferences.OnSharedPreferenceChangeListener, PreferenceSynchronizer.IPropertySynchronizeCallback
+{
+ private final String TAG = toString();
+ private IOlyCameraPropertyProvider propertyInterface = null;
+ private ICameraHardwareStatus hardwareStatusInterface = null;
+ private ICameraRunMode changeRunModeExecutor = null;
+ private CameraPowerOff powerOffController = null;
+ private SharedPreferences preferences = null;
+ private ProgressDialog busyDialog = null;
+ private PreferenceSynchronizer preferenceSynchronizer = null;
+
+ public void setInterface(Context context, IOlympusInterfaceProvider factory, IChangeScene changeScene)
+ {
+ Log.v(TAG, "setInterface()");
+ this.propertyInterface = factory.getCameraPropertyProvider();
+ this.changeRunModeExecutor = factory.getCameraRunMode();
+ hardwareStatusInterface = factory.getHardwareStatus();
+ powerOffController = new CameraPowerOff(context, changeScene);
+ powerOffController.prepare();
+ }
+
+ /**
+ *
+ *
+ */
+ @Override
+ public void onAttach(Context activity)
+ {
+ super.onAttach(activity);
+ Log.v(TAG, "onAttach()");
+
+ // Preference をつかまえる
+ preferences = PreferenceManager.getDefaultSharedPreferences(activity);
+ if (preferenceSynchronizer == null)
+ {
+ preferenceSynchronizer = new PreferenceSynchronizer(this.propertyInterface, preferences, this);
+ }
+
+ // Preference を初期設定する
+ initializePreferences();
+
+ preferences.registerOnSharedPreferenceChangeListener(this);
+ }
+
+ /**
+ * Preferenceの初期化...
+ */
+ private void initializePreferences()
+ {
+ Map<String, ?> items = preferences.getAll();
+ SharedPreferences.Editor editor = preferences.edit();
+
+ if (!items.containsKey(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.TAKE_MODE))
+ {
+ editor.putString(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.TAKE_MODE, net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.TAKE_MODE_DEFAULT_VALUE);
+ }
+ if (!items.containsKey(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.LIVE_VIEW_QUALITY))
+ {
+ editor.putString(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.LIVE_VIEW_QUALITY, net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.LIVE_VIEW_QUALITY_DEFAULT_VALUE);
+ }
+ if (!items.containsKey(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL))
+ {
+ editor.putString(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL, net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL_DEFAULT_VALUE);
+ }
+ if (!items.containsKey(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.RAW))
+ {
+ editor.putBoolean(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.RAW, true);
+ }
+ if (!items.containsKey(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL))
+ {
+ editor.putString(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL, net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL_DEFAULT_VALUE);
+ }
+ editor.apply();
+ }
+
+ @Override
+ public void onCreatePreferences(Bundle savedInstanceState, String rootKey)
+ {
+ Log.v(TAG, "onCreatePreferences()");
+
+ //super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.preferences);
+
+ {
+ final HashMap<String, String> sizeTable = new HashMap<>();
+ sizeTable.put("QVGA", "(320x240)");
+ sizeTable.put("VGA", "(640x480)");
+ sizeTable.put("SVGA", "(800x600)");
+ sizeTable.put("XGA", "(1024x768)");
+ sizeTable.put("QUAD_VGA", "(1280x960)");
+
+ ListPreference liveViewQuality = (ListPreference) findPreference(IPreferencePropertyAccessor.LIVE_VIEW_QUALITY);
+ liveViewQuality.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ String key = (String) newValue;
+ preference.setSummary(newValue + " " + sizeTable.get(key));
+ return (true);
+ }
+ });
+ liveViewQuality.setSummary(liveViewQuality.getValue() + " " + sizeTable.get(liveViewQuality.getValue()));
+ }
+
+ findPreference("exit_application").setOnPreferenceClickListener(powerOffController);
+ }
+
+ /**
+ * ハードウェアのサマリ情報を取得し設定する
+ */
+ private void setHardwareSummary()
+ {
+ // レンズ状態
+ findPreference("lens_status").setSummary(hardwareStatusInterface.getLensMountStatus());
+
+ // メディア状態
+ findPreference("media_status").setSummary(hardwareStatusInterface.getMediaMountStatus());
+
+ // 焦点距離
+ String focalLength;
+ float minLength = hardwareStatusInterface.getMinimumFocalLength();
+ float maxLength = hardwareStatusInterface.getMaximumFocalLength();
+ float actualLength = hardwareStatusInterface.getActualFocalLength();
+ if (minLength == maxLength)
+ {
+ focalLength = String.format(Locale.ENGLISH, "%3.0fmm", actualLength);
+ }
+ else
+ {
+ focalLength = String.format(Locale.ENGLISH, "%3.0fmm - %3.0fmm (%3.0fmm)", minLength, maxLength, actualLength);
+ }
+ findPreference("focal_length").setSummary(focalLength);
+
+ // カメラのバージョン
+ try
+ {
+ Map<String, Object> hardwareInformation = hardwareStatusInterface.inquireHardwareInformation();
+ findPreference("camera_version").setSummary((String) hardwareInformation.get(OLYCamera.HARDWARE_INFORMATION_CAMERA_FIRMWARE_VERSION_KEY));
+
+ // 取得した一覧はログに出力する。)
+ Log.v(TAG, "- - - - - - - - - -");
+ for (Map.Entry<String, Object> entry : hardwareInformation.entrySet())
+ {
+ String value = (String) entry.getValue();
+ Log.v(TAG, entry.getKey() + " : " + value);
+ }
+ Log.v(TAG, "- - - - - - - - - -");
+ }
+ catch (Exception e)
+ {
+ findPreference("camera_version").setSummary("Unknown");
+ }
+ }
+
+ private void setCameraProperty(String name, String value)
+ {
+ try
+ {
+ String propertyValue = "<" + name + "/" + value + ">";
+ Log.v(TAG, "setCameraProperty() : " + propertyValue);
+ propertyInterface.setCameraPropertyValue(name, propertyValue);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onResume()
+ {
+ super.onResume();
+ Log.v(TAG, "onResume() Start");
+
+ // 撮影モードかどうかを確認して、撮影モードではなかったら撮影モードに切り替える
+ if ((changeRunModeExecutor != null) && (!changeRunModeExecutor.isRecordingMode()))
+ {
+ // Runモードを切り替える。(でも切り替えると、設定がクリアされてしまう...。
+ changeRunModeExecutor.changeRunMode(true);
+ }
+ synchronizeCameraProperties(true);
+ Log.v(TAG, "onResume() End");
+
+ }
+
+ @Override
+ public void onPause()
+ {
+ super.onPause();
+ Log.v(TAG, "onPause() Start");
+
+ // Preference変更のリスナを解除
+ preferences.unregisterOnSharedPreferenceChangeListener(this);
+
+ Log.v(TAG, "onPause() End");
+ }
+
+ /**
+ * カメラプロパティとPreferenceとの同期処理を実行
+ */
+ private void synchronizeCameraProperties(boolean isPropertyLoad)
+ {
+ // 実行中ダイアログを取得する
+ busyDialog = new ProgressDialog(getActivity());
+ busyDialog.setTitle(getString(R.string.dialog_title_loading_properties));
+ busyDialog.setMessage(getString(R.string.dialog_message_loading_properties));
+ busyDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
+ busyDialog.setCancelable(false);
+ busyDialog.show();
+
+ // データ読み込み処理(別スレッドで実行)
+ if (isPropertyLoad)
+ {
+ new Thread(preferenceSynchronizer).start();
+ }
+ }
+
+ /**
+ * Preferenceが更新された時に呼び出される処理
+ *
+ * @param sharedPreferences sharedPreferences
+ * @param key 変更されたキー
+ */
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
+ {
+ Log.v(TAG, "onSharedPreferenceChanged() : " + key);
+ String propertyValue;
+ boolean value;
+ if (key != null)
+ {
+ switch (key)
+ {
+ case IPreferencePropertyAccessor.RAW:
+ value = preferences.getBoolean(key, true);
+ setBooleanPreference(key, key, value);
+ propertyValue = (value) ? "ON" : "OFF";
+ setCameraProperty(IOlyCameraProperty.RAW, propertyValue);
+ break;
+
+ case IPreferencePropertyAccessor.AUTO_CONNECT_TO_CAMERA:
+ value = preferences.getBoolean(key, true);
+ Log.v(TAG, " " + key + " , " + value);
+ break;
+
+ default:
+ String strValue = preferences.getString(key, "");
+ setListPreference(key, key, strValue);
+ String propertyKey = convertKeyFromPreferenceToCameraPropertyKey(key);
+ if (propertyKey != null)
+ {
+ setCameraProperty(propertyKey, strValue);
+ }
+ break;
+ }
+ }
+ }
+
+ /**
+ * ListPreference の表示データを設定
+ *
+ * @param pref_key Preference(表示)のキー
+ * @param key Preference(データ)のキー
+ * @param defaultValue Preferenceのデフォルト値
+ */
+ private void setListPreference(String pref_key, String key, String defaultValue)
+ {
+ ListPreference pref;
+ pref = (ListPreference) findPreference(pref_key);
+ String value = preferences.getString(key, defaultValue);
+ if (pref != null)
+ {
+ pref.setValue(value);
+ pref.setSummary(value);
+ }
+ }
+
+ /**
+ * BooleanPreference の表示データを設定
+ *
+ * @param pref_key Preference(表示)のキー
+ * @param key Preference(データ)のキー
+ * @param defaultValue Preferenceのデフォルト値
+ */
+ private void setBooleanPreference(String pref_key, String key, boolean defaultValue)
+ {
+ CheckBoxPreference pref = (CheckBoxPreference) findPreference(pref_key);
+ if (pref != null)
+ {
+ boolean value = preferences.getBoolean(key, defaultValue);
+ pref.setChecked(value);
+ }
+ }
+
+ /**
+ *
+ *
+ */
+ private String convertKeyFromPreferenceToCameraPropertyKey(String key)
+ {
+ String target = null;
+ if (key == null)
+ {
+ return (null);
+ }
+ switch (key)
+ {
+ case IPreferencePropertyAccessor.TAKE_MODE:
+ target = IOlyCameraProperty.TAKE_MODE;
+ break;
+
+ case IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL:
+ target = IOlyCameraProperty.SOUND_VOLUME_LEVEL;
+ break;
+
+ default:
+ // target == null
+ break;
+ }
+ return (target);
+ }
+
+ /**
+ * カメラプロパティの同期処理終了通知
+ */
+ @Override
+ public void synchronizedProperty()
+ {
+ Activity activity = getActivity();
+ if (activity == null)
+ {
+ try
+ {
+ busyDialog.dismiss();
+ busyDialog = null;
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return;
+ }
+ activity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ // Preferenceの画面に反映させる
+ setListPreference(IPreferencePropertyAccessor.TAKE_MODE, IPreferencePropertyAccessor.TAKE_MODE, net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.TAKE_MODE_DEFAULT_VALUE);
+ setListPreference(IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL, IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL, net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL_DEFAULT_VALUE);
+ setBooleanPreference(IPreferencePropertyAccessor.RAW, IPreferencePropertyAccessor.RAW, true);
+
+ // カメラキットのバージョン
+ findPreference(IPreferencePropertyAccessor.CAMERAKIT_VERSION).setSummary(OLYCamera.getVersion());
+ if (hardwareStatusInterface != null)
+ {
+ // その他のハードウェア情報の情報設定
+ setHardwareSummary();
+ }
+
+ // 実行中ダイアログを消す
+ busyDialog.dismiss();
+ busyDialog = null;
+ } catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+
+}
--- /dev/null
+package net.osdn.gokigen.a01d.preference;
+
+import android.content.SharedPreferences;
+import android.util.Log;
+
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.IOlyCameraProperty;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.IOlyCameraPropertyProvider;
+import net.osdn.gokigen.a01d.camera.olympus.wrapper.CameraPropertyUtilities;
+
+class PreferenceSynchronizer implements Runnable
+{
+ private final String TAG = toString();
+ private final IOlyCameraPropertyProvider propertyInterface;
+ private final SharedPreferences preference;
+ private final IPropertySynchronizeCallback callback;
+
+ PreferenceSynchronizer(IOlyCameraPropertyProvider propertyInterface, SharedPreferences preference, IPropertySynchronizeCallback callback)
+ {
+ this.propertyInterface = propertyInterface;
+ this.preference = preference;
+ this.callback = callback;
+ }
+
+ private String getPropertyValue(String key)
+ {
+ String propertyValue;
+ try
+ {
+ String value = propertyInterface.getCameraPropertyValue(key);
+ propertyValue = CameraPropertyUtilities.getPropertyValue(value);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ propertyValue = "";
+ }
+ Log.v(TAG, "getPropertyValue(" + key + ") : " + propertyValue);
+ return (propertyValue);
+ }
+
+ @Override
+ public void run()
+ {
+ Log.v(TAG, "run()");
+ SharedPreferences.Editor editor = preference.edit();
+ editor.putString(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.TAKE_MODE, getPropertyValue(IOlyCameraProperty.TAKE_MODE));
+ editor.putString(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.SOUND_VOLUME_LEVEL, getPropertyValue(IOlyCameraProperty.SOUND_VOLUME_LEVEL));
+
+ boolean value = getPropertyValue(IOlyCameraProperty.RAW).equals("ON");
+ editor.putBoolean(net.osdn.gokigen.a01d.preference.IPreferencePropertyAccessor.RAW, value);
+ editor.apply();
+ if (callback != null)
+ {
+ callback.synchronizedProperty();
+ }
+ }
+
+ interface IPropertySynchronizeCallback
+ {
+ void synchronizedProperty();
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:state_enabled="false"
+ android:color="@android:color/darker_gray" />
+ <item
+ android:state_selected="true"
+ android:color="@android:color/holo_blue_light" />
+ <item
+ android:state_pressed="true"
+ android:color="@android:color/holo_blue_light" />
+ <item
+ android:color="@android:color/black" />
+
+</selector>
--- /dev/null
+<vector android:autoMirrored="true" android:height="24dp"
+ 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="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM4,12c0,-4.42 3.58,-8 8,-8 1.85,0 3.55,0.63 4.9,1.69L5.69,16.9C4.63,15.55 4,13.85 4,12zM12,20c-1.85,0 -3.55,-0.63 -4.9,-1.69L18.31,7.1C19.37,8.45 20,10.15 20,12c0,4.42 -3.58,8 -8,8z"/>
+</vector>
--- /dev/null
+<vector android:autoMirrored="true" android:height="24dp"
+ 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="M22.7,19l-9.1,-9.1c0.9,-2.3 0.4,-5 -1.5,-6.9 -2,-2 -5,-2.4 -7.4,-1.3L9,6 6,9 1.6,4.7C0.4,7.1 0.9,10.1 2.9,12.1c1.9,1.9 4.6,2.4 6.9,1.5l9.1,9.1c0.4,0.4 1,0.4 1.4,0l2.3,-2.3c0.5,-0.4 0.5,-1.1 0.1,-1.4z"/>
+</vector>
--- /dev/null
+<vector android:autoMirrored="true" android:height="24dp"
+ 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="M14,5c0,-1.1 -0.9,-2 -2,-2h-1L11,2c0,-0.55 -0.45,-1 -1,-1L6,1c-0.55,0 -1,0.45 -1,1v1L4,3c-1.1,0 -2,0.9 -2,2v15c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2h8L22,5h-8zM12,18h-2v-2h2v2zM12,9h-2L10,7h2v2zM16,18h-2v-2h2v2zM16,9h-2L14,7h2v2zM20,18h-2v-2h2v2zM20,9h-2L18,7h2v2z"/>
+</vector>
--- /dev/null
+<vector android:autoMirrored="true" android:height="24dp"
+ 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="M19,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.11,0 2,-0.9 2,-2L21,5c0,-1.1 -0.89,-2 -2,-2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"/>
+</vector>
--- /dev/null
+<vector android:autoMirrored="true" android:height="24dp"
+ 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="M19,5v14H5V5h14m0,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2z"/>
+</vector>
--- /dev/null
+<vector android:autoMirrored="true" android:height="24dp"
+ 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="M19.35,10.04C18.67,6.59 15.64,4 12,4 9.11,4 6.6,5.64 5.35,8.04 2.34,8.36 0,10.91 0,14c0,3.31 2.69,6 6,6h13c2.76,0 5,-2.24 5,-5 0,-2.64 -2.05,-4.78 -4.65,-4.96zM10,17l-3.5,-3.5 1.41,-1.41L10,14.17 15.18,9l1.41,1.41L10,17z"/>
+</vector>
--- /dev/null
+<vector android:autoMirrored="true" android:height="24dp"
+ 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="M19.35,10.04C18.67,6.59 15.64,4 12,4c-1.48,0 -2.85,0.43 -4.01,1.17l1.46,1.46C10.21,6.23 11.08,6 12,6c3.04,0 5.5,2.46 5.5,5.5v0.5H19c1.66,0 3,1.34 3,3 0,1.13 -0.64,2.11 -1.56,2.62l1.45,1.45C23.16,18.16 24,16.68 24,15c0,-2.64 -2.05,-4.78 -4.65,-4.96zM3,5.27l2.75,2.74C2.56,8.15 0,10.77 0,14c0,3.31 2.69,6 6,6h11.73l2,2L21,20.73 4.27,4 3,5.27zM7.73,10l8,8H6c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4h1.73z"/>
+</vector>
--- /dev/null
+<vector android:autoMirrored="true" android:height="24dp"
+ 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="M19.35,10.04C18.67,6.59 15.64,4 12,4 9.11,4 6.6,5.64 5.35,8.04 2.34,8.36 0,10.91 0,14c0,3.31 2.69,6 6,6h13c2.76,0 5,-2.24 5,-5 0,-2.64 -2.05,-4.78 -4.65,-4.96zM19,18H6c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4h0.71C7.37,7.69 9.48,6 12,6c3.04,0 5.5,2.46 5.5,5.5v0.5H19c1.66,0 3,1.34 3,3s-1.34,3 -3,3z"/>
+</vector>
--- /dev/null
+<vector android:autoMirrored="true" android:height="24dp"
+ 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="M8,4v1.45l2,2L10,4h4v4h-3.45l2,2L14,10v1.45l2,2L16,10h4v4h-3.45l2,2L20,16v1.45l2,2L22,4c0,-1.1 -0.9,-2 -2,-2L4.55,2l2,2L8,4zM16,4h4v4h-4L16,4zM1.27,1.27L0,2.55l2,2L2,20c0,1.1 0.9,2 2,2h15.46l2,2 1.27,-1.27L1.27,1.27zM10,12.55L11.45,14L10,14v-1.45zM4,6.55L5.45,8L4,8L4,6.55zM8,20L4,20v-4h4v4zM8,14L4,14v-4h3.45l0.55,0.55L8,14zM14,20h-4v-4h3.45l0.55,0.54L14,20zM16,20v-1.46L17.46,20L16,20z"/>
+</vector>
--- /dev/null
+<vector android:autoMirrored="true" android:height="24dp"
+ 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="M20,2L4,2c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM8,20L4,20v-4h4v4zM8,14L4,14v-4h4v4zM8,8L4,8L4,4h4v4zM14,20h-4v-4h4v4zM14,14h-4v-4h4v4zM14,8h-4L10,4h4v4zM20,20h-4v-4h4v4zM20,14h-4v-4h4v4zM20,8h-4L16,4h4v4z"/>
+</vector>
--- /dev/null
+<vector android:autoMirrored="true" android:height="24dp"
+ 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="M19,3L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM17,13L7,13v-2h10v2z"/>
+</vector>
--- /dev/null
+<vector android:autoMirrored="true" android:height="24dp"
+ 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="M12,14m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"/>
+ <path android:fillColor="#FF000000" android:pathData="M16,3.33c2.58,0 4.67,2.09 4.67,4.67H22c0,-3.31 -2.69,-6 -6,-6v1.33M16,6c1.11,0 2,0.89 2,2h1.33c0,-1.84 -1.49,-3.33 -3.33,-3.33V6"/>
+ <path android:fillColor="#FF000000" android:pathData="M17,9c0,-1.11 -0.89,-2 -2,-2L15,4L9,4L7.17,6L4,6c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,9h-5zM12,19c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z"/>
+</vector>
--- /dev/null
+<vector android:autoMirrored="true" android:height="24dp"
+ 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="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
+</vector>
--- /dev/null
+<vector android:autoMirrored="true" android:height="24dp"
+ 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="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"/>
+ <path android:fillColor="#FF000000" android:pathData="M9,2L7.17,4L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2L9,2zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z"/>
+</vector>
--- /dev/null
+<vector android:autoMirrored="true" android:height="24dp"
+ 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.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4l-2.35,2.35z"/>
+</vector>
--- /dev/null
+<vector android:autoMirrored="true" android:height="24dp"
+ 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="M14,2L6,2c-1.1,0 -1.99,0.9 -1.99,2L4,20c0,1.1 0.89,2 1.99,2L18,22c1.1,0 2,-0.9 2,-2L20,8l-6,-6zM12,18c-2.05,0 -3.81,-1.24 -4.58,-3h1.71c0.63,0.9 1.68,1.5 2.87,1.5 1.93,0 3.5,-1.57 3.5,-3.5S13.93,9.5 12,9.5c-1.35,0 -2.52,0.78 -3.1,1.9l1.6,1.6h-4L6.5,9l1.3,1.3C8.69,8.92 10.23,8 12,8c2.76,0 5,2.24 5,5s-2.24,5 -5,5z"/>
+</vector>
--- /dev/null
+<vector android:autoMirrored="true" android:height="24dp"
+ 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,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,7l-4,-4zM12,19c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM15,9L5,9L5,5h10v4z"/>
+</vector>
--- /dev/null
+<vector android:autoMirrored="true" android:height="24dp"
+ 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="M19.43,12.98c0.04,-0.32 0.07,-0.64 0.07,-0.98s-0.03,-0.66 -0.07,-0.98l2.11,-1.65c0.19,-0.15 0.24,-0.42 0.12,-0.64l-2,-3.46c-0.12,-0.22 -0.39,-0.3 -0.61,-0.22l-2.49,1c-0.52,-0.4 -1.08,-0.73 -1.69,-0.98l-0.38,-2.65C14.46,2.18 14.25,2 14,2h-4c-0.25,0 -0.46,0.18 -0.49,0.42l-0.38,2.65c-0.61,0.25 -1.17,0.59 -1.69,0.98l-2.49,-1c-0.23,-0.09 -0.49,0 -0.61,0.22l-2,3.46c-0.13,0.22 -0.07,0.49 0.12,0.64l2.11,1.65c-0.04,0.32 -0.07,0.65 -0.07,0.98s0.03,0.66 0.07,0.98l-2.11,1.65c-0.19,0.15 -0.24,0.42 -0.12,0.64l2,3.46c0.12,0.22 0.39,0.3 0.61,0.22l2.49,-1c0.52,0.4 1.08,0.73 1.69,0.98l0.38,2.65c0.03,0.24 0.24,0.42 0.49,0.42h4c0.25,0 0.46,-0.18 0.49,-0.42l0.38,-2.65c0.61,-0.25 1.17,-0.59 1.69,-0.98l2.49,1c0.23,0.09 0.49,0 0.61,-0.22l2,-3.46c0.12,-0.22 0.07,-0.49 -0.12,-0.64l-2.11,-1.65zM12,15.5c-1.93,0 -3.5,-1.57 -3.5,-3.5s1.57,-3.5 3.5,-3.5 3.5,1.57 3.5,3.5 -1.57,3.5 -3.5,3.5z"/>
+</vector>
--- /dev/null
+<vector android:autoMirrored="true" android:height="24dp"
+ android:viewportHeight="24.0" android:viewportWidth="24.0"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#010101" android:pathData="M19,4L5,4c-1.11,0 -2,0.9 -2,2v12c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,6c0,-1.1 -0.89,-2 -2,-2zM19,18L5,18L5,8h14v10z"/>
+</vector>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ tools:context="net.osdn.gokigen.a01d.A01dMain">
+
+ <FrameLayout
+ android:id="@+id/fragment1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentTop="true"
+ />
+
+<!--
+ <FrameLayout
+ android:id="@+id/fragment2"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_weight="1" />
+
+ <FrameLayout
+ android:id="@+id/fragment1"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_weight="3"
+ />
+
+ <FrameLayout
+ android:id="@+id/fragment3"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ />
+ -->
+</RelativeLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true">
+
+ <LinearLayout
+ android:id="@+id/propertyInformationPanelLayout"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="14dp"
+ android:background="@color/background_translucent_dark" >
+
+ <TextView
+ android:id="@+id/propertyInformationMessageTextView"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:gravity="start"
+ android:clickable="true"
+ android:text="@string/blank"
+ android:textColor="@color/background_dark"
+ android:textSize="14sp" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/propertyConfigPanelLayout"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="24dp"
+ android:background="@color/background_translucent_dark" >
+
+ <ImageView
+ android:id="@+id/propertySettings_save"
+ android:layout_width="0dp"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"
+ android:gravity="center"
+ android:layout_gravity="end"
+ android:visibility="invisible"
+ android:clickable="true"
+ android:scaleType="center"
+ android:contentDescription="@string/configuration"
+ android:src="@drawable/ic_save_black_24dp" />
+
+ <ImageView
+ android:id="@+id/propertySettings_refresh"
+ android:layout_width="0dp"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"
+ android:gravity="center"
+ android:layout_gravity="end"
+ android:visibility="invisible"
+ android:clickable="true"
+ android:scaleType="center"
+ android:contentDescription="@string/configuration"
+ android:src="@drawable/ic_refresh_black_24dp" />
+
+ <ImageView
+ android:id="@+id/propertySettings_restore"
+ android:layout_width="0dp"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"
+ android:gravity="center"
+ android:layout_gravity="end"
+ android:visibility="visible"
+ android:clickable="true"
+ android:scaleType="center"
+ android:contentDescription="@string/restore"
+ android:src="@drawable/ic_restore_page_black_24dp" />
+
+ </LinearLayout>
+
+ <ListView android:id="@+id/CameraPropertyListView"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+ </ListView>
+
+</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true">
+
+ <LinearLayout
+ android:id="@+id/consolePanelLayout"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+ android:background="@color/background_translucent_dark"
+ android:orientation="horizontal">
+
+ <view
+ android:id="@+id/consoleImageView1"
+ class="net.osdn.gokigen.a01d.liveview.ScalableImageViewPanel"
+ android:layout_width="0dip"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"
+ android:clickable="true"
+ android:contentDescription="@string/favorite"
+ android:gravity="center"
+ android:scaleType="fitCenter"
+ android:visibility="visible" />
+
+ <view
+ class="net.osdn.gokigen.a01d.liveview.CameraLiveImageView"
+ android:id="@+id/cameraLiveImageView"
+ android:layout_width="0dip"
+ android:layout_height="fill_parent"
+ android:layout_weight="5"
+ android:gravity="center"
+ android:scaleType="fitCenter"
+ android:visibility="visible"/>
+
+ <view
+ android:id="@+id/consoleImageView2"
+ class="net.osdn.gokigen.a01d.liveview.ScalableImageViewPanel"
+ android:layout_width="0dip"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"
+ android:clickable="true"
+ android:contentDescription="@string/favorite"
+ android:gravity="center"
+ android:scaleType="fitCenter"
+ android:visibility="visible" />
+ </LinearLayout>
+
+ <RelativeLayout
+ android:id="@+id/informationPanelLayout"
+ android:layout_width="fill_parent"
+ android:layout_height="14pt"
+ android:background="@color/background_translucent_dark"
+ android:orientation="horizontal">
+
+ <ImageButton
+ android:id="@+id/show_preference_button"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:clickable="true"
+ android:gravity="center"
+ android:scaleType="fitCenter"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentEnd="true"
+ android:contentDescription="@string/preferences"
+ android:src="@drawable/ic_settings_black_24dp"
+ android:visibility="visible" />
+
+ <ImageButton
+ android:id="@+id/connect_disconnect_button"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:clickable="true"
+ android:gravity="center"
+ android:scaleType="fitCenter"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:contentDescription="@string/grid"
+ android:src="@drawable/ic_cloud_off_black_24dp"
+ android:visibility="visible" />
+
+ <TextView
+ android:id="@+id/informationMessageTextView"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_toRightOf="@id/connect_disconnect_button"
+ android:layout_toEndOf="@id/connect_disconnect_button"
+ android:clickable="true"
+ android:gravity="start"
+ android:text="@string/information"
+ android:textColor="@color/background_translucent_dark"
+ android:textSize="12pt" />
+
+ <ImageButton
+ android:id="@+id/camera_property_settings_button"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:clickable="true"
+ android:gravity="center"
+ android:scaleType="fitCenter"
+ android:layout_alignTop="@id/show_preference_button"
+ android:layout_toLeftOf="@id/show_preference_button"
+ android:layout_toStartOf="@id/show_preference_button"
+ android:contentDescription="@string/blank"
+ android:src="@drawable/ic_build_black_24dp"
+ android:visibility="visible" />
+
+
+ <ImageButton
+ android:id="@+id/show_hide_grid_button"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:clickable="true"
+ android:gravity="center"
+ android:scaleType="fitCenter"
+ android:layout_alignTop="@id/show_preference_button"
+ android:layout_toLeftOf="@id/camera_property_settings_button"
+ android:layout_toStartOf="@id/camera_property_settings_button"
+ android:contentDescription="@string/grid"
+ android:src="@drawable/ic_grid_on_black_24dp"
+ android:visibility="visible" />
+
+
+ </RelativeLayout>
+
+</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="horizontal"
+ >
+ <ImageView
+ android:id="@+id/ObjectStyleIcons"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:scaleType="fitCenter"
+ android:tag="icon"
+ android:src="@drawable/ic_photo_camera_black_24dp"
+ android:contentDescription="@string/icon"
+ android:layout_gravity="center_vertical"
+ android:maxHeight="18dp"
+ android:minWidth="18dp">
+ </ImageView>
+ <TextView
+ android:textSize="9pt"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/ObjectDataTitle"
+ android:tag="title"
+ android:maxWidth="130dp"
+ android:minWidth="130dp"
+ android:layout_gravity="start">
+ </TextView>
+ <TextView
+ android:textSize="6pt"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/ObjectDataDetail"
+ android:tag="value"
+ android:linksClickable="true"
+ android:maxWidth="100dp"
+ android:minWidth="100dp"
+ android:layout_gravity="center_vertical">
+ </TextView>
+ <TextView
+ android:textSize="4pt"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/ObjectDataValue"
+ android:tag="name"
+ android:autoLink="all"
+ android:linksClickable="true"
+ android:layout_gravity="center_vertical">
+ </TextView>
+</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ tools:context="net.osdn.gokigen.a01d.A01dMain">
+
+ <FrameLayout
+ android:id="@+id/fragment1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentTop="true"
+ />
+
+<!--
+ <FrameLayout
+ android:id="@+id/fragment1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="3"
+ />
+
+ <FrameLayout
+ android:id="@+id/fragment2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
+
+ <FrameLayout
+ android:id="@+id/fragment3"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ />
+-->
+</RelativeLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true">
+
+ <LinearLayout
+ android:id="@+id/propertyInformationPanelLayout"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="14dp"
+ android:background="@color/background_translucent_dark" >
+
+ <TextView
+ android:id="@+id/propertyInformationMessageTextView"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:gravity="start"
+ android:clickable="true"
+ android:text="@string/blank"
+ android:textColor="@color/background_dark"
+ android:textSize="14sp" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/propertyConfigPanelLayout"
+ android:orientation="horizontal"
+ android:layout_width="fill_parent"
+ android:layout_height="24dp"
+ android:background="@color/background_translucent_dark" >
+
+ <ImageView
+ android:id="@+id/propertySettings_save"
+ android:layout_width="0dp"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"
+ android:gravity="center"
+ android:layout_gravity="end"
+ android:visibility="invisible"
+ android:clickable="true"
+ android:scaleType="center"
+ android:contentDescription="@string/configuration"
+ android:src="@drawable/ic_save_black_24dp" />
+
+ <ImageView
+ android:id="@+id/propertySettings_refresh"
+ android:layout_width="0dp"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"
+ android:gravity="center"
+ android:layout_gravity="end"
+ android:visibility="invisible"
+ android:clickable="true"
+ android:scaleType="center"
+ android:contentDescription="@string/configuration"
+ android:src="@drawable/ic_refresh_black_24dp" />
+
+ <ImageView
+ android:id="@+id/propertySettings_restore"
+ android:layout_width="0dp"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"
+ android:gravity="center"
+ android:layout_gravity="end"
+ android:visibility="visible"
+ android:clickable="true"
+ android:scaleType="center"
+ android:contentDescription="@string/restore"
+ android:src="@drawable/ic_restore_page_black_24dp" />
+
+ </LinearLayout>
+
+ <ListView android:id="@+id/CameraPropertyListView"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+ </ListView>
+
+</LinearLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true">
+
+ <view
+ android:id="@+id/cameraLiveImageView"
+ class="net.osdn.gokigen.a01d.liveview.CameraLiveImageView"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+ android:gravity="center"
+ android:scaleType="fitCenter"
+ android:visibility="visible" />
+
+ <LinearLayout
+ android:id="@+id/consolePanelLayout"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+ android:background="@color/background_translucent_dark"
+ android:orientation="horizontal">
+
+ <view
+ android:id="@+id/consoleImageView1"
+ class="net.osdn.gokigen.a01d.liveview.ScalableImageViewPanel"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"
+ android:clickable="true"
+ android:contentDescription="@string/favorite"
+ android:gravity="center"
+ android:scaleType="fitCenter"
+ android:visibility="visible" />
+
+ <view
+ android:id="@+id/consoleImageView2"
+ class="net.osdn.gokigen.a01d.liveview.ScalableImageViewPanel"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"
+ android:clickable="true"
+ android:contentDescription="@string/favorite"
+ android:gravity="center"
+ android:scaleType="fitCenter"
+ android:visibility="visible" />
+ </LinearLayout>
+
+ <RelativeLayout
+ android:id="@+id/informationPanelLayout"
+ android:layout_width="fill_parent"
+ android:layout_height="14pt"
+ android:background="@color/background_translucent_dark"
+ android:orientation="horizontal">
+
+ <ImageButton
+ android:id="@+id/show_preference_button"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:clickable="true"
+ android:gravity="center"
+ android:scaleType="fitCenter"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentEnd="true"
+ android:contentDescription="@string/preferences"
+ android:src="@drawable/ic_settings_black_24dp"
+ android:visibility="visible" />
+
+
+
+ <ImageButton
+ android:id="@+id/connect_disconnect_button"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:clickable="true"
+ android:gravity="center"
+ android:scaleType="fitCenter"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:contentDescription="@string/grid"
+ android:src="@drawable/ic_cloud_off_black_24dp"
+ android:visibility="visible" />
+
+
+ <TextView
+ android:id="@+id/informationMessageTextView"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_toRightOf="@id/connect_disconnect_button"
+ android:layout_toEndOf="@id/connect_disconnect_button"
+ android:clickable="true"
+ android:gravity="start"
+ android:text="@string/information"
+ android:textColor="@color/background_translucent_dark"
+ android:textSize="12pt" />
+
+ <ImageButton
+ android:id="@+id/camera_property_settings_button"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:clickable="true"
+ android:gravity="center"
+ android:scaleType="fitCenter"
+ android:layout_alignTop="@id/show_preference_button"
+ android:layout_toLeftOf="@id/show_preference_button"
+ android:layout_toStartOf="@id/show_preference_button"
+ android:contentDescription="@string/blank"
+ android:src="@drawable/ic_build_black_24dp"
+ android:visibility="visible" />
+
+ <ImageButton
+ android:id="@+id/show_hide_grid_button"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:clickable="true"
+ android:gravity="center"
+ android:scaleType="fitCenter"
+ android:layout_alignTop="@id/show_preference_button"
+ android:layout_toLeftOf="@id/camera_property_settings_button"
+ android:layout_toStartOf="@id/camera_property_settings_button"
+ android:contentDescription="@string/grid"
+ android:src="@drawable/ic_grid_on_black_24dp"
+ android:visibility="visible" />
+ </RelativeLayout>
+</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="horizontal"
+ >
+ <ImageView
+ android:id="@+id/ObjectStyleIcons"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:scaleType="fitCenter"
+ android:tag="icon"
+ android:src="@drawable/ic_photo_camera_black_24dp"
+ android:contentDescription="@string/icon"
+ android:layout_gravity="center_vertical"
+ android:maxHeight="18dp"
+ android:minWidth="18dp">
+ </ImageView>
+ <TextView
+ android:textSize="9pt"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/ObjectDataTitle"
+ android:tag="title"
+ android:maxWidth="130dp"
+ android:minWidth="130dp"
+ android:layout_gravity="start">
+ </TextView>
+ <TextView
+ android:textSize="6pt"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/ObjectDataDetail"
+ android:tag="value"
+ android:linksClickable="true"
+ android:maxWidth="100dp"
+ android:minWidth="100dp"
+ android:layout_gravity="center_vertical">
+ </TextView>
+ <TextView
+ android:textSize="4pt"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/ObjectDataValue"
+ android:tag="name"
+ android:autoLink="all"
+ android:linksClickable="true"
+ android:layout_gravity="center_vertical">
+ </TextView>
+</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string-array name="take_mode">
+ <item >P</item>
+ <item >iAuto</item>
+ <item >A</item>
+ <item >S</item>
+ <item >M</item>
+ <item>Movie</item>
+ </string-array>
+ <string-array name="take_mode_value">
+ <item >P</item>
+ <item >iAuto</item>
+ <item >A</item>
+ <item >S</item>
+ <item >M</item>
+ <item >movie</item>
+ </string-array>
+
+ <string-array name="sound_volume_level">
+ <item >OFF</item>
+ <item >1</item>
+ <item >2</item>
+ <item >3</item>
+ <item >4</item>
+ <item >5</item>
+ </string-array>
+
+ <string-array name="sound_volume_level_value">
+ <item >OFF</item>
+ <item >1</item>
+ <item >2</item>
+ <item >3</item>
+ <item >4</item>
+ <item >5</item>
+ </string-array>
+
+ <string-array name="live_view_quality">
+ <item >QVGA (320x240)</item>
+ <item >VGA (640x480)</item>
+ <item >SVGA (800x600)</item>
+ <item >XGA (1024x768)</item>
+ <item >QUAD VGA (1280x960)</item>
+ </string-array>
+ <string-array name="live_view_quality_value">
+ <item >QVGA</item>
+ <item >VGA</item>
+ <item >SVGA</item>
+ <item >XGA</item>
+ <item >QUAD_VGA</item>
+ </string-array>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="colorPrimary">#3F51B5</color>
+ <color name="colorPrimaryDark">#303F9F</color>
+ <color name="colorAccent">#FF4081</color>
+ <color name="background_dark">#555555</color>
+ <color name="background_translucent_dark">#AA555555</color>
+ <color name="background_translucent_white">#AAFFFFFF</color>
+</resources>
--- /dev/null
+<resources>
+ <string name="app_name">A01d</string>
+ <string name="blank"> </string>
+
+ <string name="configuration">Settings</string>
+ <string name="restore">Restore</string>
+ <string name="icon">icon</string>
+
+ <string name="dialog_positive_execute">OK</string>
+ <string name="dialog_negative_cancel">Cancel</string>
+
+ <string name="dialog_title_confirmation">確認</string>
+ <string name="dialog_message_restore_camera_property">カメラプロパティを画面オープン時の状態に戻します。</string>
+ <string name="dialog_title_loading_properties">カメラプロパティ読出中</string>
+ <string name="dialog_message_loading_properties">しばらくお待ち下さい…</string>
+
+ <string name="pref_cat_camera">カメラ設定</string>
+ <string name="pref_take_mode">撮影モード</string>
+ <string name="pref_camera_sound_volume">シャッター音</string>
+ <string name="pref_take_raw">RAW撮影</string>
+
+ <string name="pref_cat_application_control">アプリ制御</string>
+ <string name="pref_exit_power_off">アプリ終了(とカメラOFF)</string>
+
+ <string name="pref_cat_initialize">起動時設定</string>
+ <string name="pref_auto_connect_camera">カメラに自動接続</string>
+ <string name="dialog_message_power_off">カメラの電源を切り、アプリケーションを終了します。</string>
+
+
+ <string name="pref_cat_live_view">ライブビュー設定</string>
+ <string name="pref_live_view_quality">ライブビュー品質</string>
+
+ <string name="pref_cat_info">カメラ情報</string>
+ <string name="pref_focal_length">焦点距離</string>
+ <string name="pref_lens_status">レンズ状態</string>
+ <string name="pref_media_status">SDカード状態</string>
+ <string name="pref_camera_version">Camera Version</string>
+ <string name="pref_camerakit_version">Camera kit Version</string>
+
+ <string name="pref_cat_gokigen">GOKIGEN Project(現在、直接開けません)</string>
+ <string name="pref_instruction_manual">操作説明</string>
+ <string name="pref_privacy_policy">プライバシーポリシー</string>
+
+ <string name="information">ハロー!</string>
+ <string name="favorite">お気に入り</string>
+ <string name="preferences">Preferences</string>
+ <string name="grid">Grid</string>
+</resources>
--- /dev/null
+<resources>
+
+ <!-- Base application theme. -->
+ <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+ <!-- Customize your theme here. -->
+ <item name="colorPrimary">@color/colorPrimary</item>
+ <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+ <item name="colorAccent">@color/colorAccent</item>
+ <item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
+ </style>
+
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string-array name="take_mode">
+ <item >P</item>
+ <item >iAuto</item>
+ <item >A</item>
+ <item >S</item>
+ <item >M</item>
+ <item>Movie</item>
+ </string-array>
+ <string-array name="take_mode_value">
+ <item >P</item>
+ <item >iAuto</item>
+ <item >A</item>
+ <item >S</item>
+ <item >M</item>
+ <item >movie</item>
+ </string-array>
+
+ <string-array name="sound_volume_level">
+ <item >OFF</item>
+ <item >1</item>
+ <item >2</item>
+ <item >3</item>
+ <item >4</item>
+ <item >5</item>
+ </string-array>
+
+ <string-array name="sound_volume_level_value">
+ <item >OFF</item>
+ <item >1</item>
+ <item >2</item>
+ <item >3</item>
+ <item >4</item>
+ <item >5</item>
+ </string-array>
+
+ <string-array name="live_view_quality">
+ <item >QVGA (320x240)</item>
+ <item >VGA (640x480)</item>
+ <item >SVGA (800x600)</item>
+ <item >XGA (1024x768)</item>
+ <item >QUAD VGA (1280x960)</item>
+ </string-array>
+ <string-array name="live_view_quality_value">
+ <item >QVGA</item>
+ <item >VGA</item>
+ <item >SVGA</item>
+ <item >XGA</item>
+ <item >QUAD_VGA</item>
+ </string-array>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="colorPrimary">#3F51B5</color>
+ <color name="colorPrimaryDark">#303F9F</color>
+ <color name="colorAccent">#FF4081</color>
+ <color name="background_dark">#555555</color>
+ <color name="background_translucent_dark">#AA555555</color>
+ <color name="background_translucent_white">#AAFFFFFF</color>
+</resources>
--- /dev/null
+<resources>
+ <string name="app_name">A01d</string>
+ <string name="blank"> </string>
+
+ <string name="configuration">Settings</string>
+ <string name="restore">Restore</string>
+ <string name="icon">icon</string>
+
+ <string name="dialog_positive_execute">OK</string>
+ <string name="dialog_negative_cancel">Cancel</string>
+
+ <string name="dialog_title_confirmation">Confirmation</string>
+ <string name="dialog_message_restore_camera_property">Restore Camera Property</string>
+ <string name="dialog_title_loading_properties">Loading Camera Properties</string>
+ <string name="dialog_message_loading_properties">Please wait…</string>
+
+ <string name="pref_cat_camera">Camera</string>
+ <string name="pref_take_mode">Take Mode</string>
+ <string name="pref_camera_sound_volume">Shutter Sound</string>
+ <string name="pref_take_raw">Take Raw</string>
+
+ <string name="pref_cat_application_control">App. Control</string>
+ <string name="pref_exit_power_off">Exit Application(and Camera OFF)</string>
+
+
+ <string name="pref_cat_initialize">App. Startup</string>
+ <string name="pref_auto_connect_camera">Auto Connect To Camera</string>
+ <string name="dialog_message_power_off">Power Off</string>
+
+ <string name="pref_cat_live_view">Live View Settings</string>
+ <string name="pref_live_view_quality">Live View Quality</string>
+
+ <string name="pref_cat_info">Information</string>
+ <string name="pref_focal_length">Focal Length</string>
+ <string name="pref_lens_status">Lens Status</string>
+ <string name="pref_media_status">SD Card Status</string>
+ <string name="pref_camera_version">Camera Version</string>
+ <string name="pref_camerakit_version">Camera kit Version</string>
+
+ <string name="pref_cat_gokigen">GOKIGEN(Currently not open directly)</string>
+ <string name="pref_instruction_manual">A01d Instructions</string>
+ <string name="pref_privacy_policy">Privacy Policy</string>
+
+ <string name="information">Hello!</string>
+ <string name="favorite">Favorite</string>
+ <string name="preferences">Preferences</string>
+ <string name="grid">Grid</string>
+
+ <string name="network_connection_timeout">Connection time out</string>
+ <string name="dialog_title_connect_failed">Connect failed</string>
+ <string name="dialog_title_button_retry">Retry</string>
+ <string name="dialog_title_button_network_settings">WiFi Settings</string>
+
+
+ <string name="connect_start">start</string>
+ <string name="connect_check_wifi">check WIFI</string>
+ <string name="connect_connect">connecting</string>
+ <string name="connect_connected">connected</string>
+ <string name="connect_change_run_mode">changeRunMode</string>
+ <string name="connect_restore_camera_settings">restoreCameraSettings</string>
+
+ <string name="fatal_cannot_use_camera">The CameraKit SDK can not work because the running mode of camera is UNKNOWN. So please long press the power button of camera more than 8 seconds. (This is the camera reset operation.) After that turn on the camera power again.</string>
+ <string name="camera_reset_required">The camera reset operation is required.</string>
+ <string name="camera_disconnected">Disconnected</string>
+</resources>
--- /dev/null
+<resources>
+
+ <!-- Base application theme. -->
+ <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
+ <!-- Customize your theme here. -->
+ <item name="colorPrimary">@color/colorPrimary</item>
+ <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
+ <item name="colorAccent">@color/colorAccent</item>
+ <item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
+ </style>
+
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
+ <PreferenceCategory
+ android:title="@string/pref_cat_application_control">
+
+ <PreferenceScreen
+ android:key="exit_application"
+ android:title="@string/pref_exit_power_off" />
+
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:title="@string/pref_cat_initialize">
+
+ <CheckBoxPreference
+ android:key="auto_connect_to_camera"
+ android:title="@string/pref_auto_connect_camera" />
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:title="@string/pref_cat_camera">
+
+ <ListPreference
+ android:title="@string/pref_take_mode"
+ android:entryValues="@array/take_mode_value"
+ android:entries="@array/take_mode"
+ android:key="take_mode"
+ android:defaultValue="P"/>
+
+ <ListPreference
+ android:title="@string/pref_camera_sound_volume"
+ android:entryValues="@array/sound_volume_level_value"
+ android:entries="@array/sound_volume_level"
+ android:key="sound_volume_level"
+ android:defaultValue="OFF"/>
+
+ <CheckBoxPreference
+ android:key="raw"
+ android:title="@string/pref_take_raw" />
+
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:title="@string/pref_cat_live_view">
+ <ListPreference
+ android:title="@string/pref_live_view_quality"
+ android:entryValues="@array/live_view_quality_value"
+ android:entries="@array/live_view_quality"
+ android:key="live_view_quality"
+ android:defaultValue="QVGA"/>
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:title="@string/pref_cat_info">
+
+ <PreferenceScreen
+ android:key="focal_length"
+ android:title="@string/pref_focal_length"
+ android:selectable="false" />
+
+ <PreferenceScreen
+ android:key="lens_status"
+ android:title="@string/pref_lens_status"
+ android:selectable="false" />
+
+ <PreferenceScreen
+ android:key="media_status"
+ android:title="@string/pref_media_status"
+ android:selectable="false" />
+
+ <PreferenceScreen
+ android:key="camera_version"
+ android:title="@string/pref_camera_version"
+ android:selectable="false" />
+
+ <PreferenceScreen
+ android:key="camerakit_version"
+ android:title="@string/pref_camerakit_version"
+ android:selectable="false" />
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:title="@string/pref_cat_gokigen">
+ <Preference
+ android:key="instruction_link"
+ android:title="@string/pref_instruction_manual"
+ android:summary="https://osdn.net/projects/gokigen/wiki/A01d"
+ android:selectable="true">
+ <intent android:action="android.intent.action.VIEW"
+ android:data="https://osdn.net/projects/gokigen/wiki/A01d" />
+ </Preference>
+ <Preference
+ android:key="privacy_policy"
+ android:title="@string/pref_privacy_policy"
+ android:summary="https://osdn.net/projects/gokigen/wiki/PrivacyPolicy"
+ android:selectable="true">
+ <intent android:action="android.intent.action.VIEW"
+ android:data="https://osdn.net/projects/gokigen/wiki/PrivacyPolicy" />
+ </Preference>
+ </PreferenceCategory>
+</PreferenceScreen>
--- /dev/null
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:2.3.3'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
--- /dev/null
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
--- /dev/null
+#Mon Jun 19 23:15:24 JST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
--- /dev/null
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
--- /dev/null
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
--- /dev/null
+include ':app'