wasapi: Cover more HRESULT error messages
authorNirbheek Chauhan <nirbheek@centricular.com>
Tue, 6 Feb 2018 18:26:41 +0000 (23:56 +0530)
committerNirbheek Chauhan <nirbheek@centricular.com>
Thu, 8 Feb 2018 08:59:58 +0000 (14:29 +0530)
This requires using allocated strings, but it's the best option. For
instance, a call could fail because CoInitialize() wasn't called, or
because some other thing in the stack failed.

https://bugzilla.gnome.org/show_bug.cgi?id=793289

sys/wasapi/gstwasapisink.c
sys/wasapi/gstwasapisrc.c
sys/wasapi/gstwasapiutil.c
sys/wasapi/gstwasapiutil.h

index 8a9d3f8..9fe393a 100644 (file)
@@ -410,9 +410,10 @@ gst_wasapi_sink_prepare (GstAudioSink * asink, GstAudioRingBufferSpec * spec)
         self->mix_format, NULL);
   }
   if (hr != S_OK) {
+    gchar *msg = gst_wasapi_util_hresult_to_string (hr);
     GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ, (NULL),
-        ("IAudioClient::Initialize () failed: %s",
-            gst_wasapi_util_hresult_to_string (hr)));
+        ("IAudioClient::Initialize () failed: %s", msg));
+    g_free (msg);
     goto beach;
   }
 
@@ -538,8 +539,10 @@ gst_wasapi_sink_write (GstAudioSink * asink, gpointer data, guint length)
       /* Frames the card hasn't rendered yet */
       hr = IAudioClient_GetCurrentPadding (self->client, &n_frames_padding);
       if (hr != S_OK) {
+        gchar *msg = gst_wasapi_util_hresult_to_string (hr);
         GST_ERROR_OBJECT (self, "IAudioClient::GetCurrentPadding failed: %s",
-            gst_wasapi_util_hresult_to_string (hr));
+            msg);
+        g_free (msg);
         length = 0;
         goto beach;
       }
@@ -562,9 +565,10 @@ gst_wasapi_sink_write (GstAudioSink * asink, gpointer data, guint length)
     hr = IAudioRenderClient_GetBuffer (self->render_client, n_frames,
         (BYTE **) & dst);
     if (hr != S_OK) {
+      gchar *msg = gst_wasapi_util_hresult_to_string (hr);
       GST_ELEMENT_ERROR (self, RESOURCE, WRITE, (NULL),
-          ("IAudioRenderClient::GetBuffer failed: %s",
-              gst_wasapi_util_hresult_to_string (hr)));
+          ("IAudioRenderClient::GetBuffer failed: %s", msg));
+      g_free (msg);
       length = 0;
       goto beach;
     }
@@ -574,8 +578,10 @@ gst_wasapi_sink_write (GstAudioSink * asink, gpointer data, guint length)
     hr = IAudioRenderClient_ReleaseBuffer (self->render_client, n_frames,
         self->mute ? AUDCLNT_BUFFERFLAGS_SILENT : 0);
     if (hr != S_OK) {
+      gchar *msg = gst_wasapi_util_hresult_to_string (hr);
       GST_ERROR_OBJECT (self, "IAudioRenderClient::ReleaseBuffer failed: %s",
-          gst_wasapi_util_hresult_to_string (hr));
+          msg);
+      g_free (msg);
       length = 0;
       goto beach;
     }
@@ -597,9 +603,10 @@ gst_wasapi_sink_delay (GstAudioSink * asink)
 
   hr = IAudioClient_GetCurrentPadding (self->client, &delay);
   if (hr != S_OK) {
+    gchar *msg = gst_wasapi_util_hresult_to_string (hr);
     GST_ELEMENT_ERROR (self, RESOURCE, READ, (NULL),
-        ("IAudioClient::GetCurrentPadding failed %s",
-            gst_wasapi_util_hresult_to_string (hr)));
+        ("IAudioClient::GetCurrentPadding failed %s", msg));
+    g_free (msg);
   }
 
   return delay;
@@ -614,15 +621,17 @@ gst_wasapi_sink_reset (GstAudioSink * asink)
   if (self->client) {
     hr = IAudioClient_Stop (self->client);
     if (hr != S_OK) {
-      GST_ERROR_OBJECT (self, "IAudioClient::Stop () failed: %s",
-          gst_wasapi_util_hresult_to_string (hr));
+      gchar *msg = gst_wasapi_util_hresult_to_string (hr);
+      GST_ERROR_OBJECT (self, "IAudioClient::Stop () failed: %s", msg);
+      g_free (msg);
       return;
     }
 
     hr = IAudioClient_Reset (self->client);
     if (hr != S_OK) {
-      GST_ERROR_OBJECT (self, "IAudioClient::Reset () failed: %s",
-          gst_wasapi_util_hresult_to_string (hr));
+      gchar *msg = gst_wasapi_util_hresult_to_string (hr);
+      GST_ERROR_OBJECT (self, "IAudioClient::Reset () failed: %s", msg);
+      g_free (msg);
       return;
     }
   }
index 49f1d31..dcb196c 100644 (file)
@@ -405,9 +405,10 @@ gst_wasapi_src_prepare (GstAudioSrc * asrc, GstAudioRingBufferSpec * spec)
         self->mix_format, NULL);
   }
   if (hr != S_OK) {
+    gchar *msg = gst_wasapi_util_hresult_to_string (hr);
     GST_ELEMENT_ERROR (self, RESOURCE, OPEN_READ, (NULL),
-        ("IAudioClient::Initialize () failed: %s",
-            gst_wasapi_util_hresult_to_string (hr)));
+        ("IAudioClient::Initialize () failed: %s", msg));
+    g_free (msg);
     goto beach;
   }
 
@@ -553,12 +554,14 @@ gst_wasapi_src_read (GstAudioSrc * asrc, gpointer data, guint length,
     hr = IAudioCaptureClient_GetBuffer (self->capture_client,
         (BYTE **) & from, &have_frames, &flags, NULL, NULL);
     if (hr != S_OK) {
+      gchar *msg = gst_wasapi_util_hresult_to_string (hr);
       if (hr == AUDCLNT_S_BUFFER_EMPTY)
         GST_WARNING_OBJECT (self, "IAudioCaptureClient::GetBuffer failed: %s"
-            ", retrying", gst_wasapi_util_hresult_to_string (hr));
+            ", retrying", msg);
       else
         GST_ERROR_OBJECT (self, "IAudioCaptureClient::GetBuffer failed: %s",
-            gst_wasapi_util_hresult_to_string (hr));
+            msg);
+      g_free (msg);
       length = 0;
       goto beach;
     }
@@ -598,9 +601,10 @@ gst_wasapi_src_read (GstAudioSrc * asrc, gpointer data, guint length,
     /* Always release all captured buffers if we've captured any at all */
     hr = IAudioCaptureClient_ReleaseBuffer (self->capture_client, have_frames);
     if (hr != S_OK) {
+      gchar *msg = gst_wasapi_util_hresult_to_string (hr);
       GST_ERROR_OBJECT (self,
-          "IAudioCaptureClient::ReleaseBuffer () failed: %s",
-          gst_wasapi_util_hresult_to_string (hr));
+          "IAudioCaptureClient::ReleaseBuffer () failed: %s", msg);
+      g_free (msg);
       goto beach;
     }
   }
@@ -620,9 +624,10 @@ gst_wasapi_src_delay (GstAudioSrc * asrc)
 
   hr = IAudioClient_GetCurrentPadding (self->client, &delay);
   if (hr != S_OK) {
+    gchar *msg = gst_wasapi_util_hresult_to_string (hr);
     GST_ELEMENT_ERROR (self, RESOURCE, READ, (NULL),
-        ("IAudioClient::GetCurrentPadding failed %s",
-            gst_wasapi_util_hresult_to_string (hr)));
+        ("IAudioClient::GetCurrentPadding failed %s", msg));
+    g_free (msg);
   }
 
   return delay;
@@ -637,15 +642,17 @@ gst_wasapi_src_reset (GstAudioSrc * asrc)
   if (self->client) {
     hr = IAudioClient_Stop (self->client);
     if (hr != S_OK) {
-      GST_ERROR_OBJECT (self, "IAudioClient::Stop () failed: %s",
-          gst_wasapi_util_hresult_to_string (hr));
+      gchar *msg = gst_wasapi_util_hresult_to_string (hr);
+      GST_ERROR_OBJECT (self, "IAudioClient::Stop () failed: %s", msg);
+      g_free (msg);
       return;
     }
 
     hr = IAudioClient_Reset (self->client);
     if (hr != S_OK) {
-      GST_ERROR_OBJECT (self, "IAudioClient::Reset () failed: %s",
-          gst_wasapi_util_hresult_to_string (hr));
+      gchar *msg = gst_wasapi_util_hresult_to_string (hr);
+      GST_ERROR_OBJECT (self, "IAudioClient::Reset () failed: %s", msg);
+      g_free (msg);
       return;
     }
   }
index 9fcbd33..be25de5 100644 (file)
@@ -160,8 +160,8 @@ gst_wasapi_erole_to_device_role (gint erole)
   }
 }
 
-const gchar *
-gst_wasapi_util_hresult_to_string (HRESULT hr)
+static const gchar *
+hresult_to_string_fallback (HRESULT hr)
 {
   const gchar *s = "unknown error";
 
@@ -247,6 +247,9 @@ gst_wasapi_util_hresult_to_string (HRESULT hr)
     case AUDCLNT_S_POSITION_STALLED:
       s = "AUDCLNT_S_POSITION_STALLED";
       break;
+    case E_POINTER:
+      s = "E_POINTER";
+      break;
     case E_INVALIDARG:
       s = "E_INVALIDARG";
       break;
@@ -255,6 +258,33 @@ gst_wasapi_util_hresult_to_string (HRESULT hr)
   return s;
 }
 
+gchar *
+gst_wasapi_util_hresult_to_string (HRESULT hr)
+{
+  DWORD flags;
+  gchar *ret_text;
+  LPTSTR error_text = NULL;
+
+  flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER
+      | FORMAT_MESSAGE_IGNORE_INSERTS;
+  FormatMessage (flags, NULL, hr, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+      (LPTSTR) & error_text, 0, NULL);
+
+  /* If we couldn't get the error msg, try the fallback switch statement */
+  if (error_text == NULL)
+    return g_strdup (hresult_to_string_fallback (hr));
+
+#ifdef UNICODE
+  /* If UNICODE is defined, LPTSTR is LPWSTR which is UTF-16 */
+  ret_text = g_utf16_to_utf8 (error_text, 0, NULL, NULL, NULL);
+#else
+  ret_text = g_strdup (error_text);
+#endif
+
+  LocalFree (error_text);
+  return ret_text;
+}
+
 static IMMDeviceEnumerator *
 gst_wasapi_util_get_device_enumerator (GstElement * element)
 {
@@ -264,8 +294,10 @@ gst_wasapi_util_get_device_enumerator (GstElement * element)
   hr = CoCreateInstance (&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL,
       &IID_IMMDeviceEnumerator, (void **) &enumerator);
   if (hr != S_OK) {
+    gchar *msg = gst_wasapi_util_hresult_to_string (hr);
     GST_ERROR_OBJECT (element, "CoCreateInstance (MMDeviceEnumerator) failed"
-        ": %s", gst_wasapi_util_hresult_to_string (hr));
+        ": %s", msg);
+    g_free (msg);
     return NULL;
   }
 
@@ -294,15 +326,18 @@ gst_wasapi_util_get_devices (GstElement * element, gboolean active,
   hr = IMMDeviceEnumerator_EnumAudioEndpoints (enumerator, eAll, dwStateMask,
       &device_collection);
   if (hr != S_OK) {
+    gchar *msg = gst_wasapi_util_hresult_to_string (hr);
     GST_ERROR_OBJECT (element, "IMMDeviceEnumerator::EnumAudioEndpoints "
-        "failed: %s", gst_wasapi_util_hresult_to_string (hr));
+        "failed: %s", msg);
+    g_free (msg);
     goto err;
   }
 
   hr = IMMDeviceCollection_GetCount (device_collection, &count);
   if (hr != S_OK) {
-    GST_ERROR_OBJECT (element, "Failed to count devices: %s",
-        gst_wasapi_util_hresult_to_string (hr));
+    gchar *msg = gst_wasapi_util_hresult_to_string (hr);
+    GST_ERROR_OBJECT (element, "Failed to count devices: %s", msg);
+    g_free (msg);
     goto err;
   }
 
@@ -368,15 +403,18 @@ gst_wasapi_util_get_devices (GstElement * element, gboolean active,
     hr = IMMDevice_Activate (item, &IID_IAudioClient, CLSCTX_ALL, NULL,
         (void **) &client);
     if (hr != S_OK) {
+      gchar *msg = gst_wasapi_util_hresult_to_string (hr);
       GST_ERROR_OBJECT (element, "IMMDevice::Activate (IID_IAudioClient) failed"
-          "on %s: %s", strid, gst_wasapi_util_hresult_to_string (hr));
+          "on %s: %s", strid, msg);
+      g_free (msg);
       goto next;
     }
 
     hr = IAudioClient_GetMixFormat (client, &format);
     if (hr != S_OK || format == NULL) {
-      GST_ERROR_OBJECT ("GetMixFormat failed on %s: %s", strid,
-          gst_wasapi_util_hresult_to_string (hr));
+      gchar *msg = gst_wasapi_util_hresult_to_string (hr);
+      GST_ERROR_OBJECT ("GetMixFormat failed on %s: %s", strid, msg);
+      g_free (msg);
       goto next;
     }
 
@@ -437,8 +475,9 @@ gst_wasapi_util_get_device_format (GstElement * element,
 
   hr = IAudioClient_GetMixFormat (client, &format);
   if (hr != S_OK || format == NULL) {
-    GST_ERROR_OBJECT (element, "GetMixFormat failed: %s",
-        gst_wasapi_util_hresult_to_string (hr));
+    gchar *msg = gst_wasapi_util_hresult_to_string (hr);
+    GST_ERROR_OBJECT (element, "GetMixFormat failed: %s", msg);
+    g_free (msg);
     return FALSE;
   }
 
@@ -462,16 +501,18 @@ gst_wasapi_util_get_device_format (GstElement * element,
 
     hr = IMMDevice_OpenPropertyStore (device, STGM_READ, &prop_store);
     if (hr != S_OK) {
-      GST_ERROR_OBJECT (element, "OpenPropertyStore failed: %s",
-          gst_wasapi_util_hresult_to_string (hr));
+      gchar *msg = gst_wasapi_util_hresult_to_string (hr);
+      GST_ERROR_OBJECT (element, "OpenPropertyStore failed: %s", msg);
+      g_free (msg);
       return FALSE;
     }
 
     hr = IPropertyStore_GetValue (prop_store, &PKEY_AudioEngine_DeviceFormat,
         &var);
     if (hr != S_OK) {
-      GST_ERROR_OBJECT (element, "GetValue failed: %s",
-          gst_wasapi_util_hresult_to_string (hr));
+      gchar *msg = gst_wasapi_util_hresult_to_string (hr);
+      GST_ERROR_OBJECT (element, "GetValue failed: %s", msg);
+      g_free (msg);
       IUnknown_Release (prop_store);
       return FALSE;
     }
@@ -516,16 +557,19 @@ gst_wasapi_util_get_device_client (GstElement * element,
     hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint (enumerator,
         capture ? eCapture : eRender, role, &device);
     if (hr != S_OK) {
+      gchar *msg = gst_wasapi_util_hresult_to_string (hr);
       GST_ERROR_OBJECT (element,
-          "IMMDeviceEnumerator::GetDefaultAudioEndpoint failed: %s",
-          gst_wasapi_util_hresult_to_string (hr));
+          "IMMDeviceEnumerator::GetDefaultAudioEndpoint failed: %s", msg);
+      g_free (msg);
       goto beach;
     }
   } else {
     hr = IMMDeviceEnumerator_GetDevice (enumerator, device_strid, &device);
     if (hr != S_OK) {
+      gchar *msg = gst_wasapi_util_hresult_to_string (hr);
       GST_ERROR_OBJECT (element, "IMMDeviceEnumerator::GetDevice (%S) failed"
-          ": %s", device_strid, gst_wasapi_util_hresult_to_string (hr));
+          ": %s", device_strid, msg);
+      g_free (msg);
       goto beach;
     }
   }
@@ -533,8 +577,10 @@ gst_wasapi_util_get_device_client (GstElement * element,
   hr = IMMDevice_Activate (device, &IID_IAudioClient, CLSCTX_ALL, NULL,
       (void **) &client);
   if (hr != S_OK) {
+    gchar *msg = gst_wasapi_util_hresult_to_string (hr);
     GST_ERROR_OBJECT (element, "IMMDevice::Activate (IID_IAudioClient) failed"
-        ": %s", gst_wasapi_util_hresult_to_string (hr));
+        ": %s", msg);
+    g_free (msg);
     goto beach;
   }
 
@@ -569,9 +615,10 @@ gst_wasapi_util_get_render_client (GstElement * element, IAudioClient * client,
   hr = IAudioClient_GetService (client, &IID_IAudioRenderClient,
       (void **) &render_client);
   if (hr != S_OK) {
+    gchar *msg = gst_wasapi_util_hresult_to_string (hr);
     GST_ERROR_OBJECT (element,
-        "IAudioClient::GetService (IID_IAudioRenderClient) failed: %s",
-        gst_wasapi_util_hresult_to_string (hr));
+        "IAudioClient::GetService (IID_IAudioRenderClient) failed: %s", msg);
+    g_free (msg);
     goto beach;
   }
 
@@ -593,9 +640,10 @@ gst_wasapi_util_get_capture_client (GstElement * element, IAudioClient * client,
   hr = IAudioClient_GetService (client, &IID_IAudioCaptureClient,
       (void **) &capture_client);
   if (hr != S_OK) {
+    gchar *msg = gst_wasapi_util_hresult_to_string (hr);
     GST_ERROR_OBJECT (element,
-        "IAudioClient::GetService (IID_IAudioCaptureClient) failed: %s",
-        gst_wasapi_util_hresult_to_string (hr));
+        "IAudioClient::GetService (IID_IAudioCaptureClient) failed: %s", msg);
+    g_free (msg);
     goto beach;
   }
 
@@ -616,9 +664,10 @@ gst_wasapi_util_get_clock (GstElement * element, IAudioClient * client,
 
   hr = IAudioClient_GetService (client, &IID_IAudioClock, (void **) &clock);
   if (hr != S_OK) {
+    gchar *msg = gst_wasapi_util_hresult_to_string (hr);
     GST_ERROR_OBJECT (element,
-        "IAudioClient::GetService (IID_IAudioClock) failed: %s",
-        gst_wasapi_util_hresult_to_string (hr));
+        "IAudioClient::GetService (IID_IAudioClock) failed: %s", msg);
+    g_free (msg);
     goto beach;
   }
 
index b8337de..1584a64 100644 (file)
@@ -51,7 +51,7 @@ gint gst_wasapi_device_role_to_erole (gint role);
 
 gint gst_wasapi_erole_to_device_role (gint erole);
 
-const gchar *gst_wasapi_util_hresult_to_string (HRESULT hr);
+gchar *gst_wasapi_util_hresult_to_string (HRESULT hr);
 
 gboolean gst_wasapi_util_get_devices (GstElement * element, gboolean active,
     GList ** devices);