sample code - “Pull out content in ContentsTransferMode”¶
This sample code is included in SimpleCli.
1// "pull contents in ContentsTransferMode" 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 <vector>
14
15#if !defined(__APPLE__)
16 #if defined(USE_EXPERIMENTAL_FS) // for jetson
17 #include <experimental/filesystem>
18 namespace fs = std::experimental::filesystem;
19 #else
20 #include <filesystem>
21 namespace fs = std::filesystem;
22 #endif
23#endif
24
25#if defined(__APPLE__) || defined(__linux__)
26 #include <unistd.h>
27#endif
28
29// macro for multibyte character
30#if defined(_WIN32) || defined(_WIN64)
31 using CrString = std::wstring;
32 #define CRSTR(s) L ## s
33 #define CrCout std::wcout
34 #define CrPrintf std::wprintf
35 #define DELIMITER CRSTR("\\")
36#else
37 using CrString = std::string;
38 #define CRSTR(s) s
39 #define CrCout std::cout
40 #define CrPrintf std::printf
41 #define DELIMITER CRSTR("/")
42#endif
43
44
45#include "CrDeviceProperty.h"
46#include "CameraRemote_SDK.h"
47#include "IDeviceCallback.h"
48#include "CrDebugString.h" // use CrDebugString.cpp
49
50#define PrintError(msg, err) { fprintf(stderr, "Error in %s(%d):" msg ",%s\n", __FUNCTION__, __LINE__, (err ? CrErrorString(err).c_str():"")); }
51#define GotoError(msg, err) { PrintError(msg, err); goto Error; }
52
53bool m_connected = false;
54CrString m_modelId;
55int64_t m_device_handle = 0;
56
57std::mutex m_eventPromiseMutex;
58uint32_t m_setDPCode = 0;
59std::promise<void>* m_eventPromise = nullptr;
60void setEventPromise(std::promise<void>* dp)
61{
62 std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
63 m_eventPromise = dp;
64}
65
66SCRSDK::CrError _getDeviceProperty(int64_t device_handle, uint32_t code, SCRSDK::CrDeviceProperty* devProp)
67{
68 std::int32_t nprop = 0;
69 SCRSDK::CrDeviceProperty* prop_list = nullptr;
70 SCRSDK::CrError err = SCRSDK::GetSelectDeviceProperties(device_handle, 1, &code, &prop_list, &nprop);
71 if(err) GotoError("", err);
72 if(prop_list && nprop >= 1) {
73 *devProp = prop_list[0];
74 }
75Error:
76 if(prop_list) SCRSDK::ReleaseDeviceProperties(device_handle, prop_list);
77 return err;
78}
79
80class DeviceCallback : public SCRSDK::IDeviceCallback
81{
82public:
83 DeviceCallback() {};
84 ~DeviceCallback() {};
85
86 void OnConnected(SCRSDK::DeviceConnectionVersioin version)
87 {
88 CrCout << "Connected to " << m_modelId << "\n";
89 m_connected = true;
90 std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
91 if(m_eventPromise) {
92 m_eventPromise->set_value();
93 m_eventPromise = nullptr;
94 }
95 }
96
97 void OnError(CrInt32u error)
98 {
99 printf("Connection error:%s\n", CrErrorString(error).c_str());
100 std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
101 if(m_eventPromise) {
102 m_eventPromise->set_exception(std::make_exception_ptr(std::runtime_error("error")));
103 m_eventPromise = nullptr;
104 }
105 }
106
107 void OnDisconnected(CrInt32u error)
108 {
109 CrCout << "Disconnected from " << m_modelId << "\n";
110 m_connected = false;
111 std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
112 if(m_eventPromise) {
113 m_eventPromise->set_value();
114 m_eventPromise = nullptr;
115 }
116 }
117
118 void OnCompleteDownload(CrChar* filename, CrInt32u type )
119 {
120 CrCout << "OnCompleteDownload:" << filename << "\n";
121 }
122
123 void OnNotifyContentsTransfer(CrInt32u notify, SCRSDK::CrContentHandle contentHandle, CrChar* filename)
124 {
125 std::cout << "OnNotifyContentsTransfer(" << CrErrorString(notify) << "):";
126 std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
127 switch(notify) {
128 case SCRSDK::CrNotify_ContentsTransfer_Start:
129 break;
130 case SCRSDK::CrNotify_ContentsTransfer_Complete:
131 CrCout << filename;
132 if(m_eventPromise) {
133 m_eventPromise->set_value();
134 m_eventPromise = nullptr;
135 }
136 break;
137 default:
138 if(m_eventPromise) {
139 m_eventPromise->set_exception(std::make_exception_ptr(std::runtime_error("error")));
140 m_eventPromise = nullptr;
141 }
142 break;
143 }
144 std::cout << "\n";
145 }
146
147 void OnWarning(CrInt32u warning)
148 {
149 if (warning == SCRSDK::CrWarning_Connect_Reconnecting) {
150 CrCout << "Reconnecting to " << m_modelId << "\n";
151 return;
152 }
153 std::cout << "OnWarning:" << CrErrorString(warning) << "\n";
154 switch(warning) {
155 case SCRSDK::CrWarning_ContentsTransferMode_DeviceBusy:
156 case SCRSDK::CrWarning_ContentsTransferMode_StatusError:
157 case SCRSDK::CrWarning_ContentsTransferMode_CanceledFromCamera:
158 if(m_eventPromise) {
159 m_eventPromise->set_exception(std::make_exception_ptr(std::runtime_error("error")));
160 m_eventPromise = nullptr;
161 }
162 break;
163 }
164 }
165
166 void OnWarningExt(CrInt32u warning, CrInt32 param1, CrInt32 param2, CrInt32 param3) {}
167 void OnLvPropertyChanged() {}
168 void OnLvPropertyChangedCodes(CrInt32u num, CrInt32u* codes) {}
169 void OnPropertyChanged() {}
170 void OnPropertyChangedCodes(CrInt32u num, CrInt32u* codes)
171 {
172 for(uint32_t i = 0; i < num; ++i) {
173 std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
174 if(m_setDPCode && m_setDPCode == codes[i]) {
175 std::string name = CrDevicePropertyString((SCRSDK::CrDevicePropertyCode)codes[i]);
176 SCRSDK::CrDeviceProperty devProp;
177 SCRSDK::CrError err = _getDeviceProperty(m_device_handle, codes[i], &devProp);
178 if(err) break;
179 int64_t current = devProp.GetCurrentValue();
180 printf("OnPropertyChangedCodes:%s=%d\n", name.c_str(), (int)current);
181 m_setDPCode = 0;
182 if(m_eventPromise) {
183 m_eventPromise->set_value();
184 m_eventPromise = nullptr;
185 }
186 }
187 }
188 }
189};
190
191CrString _getModelId(const SCRSDK::ICrCameraObjectInfo* objInfo)
192{
193 CrString id;
194 if (CrString(objInfo->GetConnectionTypeName()) == CRSTR("IP")) {
195 id = CrString(objInfo->GetMACAddressChar());
196 } else {
197 id = CrString((CrChar*)objInfo->GetId());
198 }
199 return CrString(objInfo->GetModel()).append(CRSTR(" (")).append(id).append(CRSTR(")"));
200}
201
202SCRSDK::CrError _getIdPassword(SCRSDK::ICrCameraObjectInfo* objInfo, std::string& fingerprint, std::string& userId, std::string& userPassword)
203{
204 char fpBuff[128] = {0};
205 CrInt32u fpLen = 0;
206 SCRSDK::CrError err = SCRSDK::GetFingerprint(objInfo, fpBuff, &fpLen);
207 if(err) GotoError("", err);
208 fingerprint = std::string(fpBuff, fpLen);
209
210 std::cout << "fingerprint: " << fingerprint.c_str() << "\n";
211 std::cout << "id:"; std::getline(std::cin, userId);
212 std::cout << "password:"; std::getline(std::cin, userPassword);
213 return 0;
214Error:
215 return err;
216}
217
218SCRSDK::CrError _getThumbnail(int64_t m_device_handle, SCRSDK::CrContentHandle content, CrString path)
219{
220 int result = SCRSDK::CrError_Generic_Unknown;
221 SCRSDK::CrError err = 0;
222 #define BUF_SIZE 0x28000 // @@@@ temp
223 SCRSDK::CrImageDataBlock image_data;
224 CrInt8u image_buff[BUF_SIZE];
225 SCRSDK::CrFileType fileType = SCRSDK::CrFileType_None;
226
227 image_data.SetSize(BUF_SIZE);
228 image_data.SetData(image_buff);
229
230 err = SCRSDK::GetContentsThumbnailImage(m_device_handle, content, &image_data, &fileType);
231 if(err) GotoError("", err);
232
233 if (image_data.GetSize() <= 0 || fileType == SCRSDK::CrFileType_None)
234 GotoError("", 0);
235
236 {
237 CrString filename = DELIMITER CRSTR("Thumbnail.JPG");
238 if (fileType == SCRSDK::CrFileType_Heif) {
239 filename= DELIMITER CRSTR("Thumbnail.HIF");
240 }
241 filename = path.append(filename);
242 std::ofstream file(filename, std::ios::out | std::ios::binary);
243 if (file.bad()) GotoError("", 0);
244
245 file.write((char*)image_data.GetImageData(), image_data.GetImageSize());
246 file.close();
247 CrCout << "complete:" << filename.data() << "\n";
248 }
249 result = 0;
250Error:
251 return result;
252}
253
254int main(void)
255{
256 int result = -1;
257 SCRSDK::CrError err = SCRSDK::CrError_None;
258 SCRSDK::ICrEnumCameraObjectInfo* enumCameraObjectInfo = nullptr;
259 SCRSDK::ICrCameraObjectInfo* objInfo = nullptr;
260 DeviceCallback deviceCallback;
261
262 SCRSDK::CrMtpFolderInfo* folderList = nullptr;
263 SCRSDK::CrContentHandle* contentsHandleList = nullptr;
264 std::string inputLine;
265
266 #if defined(__APPLE__)
267 #define MAC_MAX_PATH 255
268 char pathBuf[MAC_MAX_PATH] = {0};
269 if(NULL == getcwd(pathBuf, sizeof(pathBuf) - 1)) return 1;
270 CrString path = pathBuf;
271 #else
272 CrString path = fs::current_path().native();
273 #endif
274
275 bool boolRet = SCRSDK::Init();
276 if(!boolRet) GotoError("", 0);
277
278 // enumeration
279 {
280 uint32_t count = 0;
281 uint32_t index = 1;
282
283 err = SCRSDK::EnumCameraObjects(&enumCameraObjectInfo, 3/*timeInSec*/);
284 if(err || !enumCameraObjectInfo) GotoError("no camera", err);
285
286 count = enumCameraObjectInfo->GetCount();
287 if(count >= 2) {
288 for (uint32_t i = 0; i < count; ++i) {
289 auto* info = enumCameraObjectInfo->GetCameraObjectInfo(i);
290 CrCout << '[' << i + 1 << "] " << _getModelId(info) << "\n";
291 }
292
293 std::cout << "select camera:"; std::getline(std::cin, inputLine);
294 try { index = stoi(inputLine); } catch(const std::exception&) { GotoError("", 0); }
295 if(index < 1 || index > count) GotoError("", 0);
296 }
297 objInfo = (SCRSDK::ICrCameraObjectInfo*)enumCameraObjectInfo->GetCameraObjectInfo(index - 1);
298 m_modelId = _getModelId(objInfo);
299 }
300
301 // connect
302 {
303 std::string fingerprint = "";
304 std::string userId = "";
305 std::string userPassword = "";
306 std::promise<void> eventPromise;
307 std::future<void> eventFuture = eventPromise.get_future();
308
309 if (objInfo->GetSSHsupport() == SCRSDK::CrSSHsupport_ON) {
310 err = _getIdPassword(objInfo, fingerprint, userId, userPassword); if(err) goto Error;
311 }
312
313 setEventPromise(&eventPromise);
314 err = SCRSDK::Connect(objInfo, &deviceCallback, &m_device_handle,
315 SCRSDK::CrSdkControlMode_ContentsTransfer,
316 SCRSDK::CrReconnecting_ON,
317 userId.c_str(), userPassword.c_str(), fingerprint.c_str(), (uint32_t)fingerprint.size());
318 if(err) GotoError("", err);
319
320 // std::future_status status = eventFuture.wait_for(std::chrono::milliseconds(3000));
321 // if(status != std::future_status::ready) GotoError("timeout",0);
322 try{
323 eventFuture.get();
324 } catch(const std::exception&) GotoError("", 0);
325 }
326
327 // wait contentsTransfer=ON
328 {
329 SCRSDK::CrDeviceProperty devProp;
330 std::promise<void> eventPromise;
331 std::future<void> eventFuture = eventPromise.get_future();
332 {
333 std::lock_guard<std::mutex> lock(m_eventPromiseMutex);
334 m_setDPCode = SCRSDK::CrDeviceProperty_ContentsTransferStatus;
335 m_eventPromise = &eventPromise;
336 }
337
338 try{
339 eventFuture.get();
340 } catch(const std::exception&) GotoError("", 0);
341
342 err = _getDeviceProperty(m_device_handle, SCRSDK::CrDeviceProperty_ContentsTransferStatus, &devProp);
343 if(err) GotoError("", err);
344 if(devProp.GetCurrentValue() != SCRSDK::CrContentsTransfer_ON) GotoError("", 0);
345 }
346
347 // set work directory
348 {
349 CrCout << "path=" << path.data() << "\n";
350 err = SCRSDK::SetSaveInfo(m_device_handle, const_cast<CrChar*>(path.data()), const_cast<CrChar*>(CRSTR("DSC")), -1/*startNo*/);
351 if(err) GotoError("", err);
352 }
353
354 #if defined(__linux__)
355 {
356 // The default value for Linux is 16MB.
357 // The number of divisions is inversely proportional to the "Setting_Key_PartialBuffer" size, and the larger the "Setting_Key_PartialBuffer" size, the fewer accesses between the camera and SDK, improving the processing performance of the SDK and Body.
358 // The number of times the "CrCommandId_CancelContentsTransfer/CrControlCode_CancelContentsTransfer" can be accepted also changes in sync with the number of accesses, so users who want to perform "CrCommandId_CancelContentsTransfer/CrControlCode_CancelContentsTransfer" should not make the "Setting_Key_PartialBuffer" size too large.
359 //
360 // e.g. 150MB RAW image
361 // "Setting_Key_PartialBuffer" size 16MB -> 10 divisions
362 // "Setting_Key_PartialBuffer" size 64MB -> 3 divisions
363 //
364 // Caution : Do not set a value larger than the USB bulk transfer size.
365
366 CrInt32u bufferSize = 0;
367 err = SCRSDK::GetDeviceSetting(m_device_handle, SCRSDK::Setting_Key_PartialBuffer, &bufferSize);
368 if(err) GotoError("", err);
369 printf("PartialBuffer %d[MB]->", bufferSize); std::getline(std::cin, inputLine);
370 if(inputLine != "") {
371 try { bufferSize = stoi(inputLine); } catch(const std::exception&) { GotoError("", 0); }
372 err = SCRSDK::SetDeviceSetting(m_device_handle, SCRSDK::Setting_Key_PartialBuffer, bufferSize);
373 if(err) GotoError("", err);
374 }
375 }
376 #else
377 // The default value for non-Linux is 2047MB (approximately 2GB).
378 // For content less than 2047MB, "CrCommandId_CancelContentsTransfer/CrControlCode_CancelContentsTransfer" will not be executed (it will be ignored) as it will be obtained in one process.
379 // If you want to be able to cancel the transfer process midway, make the "Setting_Key_PartialBuffer" size smaller than the content size.
380 #endif
381
382 while(1) {
383 int index = 0;
384 SCRSDK::CrFolderHandle folderHandle;
385 SCRSDK::CrContentHandle contentHandle;
386 // select folder
387 {
388 CrInt32u f_nums = 0;
389 err = SCRSDK::GetDateFolderList(m_device_handle, &folderList, &f_nums);
390 if(err) GotoError("", err);
391 if(!folderList || f_nums == 0) GotoError("", 0);
392
393 for (CrInt32u i = 0; i < f_nums; ++i) {
394 CrPrintf(CRSTR(" %d: %s\n"), i+1, folderList[i].folderName);
395 }
396 std::cout << "folder:"; std::getline(std::cin, inputLine);
397 try { index = stoi(inputLine); } catch(const std::exception&) { GotoError("", 0); }
398 if (index < 1 || index > (int)f_nums) GotoError("", 0);
399
400 folderHandle = folderList[index-1].handle;
401 SCRSDK::ReleaseDateFolderList(m_device_handle, folderList);
402 folderList = nullptr;
403 }
404 // select content
405 {
406 SCRSDK::CrMtpContentsInfo contentsDetailInfo;
407 CrInt32u c_nums = 0;
408 err = SCRSDK::GetContentsHandleList(m_device_handle, folderHandle, &contentsHandleList, &c_nums);
409 if(err) GotoError("", err);
410 if(!contentsHandleList || c_nums == 0) GotoError("", 0);
411
412 for (CrInt32u i = 0; i < c_nums; i++) {
413 err = SCRSDK::GetContentsDetailInfo(m_device_handle, contentsHandleList[i], &contentsDetailInfo);
414 if(err) GotoError("", err);
415 CrPrintf(CRSTR(" %d: %s\n"), i+1, contentsDetailInfo.fileName);
416 }
417 std::cout << "content:"; std::getline(std::cin, inputLine);
418 try { index = stoi(inputLine); } catch(const std::exception&) { GotoError("", 0); }
419 if (index < 1 || index > (int)c_nums) GotoError("", 0);
420
421 err = SCRSDK::GetContentsDetailInfo(m_device_handle, contentsHandleList[index-1], &contentsDetailInfo);
422 if(err) GotoError("", err);
423 contentHandle = contentsDetailInfo.handle;
424 SCRSDK::ReleaseContentsHandleList(m_device_handle, contentsHandleList);
425 contentsHandleList = nullptr;
426 }
427 // select type & pull content
428 {
429 std::cout << " 1:Original\n"" 2:2M\n"" 3:Thmbnail\n""type:"; std::getline(std::cin, inputLine);
430 try { index = stoi(inputLine); } catch(const std::exception&) { GotoError("", 0); }
431 if (index < 1 || index > 3) GotoError("", 0);
432
433 if(index == 3) {
434 err = _getThumbnail(m_device_handle, contentHandle, path);
435 if(err) goto Error;
436 } else {
437 std::promise<void> eventPromise;
438 std::future<void> eventFuture = eventPromise.get_future();
439 setEventPromise(&eventPromise);
440 if(index == 1) {
441 err = SCRSDK::PullContentsFile(m_device_handle, contentHandle, SCRSDK::CrPropertyStillImageTransSize_Original);
442 } else {
443 // only for .JPG, .ARW, .HIF
444 err = SCRSDK::PullContentsFile(m_device_handle, contentHandle, SCRSDK::CrPropertyStillImageTransSize_SmallSize);
445 }
446 if(err) GotoError("", err);
447 try{
448 eventFuture.get();
449 } catch(const std::exception&) GotoError("", 0);
450
451 std::this_thread::sleep_for(std::chrono::milliseconds(100)); // workaround for GetDateFolderList error
452 }
453 }
454 }
455
456 result = 0;
457Error:
458 if(enumCameraObjectInfo) enumCameraObjectInfo->Release();
459
460 if(m_connected) {
461 std::promise<void> eventPromise;
462 std::future<void> eventFuture = eventPromise.get_future();
463 setEventPromise(&eventPromise);
464 SCRSDK::Disconnect(m_device_handle);
465 eventFuture.wait_for(std::chrono::milliseconds(3000));
466 }
467 if(m_device_handle) {
468 if(folderList) SCRSDK::ReleaseDateFolderList(m_device_handle, folderList);
469 if(contentsHandleList) SCRSDK::ReleaseContentsHandleList(m_device_handle, contentsHandleList);
470 SCRSDK::ReleaseDevice(m_device_handle);
471 }
472 SCRSDK::Release();
473
474 return result;
475}