sample code - “get/set device property, send command”

usage:
   setdp  <DP name> <param> [1-blocking,0-no blocking]
   getdp  <DP name>
   infodp <DP name>
   listdp
   send <command name> <param>
   setcc  <control code> <param>
   infocc <control code>
   listcc
To exit, please enter 'q'.

argument

example

DP name

FNumber for CrDeviceProperty_FNumber.

command name

Release for CrCommandId_Release.

control code

S1Button for CrControlCode_S1Button.

param

80, 0x50 (numeric value)

This sample code is included in SimpleCli.

  1// get/set deviceProperty, send command sample
  2#include <chrono>
  3#include <cinttypes>
  4#include <codecvt>
  5#include <cstdint>
  6#include <cstdlib>
  7#include <fstream>
  8#include <future>
  9#include <iostream>
 10#include <mutex>
 11#include <sstream>
 12#include <stdexcept>
 13#include <string>
 14#include <thread>
 15#include <vector>
 16
 17#if !defined(__APPLE__)
 18  #if defined(USE_EXPERIMENTAL_FS) // for jetson
 19    #include <experimental/filesystem>
 20    namespace fs = std::experimental::filesystem;
 21  #else
 22    #include <filesystem>
 23    namespace fs = std::filesystem;
 24  #endif
 25#endif
 26
 27#if defined(__APPLE__) || defined(__linux__)
 28  #include <unistd.h>
 29#endif
 30
 31#if defined(_WIN32) || defined(_WIN64)
 32    using CrString = std::wstring;
 33#else
 34    using CrString = std::string;
 35#endif
 36
 37// macro for multibyte character
 38#if defined(_WIN32) || defined(_WIN64)
 39  #define CRSTR(s) L ## s
 40  #define CrCout std::wcout
 41  #define Utf8ToCr(a) wstring_convert.from_bytes(a)
 42  static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t> wstring_convert;
 43#else
 44  #define CRSTR(s) s
 45  #define CrCout std::cout
 46  #define Utf8ToCr(a) (a)
 47  static std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> wstring_convert;
 48#endif
 49
 50
 51#include "CrDeviceProperty.h"
 52#include "CameraRemote_SDK.h"
 53#include "IDeviceCallback.h"
 54#include "CrDebugString.h"   // use CrDebugString.cpp
 55
 56#define PrintError(msg, err) { fprintf(stderr, "Error in %s(%d):" msg ",%s\n", __FUNCTION__, __LINE__, (err ? CrErrorString(err).c_str():"")); }
 57#define GotoError(msg, err) { PrintError(msg, err); goto Error; }
 58
 59bool  m_connected = false;
 60CrString m_modelId;
 61int64_t  m_device_handle = 0;
 62bool  m_lvProtocolChanged = false;
 63
 64std::mutex m_eventPromiseMutex;
 65uint32_t m_setDPCode = 0;
 66std::promise<void>* m_eventPromise = nullptr;
 67void setEventPromise(std::promise<void>* dp)
 68{
 69    std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
 70    m_eventPromise = dp;
 71}
 72
 73SCRSDK::CrError _getDeviceProperty(int64_t device_handle, uint32_t code, SCRSDK::CrDeviceProperty* devProp)
 74{
 75    std::int32_t nprop = 0;
 76    SCRSDK::CrDeviceProperty* prop_list = nullptr;
 77    SCRSDK::CrError err = SCRSDK::GetSelectDeviceProperties(device_handle, 1, &code, &prop_list, &nprop);
 78    if(err) GotoError("", err);
 79    if(prop_list && nprop >= 1) {
 80        *devProp = prop_list[0];
 81    }
 82Error:
 83    if(prop_list) SCRSDK::ReleaseDeviceProperties(device_handle, prop_list);
 84    return err;
 85}
 86
 87SCRSDK::CrError _setDeviceProperty(int64_t device_handle, uint32_t code, uint64_t data, bool blocking=true)
 88{
 89    int result = SCRSDK::CrError_Generic_Unknown;
 90    SCRSDK::CrError err = 0;
 91    std::promise<void> eventPromise;
 92    std::future<void> eventFuture = eventPromise.get_future();
 93    std::future_status status;
 94
 95    SCRSDK::CrDeviceProperty devProp;
 96
 97    err = _getDeviceProperty(device_handle, code, &devProp);
 98    if(err) GotoError("", err);
 99    if (devProp.GetValueType() == SCRSDK::CrDataType_STR) GotoError("STR is not supported", 0);
100    if (blocking && devProp.GetCurrentValue() == data) {
101        std::cout << "skipped\n";
102        return 0;
103    }
104
105    if(blocking) {
106        std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
107        m_setDPCode = code;
108        m_eventPromise = &eventPromise;
109    }
110
111    devProp.SetCurrentValue(data);
112    err = SCRSDK::SetDeviceProperty(device_handle, &devProp);
113    if(err) GotoError("", err);
114
115    if(!blocking) return 0;
116
117    status = eventFuture.wait_for(std::chrono::milliseconds(3000));
118    if(status != std::future_status::ready) GotoError("timeout", 0);
119
120    try{
121        eventFuture.get();
122    } catch(const std::exception&) GotoError("", 0);
123    std::cout << "OK\n";
124
125    result = 0;
126Error:
127    setEventPromise(nullptr);
128    return result;
129}
130
131std::vector<int64_t> _getPossible(SCRSDK::CrDataType dataType, const uint8_t* values, uint32_t valueSize)
132{
133/*
134    CrInt32u GetSetValueSize();
135    CrInt8u* GetSetValues();
136*/
137    std::vector<int64_t> possible;
138
139    int dataLen = 1;
140    switch(dataType & 0x100F) {
141    case SCRSDK::CrDataType_UInt8:  dataLen = sizeof(uint8_t); break;
142    case SCRSDK::CrDataType_Int8:   dataLen = sizeof(int8_t); break;
143    case SCRSDK::CrDataType_UInt16: dataLen = sizeof(uint16_t); break;
144    case SCRSDK::CrDataType_Int16:  dataLen = sizeof(int16_t); break;
145    case SCRSDK::CrDataType_UInt32: dataLen = sizeof(uint32_t); break;
146    case SCRSDK::CrDataType_Int32:  dataLen = sizeof(int32_t); break;
147    case SCRSDK::CrDataType_UInt64: dataLen = sizeof(uint64_t); break;
148    default: return possible;
149    }
150
151    const uint8_t* buf = values;
152    uint32_t nval = valueSize / dataLen;
153    possible.resize(nval);
154    for (uint32_t i = 0; i < nval; ++i) {
155        int64_t data = 0;
156        switch(dataType & 0x100F) {
157        case SCRSDK::CrDataType_UInt8:  data = (reinterpret_cast<uint8_t const*>(buf))[i]; break;
158        case SCRSDK::CrDataType_Int8:   data = (reinterpret_cast<int8_t const*>(buf))[i]; break;
159        case SCRSDK::CrDataType_UInt16: data = (reinterpret_cast<uint16_t const*>(buf))[i]; break;
160        case SCRSDK::CrDataType_Int16:  data = (reinterpret_cast<int16_t const*>(buf))[i]; break;
161        case SCRSDK::CrDataType_UInt32: data = (reinterpret_cast<uint32_t const*>(buf))[i]; break;
162        case SCRSDK::CrDataType_Int32:  data = (reinterpret_cast<int32_t const*>(buf))[i]; break;
163        case SCRSDK::CrDataType_UInt64: data = (reinterpret_cast<uint64_t const*>(buf))[i]; break;
164        default: break;
165        }
166        possible.at(i) = data;
167    }
168    return possible;
169}
170
171CrString _getCurrentStr(SCRSDK::CrDeviceProperty* devProp)
172{
173    CrString current;
174    uint16_t* dp = devProp->GetCurrentStr();
175    if(!dp) GotoError("", 0);
176    if(*dp > 0) {
177    if(devProp->GetCode() == SCRSDK::CrDeviceProperty_ImageID_String) {
178        for(int i = 0; i < *dp; i++) {
179            uint16_t data = dp[1+i];
180            dp[1+i] = (data>>8) | (data<<8);
181        }
182    }
183    #if defined (_WIN32) || defined(_WIN64)
184        current = CrString((wchar_t*)(dp+1));
185    #else
186        int length = dp[0];
187        current = wstring_convert.to_bytes(std::u16string((dp+1), (dp+1)+length));
188    #endif
189    }
190Error:
191    return current;
192}
193
194class DeviceCallback : public SCRSDK::IDeviceCallback
195{
196public:
197    DeviceCallback() {};
198    ~DeviceCallback() {};
199
200    void OnConnected(SCRSDK::DeviceConnectionVersioin version)
201    {
202        CrCout << "Connected to " << m_modelId << "\n";
203        m_connected = true;
204        std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
205        if(m_eventPromise) {
206            m_eventPromise->set_value();
207            m_eventPromise = nullptr;
208        }
209    }
210
211    void OnError(CrInt32u error)
212    {
213        printf("Connection error:%s\n", CrErrorString(error).c_str());
214        std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
215        if(m_eventPromise) {
216            m_eventPromise->set_exception(std::make_exception_ptr(std::runtime_error("error")));
217            m_eventPromise = nullptr;
218        }
219    }
220
221    void OnDisconnected(CrInt32u error)
222    {
223        CrCout << "Disconnected from " << m_modelId << "\n";
224        m_connected = false;
225        std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
226        if(m_eventPromise) {
227            m_eventPromise->set_value();
228            m_eventPromise = nullptr;
229        }
230    }
231
232    void OnCompleteDownload(CrChar* filename, CrInt32u type )
233    {
234        CrCout << "OnCompleteDownload:" << filename << "\n";
235    }
236
237    void OnNotifyContentsTransfer(CrInt32u notify, SCRSDK::CrContentHandle contentHandle, CrChar* filename)
238    {
239        std::cout << "OnNotifyContentsTransfer.\n";
240    }
241
242    void OnWarning(CrInt32u warning)
243    {
244        if (warning == SCRSDK::CrWarning_Connect_Reconnecting) {
245            CrCout << "Reconnecting to " << m_modelId << "\n";
246            return;
247        }
248        if (warning == SCRSDK::CrNotify_LiveView_Alt_Ready) {
249            m_lvProtocolChanged = true;
250        }
251        std::cout << "OnWarning:" << CrErrorString(warning) << "\n";
252    }
253
254    void OnWarningExt(CrInt32u warning, CrInt32 param1, CrInt32 param2, CrInt32 param3)
255    {
256        std::cout << "OnWarningExt:" << CrWarningExtString(warning, param1, param2, param3).c_str() << "\n";
257    }
258
259    void OnLvPropertyChanged() {}
260    void OnLvPropertyChangedCodes(CrInt32u num, CrInt32u* codes) {}
261    void OnPropertyChanged() {}
262    void OnPropertyChangedCodes(CrInt32u num, CrInt32u* codes)
263    {
264        std::cout << "OnPropertyChangedCodes:\n";
265        for(uint32_t i = 0; i < num; ++i) {
266            std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
267            if(m_setDPCode && m_setDPCode == codes[i]) {
268                m_setDPCode = 0;
269                if(m_eventPromise) {
270                    m_eventPromise->set_value();
271                    m_eventPromise = nullptr;
272                }
273            }
274            std::string name = CrDevicePropertyString((SCRSDK::CrDevicePropertyCode)codes[i]);
275
276            SCRSDK::CrDeviceProperty devProp;
277            SCRSDK::CrError err = _getDeviceProperty(m_device_handle, codes[i], &devProp);
278            if(err) break;
279            if(devProp.GetValueType() == SCRSDK::CrDataType_STR) {
280                CrCout << "  " << CrString(name.begin(), name.end()) << "=\"" << _getCurrentStr(&devProp) << "\"\n";
281            } else {
282                int64_t current = devProp.GetCurrentValue();
283                if(current < 10) {
284                    printf("  %s=%" PRId64 "\n", name.c_str(), current);
285                } else {
286                    printf("  %s=0x%" PRIx64 "(%" PRId64 ")\n", name.c_str(), current, current);
287                }
288            }
289        }
290    }
291};
292
293CrString _getModelId(const SCRSDK::ICrCameraObjectInfo* objInfo)
294{
295    CrString id;
296    if (CrString(objInfo->GetConnectionTypeName()) == CRSTR("IP")) {
297        id = CrString(objInfo->GetMACAddressChar());
298    } else {
299        id = CrString((CrChar*)objInfo->GetId());
300    }
301    return CrString(objInfo->GetModel()).append(CRSTR(" (")).append(id).append(CRSTR(")"));
302}
303
304SCRSDK::CrError _getIdPassword(SCRSDK::ICrCameraObjectInfo* objInfo, std::string& fingerprint, std::string& userId, std::string& userPassword)
305{
306    char fpBuff[128] = {0};
307    CrInt32u fpLen = 0;
308    SCRSDK::CrError err = SCRSDK::GetFingerprint(objInfo, fpBuff, &fpLen);
309    if(err) GotoError("", err);
310    fingerprint = std::string(fpBuff, fpLen);
311
312    std::cout << "fingerprint: " << fingerprint.c_str() << "\n";
313    std::cout << "id:";       std::getline(std::cin, userId);
314    std::cout << "password:"; std::getline(std::cin, userPassword);
315    return 0;
316Error:
317    return err;
318}
319
320std::vector<std::string> _split(std::string inputLine, char delimiter)
321{
322    std::vector<std::string> strArray;
323    if (inputLine.empty()) return strArray;
324
325    std::string tmp;
326    std::stringstream ss{inputLine};
327    while (getline(ss, tmp, delimiter)) {
328        strArray.push_back(tmp);
329    }
330    return strArray;
331}
332
333int64_t _stoll(std::string inputLine)
334{
335    int64_t data = 0;
336    if(inputLine.empty()) throw std::runtime_error("error");
337    try {
338        if (inputLine.compare(0, 2, "0x") == 0 || inputLine.compare(0, 2, "0X") == 0) {
339            data = std::stoull(inputLine.substr(2), nullptr, 16);
340        } else {
341            data = std::stoll(inputLine, nullptr, 10);
342        }
343    } catch(const std::exception& ex) {
344        throw ex;
345    }
346    return data;
347}
348
349int main(void)
350{
351    int result = -1;
352    SCRSDK::CrError err = SCRSDK::CrError_None;
353    SCRSDK::ICrEnumCameraObjectInfo* enumCameraObjectInfo = nullptr;
354    SCRSDK::ICrCameraObjectInfo* objInfo = nullptr;
355    DeviceCallback deviceCallback;
356
357  #if defined(__APPLE__)
358    #define MAC_MAX_PATH 255
359    char pathBuf[MAC_MAX_PATH] = {0};
360    if(NULL == getcwd(pathBuf, sizeof(pathBuf) - 1)) return 1;
361    CrString path = pathBuf;
362  #else
363    CrString path = fs::current_path().native();
364  #endif
365
366    bool boolRet = SCRSDK::Init();
367    if(!boolRet) GotoError("", 0);
368
369    // enumeration
370    {
371        uint32_t count = 0;
372        uint32_t index = 1;
373
374        err = SCRSDK::EnumCameraObjects(&enumCameraObjectInfo, 3/*timeInSec*/);
375        if(err || !enumCameraObjectInfo) GotoError("no camera", err);
376
377        count = enumCameraObjectInfo->GetCount();
378        if(count >= 2) {
379            for (uint32_t i = 0; i < count; ++i) {
380                auto* info = enumCameraObjectInfo->GetCameraObjectInfo(i);
381                CrCout << '[' << i + 1 << "] " << _getModelId(info) << "\n";
382            }
383
384            std::string inputLine;
385            std::cout << "select camera:"; std::getline(std::cin, inputLine);
386            try { index = stoi(inputLine); } catch(const std::exception&) { GotoError("", 0); }
387            if(index < 1 || index > count) GotoError("", 0);
388        }
389        objInfo = (SCRSDK::ICrCameraObjectInfo*)enumCameraObjectInfo->GetCameraObjectInfo(index - 1);
390        m_modelId = _getModelId(objInfo);
391    }
392
393    // connect
394    {
395        std::string  fingerprint = "";
396        std::string  userId = "";
397        std::string  userPassword = "";
398        std::promise<void> eventPromise;
399        std::future<void> eventFuture = eventPromise.get_future();
400
401        if (objInfo->GetSSHsupport() == SCRSDK::CrSSHsupport_ON) {
402            err = _getIdPassword(objInfo, fingerprint, userId, userPassword); if(err) goto Error;
403        }
404
405        setEventPromise(&eventPromise);
406        err = SCRSDK::Connect(objInfo, &deviceCallback, &m_device_handle,
407            SCRSDK::CrSdkControlMode_Remote,
408            SCRSDK::CrReconnecting_ON,
409            userId.c_str(), userPassword.c_str(), fingerprint.c_str(), (uint32_t)fingerprint.size());
410        if(err) GotoError("", err);
411
412    //  std::future_status status = eventFuture.wait_for(std::chrono::milliseconds(3000));
413    //  if(status != std::future_status::ready) GotoError("timeout",0);
414        try{
415            eventFuture.get();
416        } catch(const std::exception&) GotoError("", 0);
417    }
418
419    // set work directory
420    {
421        CrCout << "path=" << path.data() << "\n";
422        err = SCRSDK::SetSaveInfo(m_device_handle, const_cast<CrChar*>(path.data()), const_cast<CrChar*>(CRSTR("DSC")), -1/*startNo*/);
423        if(err) GotoError("", err);
424    }
425
426    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
427
428    std::cout << "usage:\n";
429    std::cout << "   setdp  <DP name> <param> [1-blocking,0-no blocking]\n";
430    std::cout << "   getdp  <DP name>\n";
431    std::cout << "   infodp <DP name>\n";
432    std::cout << "   listdp\n";
433    std::cout << "   send <command name> <param>\n";
434    std::cout << "   setcc  <control code> <param>\n";
435    std::cout << "   infocc <control code>\n";
436    std::cout << "   listcc\n";
437    std::cout << "To exit, please enter 'q'.\n";
438
439    while(1) {
440        std::string inputLine;
441        std::getline(std::cin, inputLine);
442        std::vector<std::string> args = _split(inputLine, ' ');
443
444        if(args.size() == 0) {
445
446        } else if(args[0] == "q" || args[0]== "Q") {
447            break;
448        } else if(args[0] == "send" && args.size() >= 3) {
449            int64_t data = 0;
450            int32_t code = CrCommandIdCode(args[1]);
451            if(code < 0) continue;
452            try{ data = _stoll(args[2]); } catch(const std::exception&) {continue;}
453
454            err = SCRSDK::SendCommand(m_device_handle, code, (SCRSDK::CrCommandParam)data);
455            if(err) GotoError("", err);
456
457        } else if(args[0] == "setdp" && args.size() >= 3) {
458            int64_t data = 0;
459            bool blocking = true;
460            int32_t code = CrDevicePropertyCode(args[1]);
461            if(code < 0) continue;
462
463            try{ data = _stoll(args[2]); } catch(const std::exception&) {continue;}
464            if(args.size() >= 4) 
465                try{ blocking = _stoll(args[3]); } catch(const std::exception&) {continue;}
466
467            err = _setDeviceProperty(m_device_handle, code, data, blocking);
468            if(err) continue;
469
470        } else if((args[0] == "getdp" || args[0] == "infodp") && args.size() >= 2) {
471        // device property get/info
472            int32_t code = CrDevicePropertyCode(args[1]);
473            if(code < 0) continue;
474
475            SCRSDK::CrDeviceProperty devProp;
476            err = _getDeviceProperty(m_device_handle, code, &devProp);
477            if(err) continue;
478            SCRSDK::CrDataType dataType = devProp.GetValueType();
479
480            if(args[0] == "getdp") {
481                if(dataType == SCRSDK::CrDataType_STR) {
482                    CrCout << _getCurrentStr(&devProp) << "\n";
483                } else {
484                    printf("0x%" PRIx64 "(%" PRId64 ")\n", devProp.GetCurrentValue(), devProp.GetCurrentValue());  // macro for %lld
485                }
486            } else if(args[0] == "infodp") {
487                printf("  get enable=%d\n", devProp.IsGetEnableCurrentValue());
488                printf("  set enable=%d\n", devProp.IsSetEnableCurrentValue());
489                printf("  variable  =%d\n", devProp.GetPropertyVariableFlag());
490                printf("  enable    =%d\n", devProp.GetPropertyEnableFlag());
491                printf("  valueType =0x%x\n", dataType);
492                if(dataType == SCRSDK::CrDataType_STR) {
493                    CrCout << "  current   =\"" << _getCurrentStr(&devProp) << "\"\n";
494                } else {
495                    printf("  current   =0x%" PRIx64 "(%" PRId64 ")\n", devProp.GetCurrentValue(), devProp.GetCurrentValue());
496
497                    std::vector<int64_t> possible = _getPossible(devProp.GetValueType(), devProp.GetValues(), devProp.GetValueSize());
498                    printf("  possible  =");
499                    for(int i = 0; i < possible.size(); i++) {
500                        printf("0x%" PRIx64 "(%" PRId64 "),", possible[i], possible[i]);
501                    }
502                    printf("\n");
503                }
504            }
505        } else if(args[0] == "listdp") {
506            std::int32_t nprop = 0;
507            SCRSDK::CrDeviceProperty* prop_list = nullptr;
508            SCRSDK::CrError err = SCRSDK::GetDeviceProperties(m_device_handle, &prop_list, &nprop);
509            if(err) GotoError("", err);
510
511            for(int i = 0; i < nprop; i++) {
512                printf("%s\n", CrDevicePropertyString((SCRSDK::CrDevicePropertyCode)prop_list[i].GetCode()).c_str());
513            }
514            SCRSDK::ReleaseDeviceProperties(m_device_handle, prop_list);
515
516        } else if(args[0] == "setcc" && args.size() >= 3) {
517            int64_t data = 0;
518            SCRSDK::CrControlCode code = CrControlCode(args[1]);
519            if(code < 0) continue;
520
521            SCRSDK::CrControlCodeInfo* info = NULL;
522            err = SCRSDK::GetSelectControlCode(m_device_handle, code, &info);
523            if(err) GotoError("", err);
524
525            SCRSDK::CrDataType dataType = info->GetValueType();
526            SCRSDK::ReleaseControlCodes(m_device_handle, info);
527
528            if(dataType != SCRSDK::CrDataType_STR) {
529                try{ data = _stoll(args[2]); } catch(const std::exception&) {continue;}
530                err = SCRSDK::ExecuteControlCodeValue(m_device_handle, code, data);
531                if(err) GotoError("", err);
532            } else {
533                CrString str = Utf8ToCr(args[2]);
534                size_t len = str.length() + 1;
535                if (len == 1) GotoError("Character size error", 0);
536                if (len > (size_t)info->GetValueSize()) GotoError("Character size error", 0);
537                std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter;
538                std::u16string utf16Str = converter.from_bytes(args[2]);
539                err = SCRSDK::ExecuteControlCodeString(m_device_handle, code, (CrInt16u)utf16Str.length() + 1, (CrInt16u*)utf16Str.c_str());
540                if(err) GotoError("", err);
541            }
542
543        } else if(args[0] == "infocc" && args.size() >= 2) {
544            int64_t data = 0;
545            SCRSDK::CrControlCode code = CrControlCode(args[1]);
546            if(code < 0) continue;
547
548            SCRSDK::CrControlCodeInfo* info = NULL;
549            err = SCRSDK::GetSelectControlCode(m_device_handle, code, &info);
550            if(err) GotoError("", err);
551
552            SCRSDK::CrDataType dataType = info->GetValueType();
553            printf("  code      =0x%x\n", code);
554            printf("  valueType =0x%x\n", dataType);
555            if(dataType != SCRSDK::CrDataType_STR) {
556                std::vector<int64_t> possible = _getPossible(dataType, info->GetValues(), info->GetValueSize());
557                printf("  possible  =");
558                for(int i = 0; i < possible.size(); i++) {
559                    printf("0x%" PRIx64 "(%" PRId64 "),", possible[i], possible[i]);
560                }
561                printf("\n");
562            }
563            SCRSDK::ReleaseControlCodes(m_device_handle, info);
564
565        } else if(args[0] == "listcc") {
566            SCRSDK::CrControlCodeInfo* infos = NULL;
567            CrInt32u numOfInfos = 0;
568            err = GetSupportedControlCodes(m_device_handle, &infos, &numOfInfos);
569            if(err) GotoError("", err);
570
571            for(int i = 0; i < (int)numOfInfos; i++) {
572                printf("%s\n", CrControlCodeString(infos[i].GetCode()).c_str());
573            }
574            SCRSDK::ReleaseControlCodes(m_device_handle, infos);
575
576        } else {
577            std::cout << "unknown command\n";
578        }
579    }
580
581    result = 0;
582Error:
583    if(enumCameraObjectInfo) enumCameraObjectInfo->Release();
584
585    if(m_connected) {
586        std::promise<void> eventPromise;
587        std::future<void> eventFuture = eventPromise.get_future();
588        setEventPromise(&eventPromise);
589        SCRSDK::Disconnect(m_device_handle);
590        int msec = 3000; // 3 seconds
591        if (m_lvProtocolChanged) msec *= 10; // x10
592        // If CrLiveViewProtocol_Alt is selected, the disconnection process may take some time.
593        eventFuture.wait_for(std::chrono::milliseconds(msec));
594    }
595    if (m_device_handle) SCRSDK::ReleaseDevice(m_device_handle);
596    SCRSDK::Release();
597
598    return result;
599}