30#include <unordered_map>
34thread_local std::string g_last_error_details;
37std::mutex g_error_stats_mutex;
38std::unordered_map<duvc_result_t, size_t> g_error_counts;
39std::atomic<size_t> g_total_operations{0};
40std::atomic<size_t> g_total_errors{0};
44 std::string operation;
45 std::string device_info;
46 std::chrono::steady_clock::time_point timestamp;
47 std::thread::id thread_id;
50thread_local ErrorContext g_last_error_context;
56 g_total_operations.fetch_add(1);
59 g_total_errors.fetch_add(1);
61 std::lock_guard<std::mutex> lock(g_error_stats_mutex);
62 g_error_counts[result]++;
69void set_error_context(
const char *operation,
70 const char *device_info =
nullptr) {
71 g_last_error_context.operation = operation ? operation :
"Unknown";
72 g_last_error_context.device_info = device_info ? device_info :
"";
73 g_last_error_context.timestamp = std::chrono::steady_clock::now();
74 g_last_error_context.thread_id = std::this_thread::get_id();
113 const char *device_info) {
119 set_error_context(operation, device_info);
121 }
catch (
const std::exception &) {
127 size_t *required_size) {
129 std::ostringstream stats;
131 stats <<
"Error Statistics:\n";
132 stats <<
"================\n";
134 size_t total_ops = g_total_operations.load();
135 size_t total_errs = g_total_errors.load();
137 stats <<
"Total Operations: " << total_ops <<
"\n";
138 stats <<
"Total Errors: " << total_errs <<
"\n";
141 double success_rate =
142 (double)(total_ops - total_errs) / total_ops * 100.0;
143 double error_rate = (double)total_errs / total_ops * 100.0;
145 stats <<
"Success Rate: " << std::fixed << std::setprecision(2)
146 << success_rate <<
"%\n";
147 stats <<
"Error Rate: " << std::fixed << std::setprecision(2)
148 << error_rate <<
"%\n";
153 std::lock_guard<std::mutex> lock(g_error_stats_mutex);
154 if (!g_error_counts.empty()) {
155 stats <<
"\nDetailed Error Breakdown:\n";
156 stats <<
"========================\n";
158 for (
const auto &pair : g_error_counts) {
160 total_errs > 0 ? (double)pair.second / total_errs * 100.0 : 0.0;
162 <<
" (" << std::fixed << std::setprecision(1) << percentage
168 std::string stats_str = stats.str();
171 size_t needed = stats_str.length() + 1;
173 *required_size = needed;
175 if (!buffer || buffer_size < needed) {
179 std::memcpy(buffer, stats_str.c_str(), needed);
182 }
catch (
const std::exception &e) {
183 std::string fallback =
184 std::string(
"Failed to get error statistics: ") + e.what();
185 size_t needed = fallback.length() + 1;
188 *required_size = needed;
190 if (buffer && buffer_size >= needed) {
191 std::memcpy(buffer, fallback.c_str(), needed);
200 g_total_operations.store(0);
201 g_total_errors.store(0);
203 std::lock_guard<std::mutex> lock(g_error_stats_mutex);
204 g_error_counts.clear();
212 char *buffer,
size_t buffer_size,
213 size_t *required_size) {
215 std::ostringstream suggestions;
217 suggestions <<
"Resolution suggestions for: "
220 switch (error_code) {
222 suggestions <<
"1. Check that the camera is physically connected\n";
223 suggestions <<
"2. Verify the camera appears in Device Manager\n";
224 suggestions <<
"3. Try reconnecting the USB cable\n";
225 suggestions <<
"4. Restart the camera or computer\n";
226 suggestions <<
"5. Check if device drivers are properly installed\n";
230 suggestions <<
"1. Close other applications using the camera\n";
231 suggestions <<
"2. Check for background processes using the camera\n";
232 suggestions <<
"3. Wait a moment and try again\n";
234 <<
"4. Restart applications that might be holding the device\n";
238 suggestions <<
"1. Run the application as Administrator (Windows)\n";
239 suggestions <<
"2. Check camera privacy settings\n";
240 suggestions <<
"3. Verify antivirus isn't blocking camera access\n";
241 suggestions <<
"4. Check Windows Camera privacy settings\n";
245 suggestions <<
"1. Check device capabilities before setting properties\n";
247 <<
"2. Verify the property is supported by your camera model\n";
249 <<
"3. Try alternative properties with similar functionality\n";
253 suggestions <<
"1. Check the valid range for this property\n";
254 suggestions <<
"2. Use duvc_get_*_property_range() to get valid ranges\n";
255 suggestions <<
"3. Ensure values are within min/max bounds\n";
256 suggestions <<
"4. Check step size alignment\n";
260 suggestions <<
"1. Check USB connection and cable quality\n";
261 suggestions <<
"2. Try a different USB port\n";
262 suggestions <<
"3. Update camera drivers\n";
263 suggestions <<
"4. Check for USB power management issues\n";
267 suggestions <<
"1. Check system logs for detailed error information\n";
268 suggestions <<
"2. Verify DirectShow components are properly installed\n";
269 suggestions <<
"3. Try reinstalling camera drivers\n";
270 suggestions <<
"4. Check for Windows updates\n";
274 suggestions <<
"1. Check the detailed error information\n";
275 suggestions <<
"2. Consult the documentation for this error code\n";
276 suggestions <<
"3. Enable debug logging for more information\n";
277 suggestions <<
"4. Contact support with diagnostic information\n";
281 suggestions <<
"\nGeneral troubleshooting:\n";
283 <<
"- Enable debug logging: duvc_set_log_level(DUVC_LOG_DEBUG)\n";
284 suggestions <<
"- Get diagnostic info: duvc_get_diagnostic_info()\n";
285 suggestions <<
"- Check error statistics: duvc_get_error_statistics()\n";
287 std::string suggestions_str = suggestions.str();
290 size_t needed = suggestions_str.length() + 1;
292 *required_size = needed;
294 if (!buffer || buffer_size < needed) {
298 std::memcpy(buffer, suggestions_str.c_str(), needed);
301 }
catch (
const std::exception &e) {
302 std::string fallback =
303 std::string(
"Failed to get error suggestions: ") + e.what();
304 size_t needed = fallback.length() + 1;
307 *required_size = needed;
309 if (buffer && buffer_size >= needed) {
310 std::memcpy(buffer, fallback.c_str(), needed);
320 switch (error_code) {
Complete C ABI for duvc-ctl with comprehensive API coverage.
duvc_result_t
Result codes for duvc operations.
@ DUVC_ERROR_TIMEOUT
Operation timed out.
@ DUVC_ERROR_CONNECTION_FAILED
Failed to establish device connection.
@ DUVC_ERROR_INVALID_ARGUMENT
Invalid function argument provided.
@ DUVC_ERROR_INVALID_VALUE
Property value out of valid range.
@ DUVC_ERROR_NOT_IMPLEMENTED
Feature not implemented on this platform.
@ DUVC_ERROR_DEVICE_BUSY
Device is busy or in use by another process.
@ DUVC_ERROR_PERMISSION_DENIED
Insufficient permissions to access device.
@ DUVC_ERROR_DEVICE_NOT_FOUND
Device not found or disconnected.
@ DUVC_ERROR_BUFFER_TOO_SMALL
Provided buffer is too small for data.
@ DUVC_ERROR_SYSTEM_ERROR
System/platform error occurred.
@ DUVC_ERROR_PROPERTY_NOT_SUPPORTED
Property not supported by device.
@ DUVC_SUCCESS
Operation completed successfully.
const char * duvc_error_code_to_string(duvc_result_t code)
Convert error code to string.
HRESULT decoder and diagnostics utilities.
int duvc_should_retry_operation(duvc_result_t error_code)
duvc_result_t duvc_set_error_context(const char *operation, const char *device_info)
duvc_result_t duvc_suggest_error_resolution(duvc_result_t error_code, char *buffer, size_t buffer_size, size_t *required_size)
duvc_result_t duvc_get_error_statistics(char *buffer, size_t buffer_size, size_t *required_size)
int duvc_is_temporary_error(duvc_result_t result)
int duvc_is_user_error(duvc_result_t result)
void duvc_reset_error_statistics(void)
Structured logging interface for duvc-ctl.
Result/Error type system for duvc-ctl.