diff options
author | Ole André Vadla Ravnås <oravnas@cisco.com> | 2009-10-12 17:26:15 +0200 |
---|---|---|
committer | Ole André Vadla Ravnås <oravnas@cisco.com> | 2010-10-28 17:08:41 +0200 |
commit | d282a1d38066c1615ba6240bfd1e16b00d6b3489 (patch) | |
tree | d38048291929c4ad03ccae93962568a1ead0aec8 /sys | |
parent | cddfa50d92d45a9648fcedbc9688a1dc23d759c1 (diff) |
winks: improve error-handling
Most important part here is special-casing "device busy" so the application
is able to provide better feedback when another application is using the
device.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/winks/gstksclock.c | 6 | ||||
-rw-r--r-- | sys/winks/gstksvideodevice.c | 20 | ||||
-rw-r--r-- | sys/winks/gstksvideodevice.h | 2 | ||||
-rw-r--r-- | sys/winks/gstksvideosrc.c | 32 | ||||
-rw-r--r-- | sys/winks/kshelpers.c | 78 | ||||
-rw-r--r-- | sys/winks/kshelpers.h | 12 | ||||
-rw-r--r-- | sys/winks/ksvideohelpers.c | 10 |
7 files changed, 97 insertions, 63 deletions
diff --git a/sys/winks/gstksclock.c b/sys/winks/gstksclock.c index db1a8a16b..33c3e4d00 100644 --- a/sys/winks/gstksclock.c +++ b/sys/winks/gstksclock.c @@ -151,7 +151,7 @@ gst_ks_clock_open (GstKsClock * self) state = KSSTATE_STOP; if (!ks_object_set_property (priv->clock_handle, KSPROPSETID_Clock, - KSPROPERTY_CLOCK_STATE, &state, sizeof (state))) + KSPROPERTY_CLOCK_STATE, &state, sizeof (state), NULL)) goto error; ks_device_list_free (devices); @@ -193,7 +193,7 @@ gst_ks_clock_set_state_unlocked (GstKsClock * self, KSSTATE state) ks_state_to_string (priv->state), ks_state_to_string (next_state)); if (ks_object_set_property (priv->clock_handle, KSPROPSETID_Clock, - KSPROPERTY_CLOCK_STATE, &next_state, sizeof (next_state))) { + KSPROPERTY_CLOCK_STATE, &next_state, sizeof (next_state), NULL)) { priv->state = next_state; GST_DEBUG ("Changed clock state to %s", ks_state_to_string (priv->state)); @@ -298,7 +298,7 @@ gst_ks_clock_worker_thread_func (gpointer data) now /= 100; if (ks_object_set_property (priv->clock_handle, KSPROPSETID_Clock, - KSPROPERTY_CLOCK_TIME, &now, sizeof (now))) { + KSPROPERTY_CLOCK_TIME, &now, sizeof (now), NULL)) { GST_DEBUG ("clock synchronized"); gst_object_unref (priv->master_clock); priv->master_clock = NULL; diff --git a/sys/winks/gstksvideodevice.c b/sys/winks/gstksvideodevice.c index 0b95e3d2d..ec094185d 100644 --- a/sys/winks/gstksvideodevice.c +++ b/sys/winks/gstksvideodevice.c @@ -556,7 +556,7 @@ gst_ks_video_device_create_pin (GstKsVideoDevice * self, alignment = 0; if (ks_object_get_property (pin_handle, KSPROPSETID_Connection, - KSPROPERTY_CONNECTION_ALLOCATORFRAMING_EX, &framing_ex, NULL)) { + KSPROPERTY_CONNECTION_ALLOCATORFRAMING_EX, &framing_ex, NULL, NULL)) { if (framing_ex->CountItems >= 1) { *num_outstanding = framing_ex->FramingItem[0].Frames; alignment = framing_ex->FramingItem[0].FileAlignment; @@ -568,7 +568,8 @@ gst_ks_video_device_create_pin (GstKsVideoDevice * self, "ALLOCATORFRAMING"); if (ks_object_get_property (pin_handle, KSPROPSETID_Connection, - KSPROPERTY_CONNECTION_ALLOCATORFRAMING, &framing, &framing_size)) { + KSPROPERTY_CONNECTION_ALLOCATORFRAMING, &framing, &framing_size, + NULL)) { *num_outstanding = framing->Frames; alignment = framing->FileAlignment; } else { @@ -597,7 +598,7 @@ gst_ks_video_device_create_pin (GstKsVideoDevice * self, mem_transport = 0; /* REVISIT: use the constant here */ if (!ks_object_set_property (pin_handle, KSPROPSETID_MemoryTransport, KSPROPERTY_MEMORY_TRANSPORT, &mem_transport, - sizeof (mem_transport))) { + sizeof (mem_transport), NULL)) { GST_DEBUG ("failed to set memory transport, sticking with the default"); } } @@ -611,7 +612,7 @@ gst_ks_video_device_create_pin (GstKsVideoDevice * self, if (ks_object_get_property (pin_handle, KSPROPSETID_Stream, KSPROPERTY_STREAM_MASTERCLOCK, (gpointer *) & cur_clock_handle, - &cur_clock_handle_size)) { + &cur_clock_handle_size, NULL)) { GST_DEBUG ("current master clock handle: 0x%08x", *cur_clock_handle); CloseHandle (*cur_clock_handle); g_free (cur_clock_handle); @@ -620,7 +621,7 @@ gst_ks_video_device_create_pin (GstKsVideoDevice * self, if (ks_object_set_property (pin_handle, KSPROPSETID_Stream, KSPROPERTY_STREAM_MASTERCLOCK, &new_clock_handle, - sizeof (new_clock_handle))) { + sizeof (new_clock_handle), NULL)) { gst_ks_clock_prepare (priv->clock); } else { GST_WARNING ("failed to set pin's master clock"); @@ -660,7 +661,7 @@ gst_ks_video_device_close_current_pin (GstKsVideoDevice * self) if (!ks_is_valid_handle (priv->pin_handle)) return; - gst_ks_video_device_set_state (self, KSSTATE_STOP); + gst_ks_video_device_set_state (self, KSSTATE_STOP, NULL); CloseHandle (priv->pin_handle); priv->pin_handle = INVALID_HANDLE_VALUE; @@ -801,7 +802,8 @@ same_caps: } gboolean -gst_ks_video_device_set_state (GstKsVideoDevice * self, KSSTATE state) +gst_ks_video_device_set_state (GstKsVideoDevice * self, KSSTATE state, + gulong * error_code) { GstKsVideoDevicePrivate *priv = GST_KS_VIDEO_DEVICE_GET_PRIVATE (self); KSSTATE initial_state; @@ -828,7 +830,8 @@ gst_ks_video_device_set_state (GstKsVideoDevice * self, KSSTATE state) GST_DEBUG ("Changing pin state from %s to %s", ks_state_to_string (priv->state), ks_state_to_string (next_state)); - if (ks_object_set_connection_state (priv->pin_handle, next_state)) { + if (ks_object_set_connection_state (priv->pin_handle, next_state, + error_code)) { priv->state = next_state; GST_DEBUG ("Changed pin state to %s", ks_state_to_string (priv->state)); @@ -840,6 +843,7 @@ gst_ks_video_device_set_state (GstKsVideoDevice * self, KSSTATE state) } else { GST_WARNING ("Failed to change pin state to %s", ks_state_to_string (next_state)); + return FALSE; } } diff --git a/sys/winks/gstksvideodevice.h b/sys/winks/gstksvideodevice.h index 1d110ad36..d830492fc 100644 --- a/sys/winks/gstksvideodevice.h +++ b/sys/winks/gstksvideodevice.h @@ -71,7 +71,7 @@ GstCaps * gst_ks_video_device_get_available_caps (GstKsVideoDevice * self); gboolean gst_ks_video_device_has_caps (GstKsVideoDevice * self); gboolean gst_ks_video_device_set_caps (GstKsVideoDevice * self, GstCaps * caps); -gboolean gst_ks_video_device_set_state (GstKsVideoDevice * self, KSSTATE state); +gboolean gst_ks_video_device_set_state (GstKsVideoDevice * self, KSSTATE state, gulong * error_code); GstClockTime gst_ks_video_device_get_duration (GstKsVideoDevice * self); gboolean gst_ks_video_device_get_latency (GstKsVideoDevice * self, GstClockTime * min_latency, GstClockTime * max_latency); diff --git a/sys/winks/gstksvideosrc.c b/sys/winks/gstksvideosrc.c index df920a18f..577bef5e6 100644 --- a/sys/winks/gstksvideosrc.c +++ b/sys/winks/gstksvideosrc.c @@ -114,6 +114,8 @@ struct _GstKsVideoSrcPrivate gboolean worker_pending_run; gboolean worker_run_result; + gulong worker_error_code; + /* Statistics */ GstClockTime last_sampling; guint count; @@ -555,15 +557,15 @@ error_no_devices: error_no_match: { if (priv->device_path != NULL) { - GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS, + GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND, ("Specified video capture device with path '%s' not found", priv->device_path), (NULL)); } else if (priv->device_name != NULL) { - GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS, + GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND, ("Specified video capture device with name '%s' not found", priv->device_name), (NULL)); } else { - GST_ELEMENT_ERROR (self, RESOURCE, SETTINGS, + GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND, ("Specified video capture device with index %d not found", priv->device_index), (NULL)); } @@ -633,8 +635,8 @@ gst_ks_video_src_worker_func (gpointer data) } else if (priv->worker_pending_run) { if (priv->ksclock != NULL) gst_ks_clock_start (priv->ksclock); - priv->worker_run_result = - gst_ks_video_device_set_state (priv->device, KSSTATE_RUN); + priv->worker_run_result = gst_ks_video_device_set_state (priv->device, + KSSTATE_RUN, &priv->worker_error_code); priv->worker_pending_run = FALSE; KS_WORKER_NOTIFY_RESULT (priv); @@ -1014,6 +1016,7 @@ gst_ks_video_src_create (GstPushSrc * pushsrc, GstBuffer ** buf) while (priv->worker_pending_run) KS_WORKER_WAIT_FOR_RESULT (priv); priv->running = priv->worker_run_result; + error_code = priv->worker_error_code; KS_WORKER_UNLOCK (priv); if (!priv->running) @@ -1051,9 +1054,22 @@ error_no_caps: } error_start_capture: { - GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ, - ("could not start capture"), - ("failed to change pin state to KSSTATE_RUN")); + const gchar *debug_str = "failed to change pin state to KSSTATE_RUN"; + + switch (error_code) { + case ERROR_FILE_NOT_FOUND: + GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND, + ("failed to start capture (device unplugged)"), (debug_str)); + break; + case ERROR_NO_SYSTEM_RESOURCES: + GST_ELEMENT_ERROR (self, RESOURCE, BUSY, + ("failed to start capture (device already in use)"), (debug_str)); + break; + default: + GST_ELEMENT_ERROR (self, RESOURCE, FAILED, + ("failed to start capture (0x%08x)", error_code), (debug_str)); + break; + } return GST_FLOW_ERROR; } diff --git a/sys/winks/kshelpers.c b/sys/winks/kshelpers.c index 0f96dc75e..d170180a4 100644 --- a/sys/winks/kshelpers.c +++ b/sys/winks/kshelpers.c @@ -127,7 +127,7 @@ ks_device_list_free (GList * devices) static gboolean ks_sync_device_io_control (HANDLE device, gulong io_control_code, gpointer in_buffer, gulong in_buffer_size, gpointer out_buffer, - gulong out_buffer_size, gulong * bytes_returned) + gulong out_buffer_size, gulong * bytes_returned, gulong * error) { OVERLAPPED overlapped = { 0, }; BOOL success; @@ -136,8 +136,18 @@ ks_sync_device_io_control (HANDLE device, gulong io_control_code, success = DeviceIoControl (device, io_control_code, in_buffer, in_buffer_size, out_buffer, out_buffer_size, bytes_returned, &overlapped); - if (!success && GetLastError () == ERROR_IO_PENDING) - success = GetOverlappedResult (device, &overlapped, bytes_returned, TRUE); + if (!success) { + DWORD err; + + if ((err = GetLastError ()) == ERROR_IO_PENDING) { + success = GetOverlappedResult (device, &overlapped, bytes_returned, TRUE); + if (!success) + err = GetLastError (); + } + + if (error != NULL) + *error = err; + } CloseHandle (overlapped.hEvent); @@ -146,7 +156,8 @@ ks_sync_device_io_control (HANDLE device, gulong io_control_code, gboolean ks_filter_get_pin_property (HANDLE filter_handle, gulong pin_id, - GUID prop_set, gulong prop_id, gpointer value, gulong value_size) + GUID prop_set, gulong prop_id, gpointer value, gulong value_size, + gulong * error) { KSP_PIN prop = { 0, }; DWORD bytes_returned = 0; @@ -157,15 +168,16 @@ ks_filter_get_pin_property (HANDLE filter_handle, gulong pin_id, prop.Property.Flags = KSPROPERTY_TYPE_GET; return ks_sync_device_io_control (filter_handle, IOCTL_KS_PROPERTY, &prop, - sizeof (prop), value, value_size, &bytes_returned); + sizeof (prop), value, value_size, &bytes_returned, error); } gboolean ks_filter_get_pin_property_multi (HANDLE filter_handle, gulong pin_id, - GUID prop_set, gulong prop_id, KSMULTIPLE_ITEM ** items) + GUID prop_set, gulong prop_id, KSMULTIPLE_ITEM ** items, gulong * error) { KSP_PIN prop = { 0, }; DWORD items_size = 0, bytes_written = 0; + gulong err; gboolean ret; *items = NULL; @@ -176,23 +188,23 @@ ks_filter_get_pin_property_multi (HANDLE filter_handle, gulong pin_id, prop.Property.Flags = KSPROPERTY_TYPE_GET; ret = ks_sync_device_io_control (filter_handle, IOCTL_KS_PROPERTY, - &prop.Property, sizeof (prop), NULL, 0, &items_size); - if (!ret) { - DWORD err = GetLastError (); - if (err != ERROR_INSUFFICIENT_BUFFER && err != ERROR_MORE_DATA) - goto error; - } + &prop.Property, sizeof (prop), NULL, 0, &items_size, &err); + if (!ret && err != ERROR_INSUFFICIENT_BUFFER && err != ERROR_MORE_DATA) + goto ioctl_failed; *items = g_malloc0 (items_size); ret = ks_sync_device_io_control (filter_handle, IOCTL_KS_PROPERTY, &prop, - sizeof (prop), *items, items_size, &bytes_written); + sizeof (prop), *items, items_size, &bytes_written, &err); if (!ret) - goto error; + goto ioctl_failed; return ret; -error: +ioctl_failed: + if (error != NULL) + *error = err; + g_free (*items); *items = NULL; @@ -201,10 +213,11 @@ error: gboolean ks_object_query_property (HANDLE handle, GUID prop_set, gulong prop_id, - gulong prop_flags, gpointer * value, gulong * value_size) + gulong prop_flags, gpointer * value, gulong * value_size, gulong * error) { KSPROPERTY prop = { 0, }; DWORD req_value_size = 0, bytes_written = 0; + gulong err; gboolean ret; *value = NULL; @@ -215,12 +228,9 @@ ks_object_query_property (HANDLE handle, GUID prop_set, gulong prop_id, if (value_size == NULL || *value_size == 0) { ret = ks_sync_device_io_control (handle, IOCTL_KS_PROPERTY, - &prop, sizeof (prop), NULL, 0, &req_value_size); - if (!ret) { - DWORD err = GetLastError (); - if (err != ERROR_INSUFFICIENT_BUFFER && err != ERROR_MORE_DATA) - goto error; - } + &prop, sizeof (prop), NULL, 0, &req_value_size, &err); + if (!ret && err != ERROR_INSUFFICIENT_BUFFER && err != ERROR_MORE_DATA) + goto ioctl_failed; } else { req_value_size = *value_size; } @@ -228,16 +238,19 @@ ks_object_query_property (HANDLE handle, GUID prop_set, gulong prop_id, *value = g_malloc0 (req_value_size); ret = ks_sync_device_io_control (handle, IOCTL_KS_PROPERTY, &prop, - sizeof (prop), *value, req_value_size, &bytes_written); + sizeof (prop), *value, req_value_size, &bytes_written, &err); if (!ret) - goto error; + goto ioctl_failed; if (value_size != NULL) *value_size = bytes_written; return ret; -error: +ioctl_failed: + if (error != NULL) + *error = err; + g_free (*value); *value = NULL; @@ -249,15 +262,15 @@ error: gboolean ks_object_get_property (HANDLE handle, GUID prop_set, gulong prop_id, - gpointer * value, gulong * value_size) + gpointer * value, gulong * value_size, gulong * error) { return ks_object_query_property (handle, prop_set, prop_id, - KSPROPERTY_TYPE_GET, value, value_size); + KSPROPERTY_TYPE_GET, value, value_size, error); } gboolean ks_object_set_property (HANDLE handle, GUID prop_set, gulong prop_id, - gpointer value, gulong value_size) + gpointer value, gulong value_size, gulong * error) { KSPROPERTY prop = { 0, }; DWORD bytes_returned; @@ -267,7 +280,7 @@ ks_object_set_property (HANDLE handle, GUID prop_set, gulong prop_id, prop.Flags = KSPROPERTY_TYPE_SET; return ks_sync_device_io_control (handle, IOCTL_KS_PROPERTY, &prop, - sizeof (prop), value, value_size, &bytes_returned); + sizeof (prop), value, value_size, &bytes_returned, error); } gboolean @@ -275,12 +288,13 @@ ks_object_get_supported_property_sets (HANDLE handle, GUID ** propsets, gulong * len) { gulong size = 0; + gulong error; *propsets = NULL; *len = 0; if (ks_object_query_property (handle, GUID_NULL, 0, - KSPROPERTY_TYPE_SETSUPPORT, propsets, &size)) { + KSPROPERTY_TYPE_SETSUPPORT, propsets, &size, &error)) { if (size % sizeof (GUID) == 0) { *len = size / sizeof (GUID); return TRUE; @@ -294,10 +308,10 @@ ks_object_get_supported_property_sets (HANDLE handle, GUID ** propsets, } gboolean -ks_object_set_connection_state (HANDLE handle, KSSTATE state) +ks_object_set_connection_state (HANDLE handle, KSSTATE state, gulong * error) { return ks_object_set_property (handle, KSPROPSETID_Connection, - KSPROPERTY_CONNECTION_STATE, &state, sizeof (state)); + KSPROPERTY_CONNECTION_STATE, &state, sizeof (state), error); } gchar * diff --git a/sys/winks/kshelpers.h b/sys/winks/kshelpers.h index a233722e8..b84fcde36 100644 --- a/sys/winks/kshelpers.h +++ b/sys/winks/kshelpers.h @@ -41,16 +41,16 @@ GList * ks_enumerate_devices (const GUID * category); void ks_device_entry_free (KsDeviceEntry * entry); void ks_device_list_free (GList * devices); -gboolean ks_filter_get_pin_property (HANDLE filter_handle, gulong pin_id, GUID prop_set, gulong prop_id, gpointer value, gulong value_size); -gboolean ks_filter_get_pin_property_multi (HANDLE filter_handle, gulong pin_id, GUID prop_set, gulong prop_id, KSMULTIPLE_ITEM ** items); +gboolean ks_filter_get_pin_property (HANDLE filter_handle, gulong pin_id, GUID prop_set, gulong prop_id, gpointer value, gulong value_size, gulong * error); +gboolean ks_filter_get_pin_property_multi (HANDLE filter_handle, gulong pin_id, GUID prop_set, gulong prop_id, KSMULTIPLE_ITEM ** items, gulong * error); -gboolean ks_object_query_property (HANDLE handle, GUID prop_set, gulong prop_id, gulong prop_flags, gpointer * value, gulong * value_size); -gboolean ks_object_get_property (HANDLE handle, GUID prop_set, gulong prop_id, gpointer * value, gulong * value_size); -gboolean ks_object_set_property (HANDLE handle, GUID prop_set, gulong prop_id, gpointer value, gulong value_size); +gboolean ks_object_query_property (HANDLE handle, GUID prop_set, gulong prop_id, gulong prop_flags, gpointer * value, gulong * value_size, gulong * error); +gboolean ks_object_get_property (HANDLE handle, GUID prop_set, gulong prop_id, gpointer * value, gulong * value_size, gulong * error); +gboolean ks_object_set_property (HANDLE handle, GUID prop_set, gulong prop_id, gpointer value, gulong value_size, gulong * error); gboolean ks_object_get_supported_property_sets (HANDLE handle, GUID ** propsets, gulong * len); -gboolean ks_object_set_connection_state (HANDLE handle, KSSTATE state); +gboolean ks_object_set_connection_state (HANDLE handle, KSSTATE state, gulong * error); gchar * ks_guid_to_string (const GUID * guid); const gchar * ks_state_to_string (KSSTATE state); diff --git a/sys/winks/ksvideohelpers.c b/sys/winks/ksvideohelpers.c index e93f71b1d..69b4311b2 100644 --- a/sys/winks/ksvideohelpers.c +++ b/sys/winks/ksvideohelpers.c @@ -427,7 +427,7 @@ ks_video_probe_filter_for_caps (HANDLE filter_handle) guint pin_id; if (!ks_filter_get_pin_property (filter_handle, 0, KSPROPSETID_Pin, - KSPROPERTY_PIN_CTYPES, &pin_count, sizeof (pin_count))) + KSPROPERTY_PIN_CTYPES, &pin_count, sizeof (pin_count), NULL)) goto beach; GST_DEBUG ("pin_count = %d", pin_count); @@ -438,15 +438,15 @@ ks_video_probe_filter_for_caps (HANDLE filter_handle) GUID pin_cat; if (!ks_filter_get_pin_property (filter_handle, pin_id, KSPROPSETID_Pin, - KSPROPERTY_PIN_COMMUNICATION, &pin_comm, sizeof (pin_comm))) + KSPROPERTY_PIN_COMMUNICATION, &pin_comm, sizeof (pin_comm), NULL)) continue; if (!ks_filter_get_pin_property (filter_handle, pin_id, KSPROPSETID_Pin, - KSPROPERTY_PIN_DATAFLOW, &pin_flow, sizeof (pin_flow))) + KSPROPERTY_PIN_DATAFLOW, &pin_flow, sizeof (pin_flow), NULL)) continue; if (!ks_filter_get_pin_property (filter_handle, pin_id, KSPROPSETID_Pin, - KSPROPERTY_PIN_CATEGORY, &pin_cat, sizeof (pin_cat))) + KSPROPERTY_PIN_CATEGORY, &pin_cat, sizeof (pin_cat), NULL)) continue; GST_DEBUG ("pin[%u]: pin_comm=%d, pin_flow=%d", pin_id, pin_comm, pin_flow); @@ -456,7 +456,7 @@ ks_video_probe_filter_for_caps (HANDLE filter_handle) KSMULTIPLE_ITEM *items; if (ks_filter_get_pin_property_multi (filter_handle, pin_id, - KSPROPSETID_Pin, KSPROPERTY_PIN_DATARANGES, &items)) { + KSPROPSETID_Pin, KSPROPERTY_PIN_DATARANGES, &items, NULL)) { KSDATARANGE *range = (KSDATARANGE *) (items + 1); guint i; |