/* * Copyright (C) 2008 Ole André Vadla Ravnås * Copyright (C) 2018 Centricular Ltd. * Author: Nirbheek Chauhan * Copyright (C) 2020 Seungha Yang * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include "gstwasapi2util.h" #include GST_DEBUG_CATEGORY_EXTERN (gst_wasapi_debug); #define GST_CAT_DEFAULT gst_wasapi_debug /* *INDENT-OFF* */ static struct { guint64 wasapi_pos; GstAudioChannelPosition gst_pos; } wasapi_to_gst_pos[] = { {SPEAKER_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, {SPEAKER_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, {SPEAKER_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, {SPEAKER_LOW_FREQUENCY, GST_AUDIO_CHANNEL_POSITION_LFE1}, {SPEAKER_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT}, {SPEAKER_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, {SPEAKER_FRONT_LEFT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER}, {SPEAKER_FRONT_RIGHT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, {SPEAKER_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, /* Enum values diverge from this point onwards */ {SPEAKER_SIDE_LEFT, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT}, {SPEAKER_SIDE_RIGHT, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}, {SPEAKER_TOP_CENTER, GST_AUDIO_CHANNEL_POSITION_TOP_CENTER}, {SPEAKER_TOP_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT}, {SPEAKER_TOP_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER}, {SPEAKER_TOP_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT}, {SPEAKER_TOP_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT}, {SPEAKER_TOP_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER}, {SPEAKER_TOP_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT} }; /* *INDENT-ON* */ static const gchar * hresult_to_string_fallback (HRESULT hr) { const gchar *s = "unknown error"; switch (hr) { case AUDCLNT_E_NOT_INITIALIZED: s = "AUDCLNT_E_NOT_INITIALIZED"; break; case AUDCLNT_E_ALREADY_INITIALIZED: s = "AUDCLNT_E_ALREADY_INITIALIZED"; break; case AUDCLNT_E_WRONG_ENDPOINT_TYPE: s = "AUDCLNT_E_WRONG_ENDPOINT_TYPE"; break; case AUDCLNT_E_DEVICE_INVALIDATED: s = "AUDCLNT_E_DEVICE_INVALIDATED"; break; case AUDCLNT_E_NOT_STOPPED: s = "AUDCLNT_E_NOT_STOPPED"; break; case AUDCLNT_E_BUFFER_TOO_LARGE: s = "AUDCLNT_E_BUFFER_TOO_LARGE"; break; case AUDCLNT_E_OUT_OF_ORDER: s = "AUDCLNT_E_OUT_OF_ORDER"; break; case AUDCLNT_E_UNSUPPORTED_FORMAT: s = "AUDCLNT_E_UNSUPPORTED_FORMAT"; break; case AUDCLNT_E_INVALID_DEVICE_PERIOD: s = "AUDCLNT_E_INVALID_DEVICE_PERIOD"; break; case AUDCLNT_E_INVALID_SIZE: s = "AUDCLNT_E_INVALID_SIZE"; break; case AUDCLNT_E_DEVICE_IN_USE: s = "AUDCLNT_E_DEVICE_IN_USE"; break; case AUDCLNT_E_BUFFER_OPERATION_PENDING: s = "AUDCLNT_E_BUFFER_OPERATION_PENDING"; break; case AUDCLNT_E_BUFFER_SIZE_ERROR: s = "AUDCLNT_E_BUFFER_SIZE_ERROR"; break; case AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED: s = "AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED"; break; case AUDCLNT_E_THREAD_NOT_REGISTERED: s = "AUDCLNT_E_THREAD_NOT_REGISTERED"; break; case AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED: s = "AUDCLNT_E_EXCLUSIVE_MODE_NOT_ALLOWED"; break; case AUDCLNT_E_ENDPOINT_CREATE_FAILED: s = "AUDCLNT_E_ENDPOINT_CREATE_FAILED"; break; case AUDCLNT_E_SERVICE_NOT_RUNNING: s = "AUDCLNT_E_SERVICE_NOT_RUNNING"; break; case AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED: s = "AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED"; break; case AUDCLNT_E_EXCLUSIVE_MODE_ONLY: s = "AUDCLNT_E_EXCLUSIVE_MODE_ONLY"; break; case AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL: s = "AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL"; break; case AUDCLNT_E_EVENTHANDLE_NOT_SET: s = "AUDCLNT_E_EVENTHANDLE_NOT_SET"; break; case AUDCLNT_E_INCORRECT_BUFFER_SIZE: s = "AUDCLNT_E_INCORRECT_BUFFER_SIZE"; break; case AUDCLNT_E_CPUUSAGE_EXCEEDED: s = "AUDCLNT_E_CPUUSAGE_EXCEEDED"; break; case AUDCLNT_S_BUFFER_EMPTY: s = "AUDCLNT_S_BUFFER_EMPTY"; break; case AUDCLNT_S_THREAD_ALREADY_REGISTERED: s = "AUDCLNT_S_THREAD_ALREADY_REGISTERED"; break; 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; } return s; } static gchar * gst_wasapi2_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; } gboolean _gst_wasapi2_result (HRESULT hr, GstDebugCategory * cat, const gchar * file, const gchar * function, gint line) { #ifndef GST_DISABLE_GST_DEBUG gboolean ret = TRUE; if (FAILED (hr)) { gchar *error_text = NULL; error_text = gst_wasapi2_util_hresult_to_string (hr); gst_debug_log (cat, GST_LEVEL_WARNING, file, function, line, NULL, "WASAPI call failed: 0x%x, %s", (guint) hr, error_text); g_free (error_text); ret = FALSE; } return ret; #else return SUCCEEDED (hr); #endif }