sample code - “control FTP job”

usage:
   media <1~3(slot)>               - get content info on media
   add <1~3(slot)> <0~(contentId)> - add FTP job
   job                             - get job info
To exit, please enter 'q'.

This sample code is included in SimpleCli.

  1// "FTP job list" sample
  2#include <chrono>
  3#include <cstdint>
  4#include <cstdlib>
  5#include <fstream>
  6#include <future>
  7#include <iostream>
  8#include <mutex>
  9#include <sstream>
 10#include <stdexcept>
 11#include <string>
 12#include <thread>
 13#include <unordered_map>
 14#include <vector>
 15
 16#if !defined(__APPLE__)
 17  #if defined(USE_EXPERIMENTAL_FS) // for jetson
 18    #include <experimental/filesystem>
 19    namespace fs = std::experimental::filesystem;
 20  #else
 21    #include <filesystem>
 22    namespace fs = std::filesystem;
 23  #endif
 24#endif
 25
 26#if defined(__APPLE__) || defined(__linux__)
 27  #include <unistd.h>
 28#endif
 29
 30// macro for multibyte character
 31#if defined(_WIN32) || defined(_WIN64)
 32  using CrString = std::wstring;
 33  #define CRSTR(s) L ## s
 34  #define CrCout std::wcout
 35  #define CrCin std::wcin
 36  #define CrPrintf std::wprintf
 37#else
 38  using CrString = std::string;
 39  #define CRSTR(s) s
 40  #define CrCout std::cout
 41  #define CrCin std::cin
 42  #define CrPrintf std::printf
 43#endif
 44
 45
 46#include "CrDeviceProperty.h"
 47#include "CameraRemote_SDK.h"
 48#include "IDeviceCallback.h"
 49#include "CrDebugString.h"   // use CrDebugString.cpp
 50
 51#define PrintError(msg, err) { fprintf(stderr, "Error in %s(%d):" msg ",%s\n", __FUNCTION__, __LINE__, (err ? CrErrorString(err).c_str():"")); }
 52#define GotoError(msg, err) { PrintError(msg, err); goto Error; }
 53
 54bool  m_connected = false;
 55CrString m_modelId;
 56
 57std::mutex m_eventPromiseMutex;
 58std::promise<void>* m_eventPromise = nullptr;
 59void setEventPromise(std::promise<void>* dp)
 60{
 61    std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
 62    m_eventPromise = dp;
 63}
 64
 65SCRSDK::CrError _getDeviceProperty(int64_t device_handle, uint32_t code, SCRSDK::CrDeviceProperty* devProp)
 66{
 67    std::int32_t nprop = 0;
 68    SCRSDK::CrDeviceProperty* prop_list = nullptr;
 69    SCRSDK::CrError err = SCRSDK::GetSelectDeviceProperties(device_handle, 1, &code, &prop_list, &nprop);
 70    if(err) GotoError("", err);
 71    if(prop_list && nprop >= 1) {
 72        *devProp = prop_list[0];
 73    }
 74Error:
 75    if(prop_list) SCRSDK::ReleaseDeviceProperties(device_handle, prop_list);
 76    return err;
 77}
 78
 79class DeviceCallback : public SCRSDK::IDeviceCallback
 80{
 81public:
 82    DeviceCallback() {};
 83    ~DeviceCallback() {};
 84
 85    void OnConnected(SCRSDK::DeviceConnectionVersioin version)
 86    {
 87        CrCout << "Connected to " << m_modelId << "\n";
 88        m_connected = true;
 89        std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
 90        if(m_eventPromise) {
 91            m_eventPromise->set_value();
 92            m_eventPromise = nullptr;
 93        }
 94    }
 95
 96    void OnError(CrInt32u error)
 97    {
 98        printf("Connection error:%s\n", CrErrorString(error).c_str());
 99        std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
100        if(m_eventPromise) {
101            m_eventPromise->set_exception(std::make_exception_ptr(std::runtime_error("error")));
102            m_eventPromise = nullptr;
103        }
104    }
105
106    void OnDisconnected(CrInt32u error)
107    {
108        CrCout << "Disconnected from " << m_modelId << "\n";
109        m_connected = false;
110        std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
111        if(m_eventPromise) {
112            m_eventPromise->set_value();
113            m_eventPromise = nullptr;
114        }
115    }
116
117    void OnCompleteDownload(CrChar* filename, CrInt32u type)
118    {
119        CrCout << "OnCompleteDownload:" << filename << "\n";
120    }
121
122    void OnNotifyContentsTransfer(CrInt32u notify, SCRSDK::CrContentHandle contentHandle, CrChar* filename)
123    {
124        std::cout << "OnNotifyContentsTransfer.\n";
125    }
126
127    void OnWarning(CrInt32u warning)
128    {
129        if (warning == SCRSDK::CrWarning_Connect_Reconnecting) {
130            CrCout << "Reconnecting to " << m_modelId << "\n";
131            return;
132        }
133        std::cout << "OnWarning:" << CrErrorString(warning) << "\n";
134        std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
135        switch(warning) {
136        case SCRSDK::CrWarning_RequestFTPJobList_Result_Success:
137        case SCRSDK::CrWarning_ControlFTPJobList_Set_Result_OK:
138            if(m_eventPromise) {
139                m_eventPromise->set_value();
140                m_eventPromise = nullptr;
141            }
142            break;
143
144        case SCRSDK::CrWarning_RequestFTPJobList_Result_DeviceBusy:
145        case SCRSDK::CrWarning_RequestFTPJobList_Result_Error:
146        case SCRSDK::CrWarning_ControlFTPJobList_Set_Result_Invalid:
147        case SCRSDK::CrWarning_ControlFTPJobList_Set_Result_NG:
148        case SCRSDK::CrWarning_ControlFTPJobList_Set_Result_DeviceBusy:
149            if(m_eventPromise) {
150                m_eventPromise->set_exception(std::make_exception_ptr(std::runtime_error("error")));
151                m_eventPromise = nullptr;
152            }
153            break;
154        }
155    }
156
157
158    void OnWarningExt(CrInt32u warning, CrInt32 param1, CrInt32 param2, CrInt32 param3)
159    {
160        std::cout << "OnWarningExt:" << CrWarningExtString(warning, param1, param2, param3).c_str() << "\n";
161    }
162
163    void OnLvPropertyChanged() {}
164    void OnLvPropertyChangedCodes(CrInt32u num, CrInt32u* codes) {}
165    void OnPropertyChanged() {}
166    void OnPropertyChangedCodes(CrInt32u num, CrInt32u* codes) {}
167
168    void OnNotifyFTPTransferResult(CrInt32u notify, CrInt32u numOfSuccess, CrInt32u numOfFail)
169    {
170        std::cout << "OnNotifyFTPTransferResult" << CrErrorString(notify) << "\n";
171    }
172};
173
174CrString _getModelId(const SCRSDK::ICrCameraObjectInfo* objInfo)
175{
176    CrString id;
177    if (CrString(objInfo->GetConnectionTypeName()) == CRSTR("IP")) {
178        id = CrString(objInfo->GetMACAddressChar());
179    } else {
180        id = CrString((CrChar*)objInfo->GetId());
181    }
182    return CrString(objInfo->GetModel()).append(CRSTR(" (")).append(id).append(CRSTR(")"));
183}
184
185SCRSDK::CrError _getIdPassword(SCRSDK::ICrCameraObjectInfo* objInfo, std::string& fingerprint, std::string& userId, std::string& userPassword)
186{
187    char fpBuff[128] = {0};
188    CrInt32u fpLen = 0;
189    SCRSDK::CrError err = SCRSDK::GetFingerprint(objInfo, fpBuff, &fpLen);
190    if(err) GotoError("", err);
191    fingerprint = std::string(fpBuff, fpLen);
192
193    std::cout << "fingerprint: " << fingerprint.c_str() << "\n";
194    std::cout << "id:";       std::getline(std::cin, userId);
195    std::cout << "password:"; std::getline(std::cin, userPassword);
196    return 0;
197Error:
198    return err;
199}
200
201SCRSDK::CrError _getMediaProfile(int64_t device_handle, SCRSDK::CrMediaProfile slot)
202{
203    int result = SCRSDK::CrError_Generic_Unknown;
204    SCRSDK::CrError err = SCRSDK::CrError_None;
205
206    {
207        const std::unordered_map<SCRSDK::CrMediaProfile, SCRSDK::CrDevicePropertyCode> map_DP_status
208        {
209            {SCRSDK::CrMediaProfile_Slot1, SCRSDK::CrDeviceProperty_MediaSLOT1_Status},
210            {SCRSDK::CrMediaProfile_Slot2, SCRSDK::CrDeviceProperty_MediaSLOT2_Status},
211            {SCRSDK::CrMediaProfile_Slot3, SCRSDK::CrDeviceProperty_MediaSLOT3_Status},
212        };
213
214        SCRSDK::CrDeviceProperty devProp;
215
216        auto iter = map_DP_status.find(slot);
217        if(iter == end(map_DP_status)) GotoError("", 0);
218
219        err = _getDeviceProperty(device_handle, (uint32_t)iter->second, &devProp);
220        if(err) GotoError("", err);
221        if(devProp.GetCurrentValue() != (int)SCRSDK::CrSlotStatus_OK) GotoError("not ready", 0);
222    }
223
224    {
225        CrInt32u nums = 0;
226        SCRSDK::CrMediaProfileInfo* mediaProfileList = nullptr;
227        err = SCRSDK::GetMediaProfile(device_handle, slot, &mediaProfileList, &nums);
228        if(err || nums == 0) GotoError("", err);
229
230        for (CrInt32u i = 0; i < nums; i++) {
231            #define _CHAR(a) (a ? (const char*)a : "")
232            
233            printf("id:%d\n", i);
234            std::cout << "contentName:" << _CHAR(mediaProfileList[i].contentName) << "\n";
235            std::cout << "contentUrl:" << _CHAR(mediaProfileList[i].contentUrl) << "\n";
236            std::cout << "contentType:" << _CHAR(mediaProfileList[i].contentType) << "\n";
237            std::cout << "contentFrameRate:" << _CHAR(mediaProfileList[i].contentFrameRate) << "\n";
238            std::cout << "contentAspectRatio:" << _CHAR(mediaProfileList[i].contentAspectRatio) << "\n";
239            std::cout << "contentChannel:" << _CHAR(mediaProfileList[i].contentChannel) << "\n";
240            std::cout << "contentVideoType:" << _CHAR(mediaProfileList[i].contentVideoType) << "\n";
241            std::cout << "contentAudioType:" << _CHAR(mediaProfileList[i].contentAudioType) << "\n";
242            if (mediaProfileList[i].proxyUrl != nullptr) {
243                std::cout << "proxyUrl:" << _CHAR(mediaProfileList[i].proxyUrl) << "\n";
244                std::cout << "proxyType:" << _CHAR(mediaProfileList[i].proxyType) << "\n";
245                std::cout << "proxyFrameRate:" << _CHAR(mediaProfileList[i].proxyFrameRate) << "\n";
246                std::cout << "proxyAspectRatio:" << _CHAR(mediaProfileList[i].proxyAspectRatio) << "\n";
247                std::cout << "proxyChannel:" << _CHAR(mediaProfileList[i].proxyChannel) << "\n";
248                std::cout << "proxyVideoType:" << _CHAR(mediaProfileList[i].proxyVideoType) << "\n";
249                std::cout << "proxyAudioType:" << _CHAR(mediaProfileList[i].proxyAudioType) << "\n";
250            }
251            std::cout << "thumbnailUrl:" << _CHAR(mediaProfileList[i].thumbnailUrl) << "\n";
252            std::cout << "metaUrl:" << _CHAR(mediaProfileList[i].metaUrl) << "\n";
253
254            std::cout << "umid:";
255            for(int j = 0; j < 32; j++) {
256                printf("%02x", mediaProfileList[i].umid[j]);
257            }
258            std::cout << "\n";
259
260            printf("duration:%d\n", mediaProfileList[i].duration);
261            printf("restrictionFrame:%d\n", mediaProfileList[i].restrictionFrame);
262            printf("isTrimmingAvailable:%d\n", mediaProfileList[i].isTrimmingAvailable);
263            std::cout << "\n";
264        }
265        SCRSDK::ReleaseMediaProfile(device_handle, mediaProfileList);
266    }
267Error:
268    return err;
269}
270
271SCRSDK::CrError _addMediaProfileToFTPJob(int64_t device_handle, SCRSDK::CrMediaProfile slot, uint32_t mediaIndex, uint32_t proxyFlag)
272{
273    int result = SCRSDK::CrError_Generic_Unknown;
274    SCRSDK::CrError err = SCRSDK::CrError_None;
275
276    SCRSDK::CrDeviceProperty devProp;
277    CrInt32u nums = 0;
278    SCRSDK::CrMediaProfileInfo* mediaProfileList = nullptr;
279    SCRSDK::CrFTPJobSetting* ftpJobSetting = nullptr;
280    std::promise<void> eventPromise;
281    std::future<void> eventFuture = eventPromise.get_future();
282
283    err = SCRSDK::GetMediaProfile(device_handle, slot, &mediaProfileList, &nums);
284    if(err || nums == 0 || mediaIndex >= nums) GotoError("", err);
285
286    err = _getDeviceProperty(device_handle, SCRSDK::CrDeviceProperty_SelectFTPServerID, &devProp);
287    if(err) GotoError("", err);
288
289    if (proxyFlag) {
290        if(mediaProfileList[mediaIndex].proxyUrl == nullptr) GotoError("no proxy", 0);
291
292        ftpJobSetting = new SCRSDK::CrFTPJobSetting(
293            /*trimType*/ SCRSDK::CrFTPJobTrimType_NoTrim,
294            /*serverId*/ (CrInt32u)devProp.GetCurrentValue(),
295            /*slotId*/ (SCRSDK::CrFTPJobSlotId)slot,
296            /*clipPath*/ (char*)mediaProfileList[mediaIndex].proxyUrl,
297            /*metaPath*/ nullptr,
298            /*transferDir*/ nullptr,
299            /*inFrame*/ 0,
300            /*outFrame*/ 0,
301            /*duration*/ 0,
302            /*destClipName*/ nullptr,
303            /*umid*/ nullptr,
304            /*videoType*/ nullptr,
305            /*compJobAction*/ SCRSDK::CrFTPJobCompleteAction_NoAction,
306            /*deleteJobAction*/ SCRSDK::CrFTPJobDeleteAction_NoAction);
307    } else {
308        ftpJobSetting = new SCRSDK::CrFTPJobSetting(
309            /*trimType*/ SCRSDK::CrFTPJobTrimType_NoTrim,
310            /*serverId*/ (CrInt32u)devProp.GetCurrentValue(),
311            /*slotId*/ (SCRSDK::CrFTPJobSlotId)slot,
312            /*clipPath*/ (char*)mediaProfileList[mediaIndex].contentUrl,
313            /*metaPath*/ (char*)mediaProfileList[mediaIndex].metaUrl,
314            /*transferDir*/ nullptr,
315            /*inFrame*/ 0,
316            /*outFrame*/ 0,
317            /*duration*/ 0,
318            /*destClipName*/ nullptr,
319            /*umid*/ nullptr,
320            /*videoType*/ nullptr,
321            /*compJobAction*/ SCRSDK::CrFTPJobCompleteAction_NoAction,
322            /*deleteJobAction*/ SCRSDK::CrFTPJobDeleteAction_NoAction);
323    }
324    setEventPromise(&eventPromise);
325
326    err = SCRSDK::ControlFTPJobList(device_handle, SCRSDK::CrFTPJobControlType_Add, ftpJobSetting, 1, SCRSDK::CrFTPJobDeleteType_Individual);
327    if(err) GotoError("", err);
328
329    try{
330        eventFuture.get();
331    } catch(const std::exception&) GotoError("", 0);
332    result = 0;
333Error:
334    setEventPromise(nullptr);
335    if(ftpJobSetting) delete ftpJobSetting;
336    return result;
337}
338
339
340void _printFTPJobInfo(SCRSDK::CrFTPJobInfo* jobInfo)
341{
342    #define _printChar(msg, dp) { \
343        const char* _dp = dp; \
344        std::cout << msg; \
345        if(_dp) std::cout << _dp; \
346        std::cout << "\n"; \
347    }
348
349    printf("jobId:%d\n",        jobInfo->jobId);
350    printf("serverId:%d\n",     jobInfo->serverId);
351    printf("slotId:%d\n",       jobInfo->slotId);
352    printf("jobStatus:%d\n",    jobInfo->jobStatus);
353    printf("chunkNum:%d\n",     jobInfo->chunkNum);
354    printf("fileSize:%d\n",     (int)jobInfo->fileSize);
355    printf("transferSize:%d\n", (int)jobInfo->transferSize);
356    _printChar("clipName:",     jobInfo->GetClipName());
357    _printChar("mainName:",     jobInfo->GetMainName());
358    _printChar("metaName:",     jobInfo->GetMetaName());
359    return;
360}
361
362SCRSDK::CrError _getFTPJobInfo(int64_t device_handle/*, uint32_t index*/)
363{
364    int result = SCRSDK::CrError_Generic_Unknown;
365    SCRSDK::CrError err = SCRSDK::CrError_None;
366    std::promise<void> eventPromise;
367    std::future<void> eventFuture = eventPromise.get_future();
368
369    // request FTPJobList
370    setEventPromise(&eventPromise);
371
372    err = SCRSDK::RequestFTPJobList(device_handle);
373    if(err) GotoError("", err);
374
375    try{
376        eventFuture.get();
377    } catch(const std::exception&) GotoError("", 0);
378
379    // Get FTPJobList
380    {
381        SCRSDK::CrFTPJobInfo* ftpJobList = nullptr;
382        CrInt32u ftpJobListSize = 0;
383
384        err = SCRSDK::GetFTPJobList(device_handle, &ftpJobList, &ftpJobListSize);
385        if(err || ftpJobListSize == 0) GotoError("", err);
386
387        for(uint32_t i = 0; i < ftpJobListSize; i++) {
388            _printFTPJobInfo(ftpJobList + i);
389            std::cout << "\n";
390        }
391        SCRSDK::ReleaseFTPJobList(device_handle, ftpJobList);
392    }
393
394    result = 0;
395Error:
396    setEventPromise(nullptr);
397    return result;
398}
399
400std::vector<std::string> _split(std::string inputLine, char delimiter)
401{
402    std::vector<std::string> strArray;
403    if (inputLine.empty()) return strArray;
404
405    std::string tmp;
406    std::stringstream ss{inputLine};
407    while (getline(ss, tmp, delimiter)) {
408        strArray.push_back(tmp);
409    }
410    return strArray;
411}
412
413int main(void)
414{
415    int result = -1;
416    SCRSDK::CrError err = SCRSDK::CrError_None;
417    int64_t  m_device_handle = 0;
418    SCRSDK::ICrEnumCameraObjectInfo* enumCameraObjectInfo = nullptr;
419    SCRSDK::ICrCameraObjectInfo* objInfo = nullptr;
420    DeviceCallback deviceCallback;
421
422  #if defined(__APPLE__)
423    #define MAC_MAX_PATH 255
424    char pathBuf[MAC_MAX_PATH] = {0};
425    if(NULL == getcwd(pathBuf, sizeof(pathBuf) - 1)) return 1;
426    CrString path = pathBuf;
427  #else
428    CrString path = fs::current_path().native();
429  #endif
430
431    bool boolRet = SCRSDK::Init();
432    if(!boolRet) GotoError("", 0);
433
434    // enumeration
435    {
436        uint32_t count = 0;
437        uint32_t index = 1;
438
439        err = SCRSDK::EnumCameraObjects(&enumCameraObjectInfo, 3/*timeInSec*/);
440        if(err || !enumCameraObjectInfo) GotoError("no camera", err);
441
442        count = enumCameraObjectInfo->GetCount();
443        if(count >= 2) {
444            for (uint32_t i = 0; i < count; ++i) {
445                auto* info = enumCameraObjectInfo->GetCameraObjectInfo(i);
446                CrCout << '[' << i + 1 << "] " << _getModelId(info) << "\n";
447            }
448
449            std::string inputLine;
450            std::cout << "select camera:"; std::getline(std::cin, inputLine);
451            try { index = stoi(inputLine); } catch(const std::exception&) { GotoError("", 0); }
452            if(index < 1 || index > count) GotoError("", 0);
453        }
454        objInfo = (SCRSDK::ICrCameraObjectInfo*)enumCameraObjectInfo->GetCameraObjectInfo(index - 1);
455        m_modelId = _getModelId(objInfo);
456    }
457
458    // connect
459    {
460        std::string  fingerprint = "";
461        std::string  userId = "";
462        std::string  userPassword = "";
463        std::promise<void> eventPromise;
464        std::future<void> eventFuture = eventPromise.get_future();
465
466        if (objInfo->GetSSHsupport() == SCRSDK::CrSSHsupport_ON) {
467            err = _getIdPassword(objInfo, fingerprint, userId, userPassword); if(err) goto Error;
468        }
469
470        setEventPromise(&eventPromise);
471        err = SCRSDK::Connect(objInfo, &deviceCallback, &m_device_handle,
472            SCRSDK::CrSdkControlMode_Remote,
473            SCRSDK::CrReconnecting_ON,
474            userId.c_str(), userPassword.c_str(), fingerprint.c_str(), (uint32_t)fingerprint.size());
475        if(err) GotoError("", err);
476
477    //  std::future_status status = eventFuture.wait_for(std::chrono::milliseconds(3000));
478    //  if(status != std::future_status::ready) GotoError("timeout",0);
479        try{
480            eventFuture.get();
481        } catch(const std::exception&) GotoError("", 0);
482    }
483
484    // set work directory
485    {
486        CrCout << "path=" << path.data() << "\n";
487        err = SCRSDK::SetSaveInfo(m_device_handle, const_cast<CrChar*>(path.data()), const_cast<CrChar*>(CRSTR("DSC")), -1/*startNo*/);
488        if(err) GotoError("", err);
489    }
490
491    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
492
493    std::cout << "usage:\n";
494    std::cout << "   media <1~3(slot)>               - get content info on media\n";
495    std::cout << "   add <1~3(slot)> <0~(contentId)> - add FTP job\n";
496    std::cout << "   job                             - get job info\n";
497    std::cout << "To exit, please enter 'q'.\n";
498
499    while(1) {
500        std::string inputLine;
501        std::getline(std::cin, inputLine);
502        std::vector<std::string> args = _split(inputLine, ' ');
503
504        if(args.size() == 0) {
505            
506        } else if((args[0] == "media" || args[0] == "m") && args.size() >= 2) {
507            int slot = 0;
508            try {
509                slot = stol(args[1]);
510            } catch(const std::exception&) { GotoError("", 0); }
511            err = _getMediaProfile(m_device_handle, (SCRSDK::CrMediaProfile)slot);
512            if(err) goto Error;
513
514        } else if((args[0] == "add" || args[0] == "a") && args.size() >= 3) {
515            int slot = 0;
516            int mediaIndex = 0;
517            int proxyFlag = 0;
518            try {
519                slot = stol(args[1]);
520                mediaIndex = stol(args[2]);
521                if(args.size() >= 4) proxyFlag = stol(args[3]);
522            } catch(const std::exception&) { GotoError("", 0); }
523
524            err = _addMediaProfileToFTPJob(m_device_handle, (SCRSDK::CrMediaProfile)slot, mediaIndex, proxyFlag);
525            if(err) goto Error;
526
527        } else if((args[0] == "job" || args[0] == "j") ) {
528            err = _getFTPJobInfo(m_device_handle);
529            if(err) goto Error;
530
531        } else if(args[0] == "q" || args[0] == "Q") {
532            break;
533        } else {
534            std::cout << "unknown command\n";
535        }
536    }
537
538    result = 0;
539Error:
540    if(enumCameraObjectInfo) enumCameraObjectInfo->Release();
541
542    if(m_connected) {
543        std::promise<void> eventPromise;
544        std::future<void> eventFuture = eventPromise.get_future();
545        setEventPromise(&eventPromise);
546        SCRSDK::Disconnect(m_device_handle);
547        eventFuture.wait_for(std::chrono::milliseconds(3000));
548    }
549    if(m_device_handle) SCRSDK::ReleaseDevice(m_device_handle);
550    SCRSDK::Release();
551
552    return result;
553}