Wine-devel
Threads by month
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
February 2021
- 81 participants
- 640 discussions
[PATCH] user32: Keep toplevel minimized windows offscreen if they're already.
by Gabriel Ivăncescu 04 Feb '21
by Gabriel Ivăncescu 04 Feb '21
04 Feb '21
Some applications (e.g. Lego Worlds) use (-32000,-32000) to determine
whether a window is minimized.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
dlls/user32/tests/win.c | 52 +++++++++++++++++++++++++++++++++++++++++
dlls/user32/winpos.c | 8 +++++++
2 files changed, 60 insertions(+)
diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c
index 843da89..19a0db2 100644
--- a/dlls/user32/tests/win.c
+++ b/dlls/user32/tests/win.c
@@ -11593,6 +11593,58 @@ todo_wine
ok(EqualRect(&wp.rcNormalPosition, &orig), "got normal pos %s\n",
wine_dbgstr_rect(&wp.rcNormalPosition));
+ wp.flags = WPF_SETMINPOSITION;
+ wp.showCmd = SW_NORMAL;
+ wp.ptMinPosition.x = wp.ptMinPosition.y = 100;
+ wp.ptMaxPosition.x = wp.ptMaxPosition.y = 100;
+ wp.rcNormalPosition = orig;
+ ret = SetWindowPlacement(hwnd, &wp);
+ ok(ret, "failed to set window placement, error %u\n", GetLastError());
+
+ ShowWindow(hwnd, SW_MINIMIZE);
+
+ ret = GetWindowPlacement(hwnd, &wp);
+ ok(ret, "failed to get window placement, error %u\n", GetLastError());
+ ok(wp.showCmd == SW_SHOWMINIMIZED, "got show cmd %u\n", wp.showCmd);
+ ok(wp.ptMinPosition.x == -32000 && wp.ptMinPosition.y == -32000,
+ "got minimized pos (%d,%d)\n", wp.ptMinPosition.x, wp.ptMinPosition.y);
+todo_wine
+ ok(wp.ptMaxPosition.x == -1 && wp.ptMaxPosition.y == -1,
+ "got maximized pos (%d,%d)\n", wp.ptMaxPosition.x, wp.ptMaxPosition.y);
+ ok(EqualRect(&wp.rcNormalPosition, &orig), "got normal pos %s\n",
+ wine_dbgstr_rect(&wp.rcNormalPosition));
+
+ ret = SetWindowPos(hwnd, NULL, 100, 100, 151, 151, SWP_NOACTIVATE | SWP_NOZORDER);
+ ok(ret, "failed to set window pos, error %u\n", GetLastError());
+
+ ret = GetWindowPlacement(hwnd, &wp);
+ ok(ret, "failed to get window placement, error %u\n", GetLastError());
+ ok(wp.showCmd == SW_SHOWMINIMIZED, "got show cmd %u\n", wp.showCmd);
+ ok(wp.ptMinPosition.x == -32000 && wp.ptMinPosition.y == -32000,
+ "got minimized pos (%d,%d)\n", wp.ptMinPosition.x, wp.ptMinPosition.y);
+todo_wine
+ ok(wp.ptMaxPosition.x == -1 && wp.ptMaxPosition.y == -1,
+ "got maximized pos (%d,%d)\n", wp.ptMaxPosition.x, wp.ptMaxPosition.y);
+ ok(EqualRect(&wp.rcNormalPosition, &orig), "got normal pos %s\n",
+ wine_dbgstr_rect(&wp.rcNormalPosition));
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == -32000 && rect.top == -32000, "got window rect %s\n", wine_dbgstr_rect(&rect));
+
+ ShowWindow(hwnd, SW_SHOWNORMAL);
+
+ ret = GetWindowPlacement(hwnd, &wp);
+ ok(ret, "failed to get window placement, error %u\n", GetLastError());
+ ok(wp.showCmd == SW_NORMAL, "got show cmd %u\n", wp.showCmd);
+ ok(wp.ptMinPosition.x == -32000 && wp.ptMinPosition.y == -32000,
+ "got minimized pos (%d,%d)\n", wp.ptMinPosition.x, wp.ptMinPosition.y);
+todo_wine
+ ok(wp.ptMaxPosition.x == -1 && wp.ptMaxPosition.y == -1,
+ "got maximized pos (%d,%d)\n", wp.ptMaxPosition.x, wp.ptMaxPosition.y);
+ ok(EqualRect(&wp.rcNormalPosition, &orig), "got normal pos %s\n",
+ wine_dbgstr_rect(&wp.rcNormalPosition));
+ GetWindowRect(hwnd, &rect);
+ ok(EqualRect(&rect, &orig), "got window rect %s\n", wine_dbgstr_rect(&rect));
+
DestroyWindow(hwnd);
}
diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c
index b45b74c..3ccd939 100644
--- a/dlls/user32/winpos.c
+++ b/dlls/user32/winpos.c
@@ -1688,6 +1688,14 @@ static BOOL SWP_DoWinPosChanging( WINDOWPOS *pWinpos, RECT *old_window_rect, REC
}
if (!(pWinpos->flags & SWP_NOMOVE))
{
+ /* If the window is toplevel minimized off-screen, force keep it there */
+ if ((wndPtr->dwStyle & WS_MINIMIZE) &&
+ wndPtr->window_rect.left <= -32000 && wndPtr->window_rect.top <= -32000 &&
+ (!wndPtr->parent || wndPtr->parent == GetDesktopWindow()))
+ {
+ pWinpos->x = -32000;
+ pWinpos->y = -32000;
+ }
new_window_rect->left = pWinpos->x;
new_window_rect->top = pWinpos->y;
new_window_rect->right += pWinpos->x - old_window_rect->left;
--
2.21.0
3
3
[PATCH resend] user32: Keep toplevel minimized windows offscreen if they're already.
by Gabriel Ivăncescu 04 Feb '21
by Gabriel Ivăncescu 04 Feb '21
04 Feb '21
Some applications (e.g. Lego Worlds, Hitman 2) use (-32000,-32000) to
determine whether a window is minimized.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
dlls/user32/tests/win.c | 52 +++++++++++++++++++++++++++++++++++++++++
dlls/user32/winpos.c | 8 +++++++
2 files changed, 60 insertions(+)
diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c
index 4786434..eecccb7 100644
--- a/dlls/user32/tests/win.c
+++ b/dlls/user32/tests/win.c
@@ -11547,6 +11547,58 @@ todo_wine
ok(EqualRect(&wp.rcNormalPosition, &orig), "got normal pos %s\n",
wine_dbgstr_rect(&wp.rcNormalPosition));
+ wp.flags = WPF_SETMINPOSITION;
+ wp.showCmd = SW_NORMAL;
+ wp.ptMinPosition.x = wp.ptMinPosition.y = 100;
+ wp.ptMaxPosition.x = wp.ptMaxPosition.y = 100;
+ wp.rcNormalPosition = orig;
+ ret = SetWindowPlacement(hwnd, &wp);
+ ok(ret, "failed to set window placement, error %u\n", GetLastError());
+
+ ShowWindow(hwnd, SW_MINIMIZE);
+
+ ret = GetWindowPlacement(hwnd, &wp);
+ ok(ret, "failed to get window placement, error %u\n", GetLastError());
+ ok(wp.showCmd == SW_SHOWMINIMIZED, "got show cmd %u\n", wp.showCmd);
+ ok(wp.ptMinPosition.x == -32000 && wp.ptMinPosition.y == -32000,
+ "got minimized pos (%d,%d)\n", wp.ptMinPosition.x, wp.ptMinPosition.y);
+todo_wine
+ ok(wp.ptMaxPosition.x == -1 && wp.ptMaxPosition.y == -1,
+ "got maximized pos (%d,%d)\n", wp.ptMaxPosition.x, wp.ptMaxPosition.y);
+ ok(EqualRect(&wp.rcNormalPosition, &orig), "got normal pos %s\n",
+ wine_dbgstr_rect(&wp.rcNormalPosition));
+
+ ret = SetWindowPos(hwnd, NULL, 100, 100, 151, 151, SWP_NOACTIVATE | SWP_NOZORDER);
+ ok(ret, "failed to set window pos, error %u\n", GetLastError());
+
+ ret = GetWindowPlacement(hwnd, &wp);
+ ok(ret, "failed to get window placement, error %u\n", GetLastError());
+ ok(wp.showCmd == SW_SHOWMINIMIZED, "got show cmd %u\n", wp.showCmd);
+ ok(wp.ptMinPosition.x == -32000 && wp.ptMinPosition.y == -32000,
+ "got minimized pos (%d,%d)\n", wp.ptMinPosition.x, wp.ptMinPosition.y);
+todo_wine
+ ok(wp.ptMaxPosition.x == -1 && wp.ptMaxPosition.y == -1,
+ "got maximized pos (%d,%d)\n", wp.ptMaxPosition.x, wp.ptMaxPosition.y);
+ ok(EqualRect(&wp.rcNormalPosition, &orig), "got normal pos %s\n",
+ wine_dbgstr_rect(&wp.rcNormalPosition));
+ GetWindowRect(hwnd, &rect);
+ ok(rect.left == -32000 && rect.top == -32000, "got window rect %s\n", wine_dbgstr_rect(&rect));
+
+ ShowWindow(hwnd, SW_SHOWNORMAL);
+
+ ret = GetWindowPlacement(hwnd, &wp);
+ ok(ret, "failed to get window placement, error %u\n", GetLastError());
+ ok(wp.showCmd == SW_NORMAL, "got show cmd %u\n", wp.showCmd);
+ ok(wp.ptMinPosition.x == -32000 && wp.ptMinPosition.y == -32000,
+ "got minimized pos (%d,%d)\n", wp.ptMinPosition.x, wp.ptMinPosition.y);
+todo_wine
+ ok(wp.ptMaxPosition.x == -1 && wp.ptMaxPosition.y == -1,
+ "got maximized pos (%d,%d)\n", wp.ptMaxPosition.x, wp.ptMaxPosition.y);
+ ok(EqualRect(&wp.rcNormalPosition, &orig), "got normal pos %s\n",
+ wine_dbgstr_rect(&wp.rcNormalPosition));
+ GetWindowRect(hwnd, &rect);
+ ok(EqualRect(&rect, &orig), "got window rect %s\n", wine_dbgstr_rect(&rect));
+
DestroyWindow(hwnd);
}
diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c
index 9e5a0c2..072b574 100644
--- a/dlls/user32/winpos.c
+++ b/dlls/user32/winpos.c
@@ -1688,6 +1688,14 @@ static BOOL SWP_DoWinPosChanging( WINDOWPOS *pWinpos, RECT *old_window_rect, REC
}
if (!(pWinpos->flags & SWP_NOMOVE))
{
+ /* If the window is toplevel minimized off-screen, force keep it there */
+ if ((wndPtr->dwStyle & WS_MINIMIZE) &&
+ wndPtr->window_rect.left <= -32000 && wndPtr->window_rect.top <= -32000 &&
+ (!wndPtr->parent || wndPtr->parent == GetDesktopWindow()))
+ {
+ pWinpos->x = -32000;
+ pWinpos->y = -32000;
+ }
new_window_rect->left = pWinpos->x;
new_window_rect->top = pWinpos->y;
new_window_rect->right += pWinpos->x - old_window_rect->left;
--
2.30.0
1
0
04 Feb '21
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=43422
Signed-off-by: Jan Sikorski <jsikorski(a)codeweavers.com>
---
dlls/wined3d/vertexdeclaration.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/dlls/wined3d/vertexdeclaration.c b/dlls/wined3d/vertexdeclaration.c
index c5df45541e4..7a099054372 100644
--- a/dlls/wined3d/vertexdeclaration.c
+++ b/dlls/wined3d/vertexdeclaration.c
@@ -246,11 +246,7 @@ static HRESULT vertexdeclaration_init(struct wined3d_vertex_declaration *declara
}
if (e->offset & 0x3)
- {
- WARN("Declaration element %u is not 4 byte aligned(%u), returning E_FAIL.\n", i, e->offset);
- heap_free(declaration->elements);
- return E_FAIL;
- }
+ WARN("Declaration element %u is not 4 byte aligned(%u).\n", i, e->offset);
}
return WINED3D_OK;
--
2.30.0
1
0
From: Andrew Eikum <aeikum(a)codeweavers.com>
This makes car radio / ambient noises audible in Cyberpunk 2077.
Signed-off-by: Arkadiusz Hiler <ahiler(a)codeweavers.com>
---
dlls/mmdevapi/Makefile.in | 3 +-
dlls/mmdevapi/audiovolume.c | 1 +
dlls/mmdevapi/devenum.c | 5 +
dlls/mmdevapi/main.c | 1 +
dlls/mmdevapi/mmdevapi.h | 1 +
dlls/mmdevapi/spatialaudio.c | 988 +++++++++++++++++++++++++++++++++
include/spatialaudioclient.idl | 121 ++++
7 files changed, 1119 insertions(+), 1 deletion(-)
create mode 100644 dlls/mmdevapi/spatialaudio.c
diff --git a/dlls/mmdevapi/Makefile.in b/dlls/mmdevapi/Makefile.in
index 5f44f7ba53b..903b14335a9 100644
--- a/dlls/mmdevapi/Makefile.in
+++ b/dlls/mmdevapi/Makefile.in
@@ -6,6 +6,7 @@ EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
audiovolume.c \
devenum.c \
- main.c
+ main.c \
+ spatialaudio.c
IDL_SRCS = mmdevapi_classes.idl
diff --git a/dlls/mmdevapi/audiovolume.c b/dlls/mmdevapi/audiovolume.c
index 9214980120e..6f403cf348a 100644
--- a/dlls/mmdevapi/audiovolume.c
+++ b/dlls/mmdevapi/audiovolume.c
@@ -33,6 +33,7 @@
#include "audioclient.h"
#include "endpointvolume.h"
#include "audiopolicy.h"
+#include "spatialaudioclient.h"
#include "mmdevapi.h"
diff --git a/dlls/mmdevapi/devenum.c b/dlls/mmdevapi/devenum.c
index 9e4a29816ce..07b4dca028b 100644
--- a/dlls/mmdevapi/devenum.c
+++ b/dlls/mmdevapi/devenum.c
@@ -35,6 +35,7 @@
#include "audioclient.h"
#include "endpointvolume.h"
#include "audiopolicy.h"
+#include "spatialaudioclient.h"
#include "mmdevapi.h"
#include "devpkey.h"
@@ -635,6 +636,10 @@ static HRESULT WINAPI MMDevice_Activate(IMMDevice *iface, REFIID riid, DWORD cls
IDirectSoundCapture_Release((IDirectSoundCapture*)*ppv);
}
}
+ else if (IsEqualIID(riid, &IID_ISpatialAudioClient))
+ {
+ hr = SpatialAudioClient_Create(iface, (ISpatialAudioClient**)ppv);
+ }
else
ERR("Invalid/unknown iid %s\n", debugstr_guid(riid));
diff --git a/dlls/mmdevapi/main.c b/dlls/mmdevapi/main.c
index 247ebc3b001..eac1da28f18 100644
--- a/dlls/mmdevapi/main.c
+++ b/dlls/mmdevapi/main.c
@@ -37,6 +37,7 @@
#include "audiopolicy.h"
#include "devpkey.h"
#include "winreg.h"
+#include "spatialaudioclient.h"
#include "mmdevapi.h"
#include "wine/debug.h"
diff --git a/dlls/mmdevapi/mmdevapi.h b/dlls/mmdevapi/mmdevapi.h
index bc9788e95c8..3bcf568cddf 100644
--- a/dlls/mmdevapi/mmdevapi.h
+++ b/dlls/mmdevapi/mmdevapi.h
@@ -71,5 +71,6 @@ typedef struct MMDevice {
extern HRESULT AudioClient_Create(MMDevice *parent, IAudioClient **ppv) DECLSPEC_HIDDEN;
extern HRESULT AudioEndpointVolume_Create(MMDevice *parent, IAudioEndpointVolumeEx **ppv) DECLSPEC_HIDDEN;
+extern HRESULT SpatialAudioClient_Create(IMMDevice *device, ISpatialAudioClient **out) DECLSPEC_HIDDEN;
extern const WCHAR drv_keyW[] DECLSPEC_HIDDEN;
diff --git a/dlls/mmdevapi/spatialaudio.c b/dlls/mmdevapi/spatialaudio.c
new file mode 100644
index 00000000000..cbca57b4890
--- /dev/null
+++ b/dlls/mmdevapi/spatialaudio.c
@@ -0,0 +1,988 @@
+/*
+ * Copyright 2020 Andrew Eikum for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ */
+
+#define COBJMACROS
+#define NONAMELESSUNION
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winnls.h"
+#include "winreg.h"
+#include "wine/heap.h"
+#include "wine/debug.h"
+#include "wine/list.h"
+
+#include "ole2.h"
+#include "mmdeviceapi.h"
+#include "mmsystem.h"
+#include "audioclient.h"
+#include "endpointvolume.h"
+#include "audiopolicy.h"
+#include "spatialaudioclient.h"
+
+#include "mmdevapi.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi);
+
+#define MAX_PERIODS 3
+
+static UINT32 AudioObjectType_to_index(AudioObjectType type)
+{
+ UINT32 o = 0;
+ while(type){
+ type >>= 1;
+ ++o;
+ }
+ return o - 2;
+}
+
+typedef struct SpatialAudioImpl SpatialAudioImpl;
+typedef struct SpatialAudioStreamImpl SpatialAudioStreamImpl;
+typedef struct SpatialAudioObjectImpl SpatialAudioObjectImpl;
+
+struct SpatialAudioObjectImpl {
+ ISpatialAudioObject ISpatialAudioObject_iface;
+ LONG ref;
+
+ SpatialAudioStreamImpl *sa_stream;
+ AudioObjectType type;
+ UINT32 static_idx;
+
+ float *buf;
+
+ struct list entry;
+};
+
+struct SpatialAudioStreamImpl {
+ ISpatialAudioObjectRenderStream ISpatialAudioObjectRenderStream_iface;
+ LONG ref;
+ CRITICAL_SECTION lock;
+
+ SpatialAudioImpl *sa_client;
+ SpatialAudioObjectRenderStreamActivationParams params;
+
+ IAudioClient *client;
+ IAudioRenderClient *render;
+
+ UINT32 period_frames, update_frames;
+ WAVEFORMATEXTENSIBLE stream_fmtex;
+
+ float *buf;
+
+ UINT32 static_object_map[17];
+
+ struct list objects;
+};
+
+struct SpatialAudioImpl {
+ ISpatialAudioClient ISpatialAudioClient_iface;
+ IAudioFormatEnumerator IAudioFormatEnumerator_iface;
+ IMMDevice *mmdev;
+ LONG ref;
+ WAVEFORMATEXTENSIBLE object_fmtex;
+};
+
+static inline SpatialAudioObjectImpl *impl_from_ISpatialAudioObject(ISpatialAudioObject *iface)
+{
+ return CONTAINING_RECORD(iface, SpatialAudioObjectImpl, ISpatialAudioObject_iface);
+}
+
+static inline SpatialAudioStreamImpl *impl_from_ISpatialAudioObjectRenderStream(ISpatialAudioObjectRenderStream *iface)
+{
+ return CONTAINING_RECORD(iface, SpatialAudioStreamImpl, ISpatialAudioObjectRenderStream_iface);
+}
+
+static inline SpatialAudioImpl *impl_from_ISpatialAudioClient(ISpatialAudioClient *iface)
+{
+ return CONTAINING_RECORD(iface, SpatialAudioImpl, ISpatialAudioClient_iface);
+}
+
+static inline SpatialAudioImpl *impl_from_IAudioFormatEnumerator(IAudioFormatEnumerator *iface)
+{
+ return CONTAINING_RECORD(iface, SpatialAudioImpl, IAudioFormatEnumerator_iface);
+}
+
+static HRESULT WINAPI SAO_QueryInterface(ISpatialAudioObject *iface,
+ REFIID riid, void **ppv)
+{
+ SpatialAudioObjectImpl *This = impl_from_ISpatialAudioObject(iface);
+
+ TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppv);
+
+ if (!ppv)
+ return E_POINTER;
+
+ *ppv = NULL;
+
+ if (IsEqualIID(riid, &IID_IUnknown) ||
+ IsEqualIID(riid, &IID_ISpatialAudioObjectBase) ||
+ IsEqualIID(riid, &IID_ISpatialAudioObject)) {
+ *ppv = &This->ISpatialAudioObject_iface;
+ }
+ else
+ return E_NOINTERFACE;
+
+ IUnknown_AddRef((IUnknown *)*ppv);
+
+ return S_OK;
+}
+
+static ULONG WINAPI SAO_AddRef(ISpatialAudioObject *iface)
+{
+ SpatialAudioObjectImpl *This = impl_from_ISpatialAudioObject(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+ TRACE("(%p) new ref %u\n", This, ref);
+ return ref;
+}
+
+static ULONG WINAPI SAO_Release(ISpatialAudioObject *iface)
+{
+ SpatialAudioObjectImpl *This = impl_from_ISpatialAudioObject(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+ TRACE("(%p) new ref %u\n", This, ref);
+ if(!ref){
+ EnterCriticalSection(&This->sa_stream->lock);
+ list_remove(&This->entry);
+ LeaveCriticalSection(&This->sa_stream->lock);
+
+ ISpatialAudioObjectRenderStream_Release(&This->sa_stream->ISpatialAudioObjectRenderStream_iface);
+ heap_free(This->buf);
+ heap_free(This);
+ }
+ return ref;
+}
+
+static HRESULT WINAPI SAO_GetBuffer(ISpatialAudioObject *iface,
+ BYTE **buffer, UINT32 *bytes)
+{
+ SpatialAudioObjectImpl *This = impl_from_ISpatialAudioObject(iface);
+
+ TRACE("(%p)->(%p, %p)\n", This, buffer, bytes);
+
+ EnterCriticalSection(&This->sa_stream->lock);
+
+ if(This->sa_stream->update_frames == ~0){
+ LeaveCriticalSection(&This->sa_stream->lock);
+ return SPTLAUDCLNT_E_OUT_OF_ORDER;
+ }
+
+ *buffer = (BYTE *)This->buf;
+ *bytes = This->sa_stream->update_frames *
+ This->sa_stream->sa_client->object_fmtex.Format.nBlockAlign;
+
+ LeaveCriticalSection(&This->sa_stream->lock);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI SAO_SetEndOfStream(ISpatialAudioObject *iface, UINT32 frames)
+{
+ SpatialAudioObjectImpl *This = impl_from_ISpatialAudioObject(iface);
+ FIXME("(%p)->(%u)\n", This, frames);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SAO_IsActive(ISpatialAudioObject *iface, BOOL *active)
+{
+ SpatialAudioObjectImpl *This = impl_from_ISpatialAudioObject(iface);
+ FIXME("(%p)->(%p)\n", This, active);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SAO_GetAudioObjectType(ISpatialAudioObject *iface,
+ AudioObjectType *type)
+{
+ SpatialAudioObjectImpl *This = impl_from_ISpatialAudioObject(iface);
+
+ TRACE("(%p)->(%p)\n", This, type);
+
+ *type = This->type;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI SAO_SetPosition(ISpatialAudioObject *iface, float x,
+ float y, float z)
+{
+ SpatialAudioObjectImpl *This = impl_from_ISpatialAudioObject(iface);
+ FIXME("(%p)->(%f, %f, %f)\n", This, x, y, z);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SAO_SetVolume(ISpatialAudioObject *iface, float vol)
+{
+ SpatialAudioObjectImpl *This = impl_from_ISpatialAudioObject(iface);
+ FIXME("(%p)->(%f)\n", This, vol);
+ return E_NOTIMPL;
+}
+
+static ISpatialAudioObjectVtbl ISpatialAudioObject_vtbl = {
+ SAO_QueryInterface,
+ SAO_AddRef,
+ SAO_Release,
+ SAO_GetBuffer,
+ SAO_SetEndOfStream,
+ SAO_IsActive,
+ SAO_GetAudioObjectType,
+ SAO_SetPosition,
+ SAO_SetVolume,
+};
+
+static HRESULT WINAPI SAORS_QueryInterface(ISpatialAudioObjectRenderStream *iface,
+ REFIID riid, void **ppv)
+{
+ SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
+
+ TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppv);
+
+ if (!ppv)
+ return E_POINTER;
+
+ *ppv = NULL;
+
+ if (IsEqualIID(riid, &IID_IUnknown) ||
+ IsEqualIID(riid, &IID_ISpatialAudioObjectRenderStreamBase) ||
+ IsEqualIID(riid, &IID_ISpatialAudioObjectRenderStream)) {
+ *ppv = &This->ISpatialAudioObjectRenderStream_iface;
+ }
+ else
+ return E_NOINTERFACE;
+
+ IUnknown_AddRef((IUnknown *)*ppv);
+
+ return S_OK;
+}
+
+static ULONG WINAPI SAORS_AddRef(ISpatialAudioObjectRenderStream *iface)
+{
+ SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+ TRACE("(%p) new ref %u\n", This, ref);
+ return ref;
+}
+
+static ULONG WINAPI SAORS_Release(ISpatialAudioObjectRenderStream *iface)
+{
+ SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+ TRACE("(%p) new ref %u\n", This, ref);
+ if(!ref){
+ IAudioClient_Stop(This->client);
+ if(This->update_frames != ~0 && This->update_frames > 0)
+ IAudioRenderClient_ReleaseBuffer(This->render, This->update_frames, 0);
+ IAudioRenderClient_Release(This->render);
+ IAudioClient_Release(This->client);
+ if(This->params.NotifyObject)
+ ISpatialAudioObjectRenderStreamNotify_Release(This->params.NotifyObject);
+ heap_free((void*)This->params.ObjectFormat);
+ CloseHandle(This->params.EventHandle);
+ DeleteCriticalSection(&This->lock);
+ ISpatialAudioClient_Release(&This->sa_client->ISpatialAudioClient_iface);
+ heap_free(This);
+ }
+ return ref;
+}
+
+static HRESULT WINAPI SAORS_GetAvailableDynamicObjectCount(
+ ISpatialAudioObjectRenderStream *iface, UINT32 *count)
+{
+ SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
+ FIXME("(%p)->(%p)\n", This, count);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SAORS_GetService(ISpatialAudioObjectRenderStream *iface,
+ REFIID riid, void **service)
+{
+ SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
+ FIXME("(%p)->(%s, %p)\n", This, debugstr_guid(riid), service);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SAORS_Start(ISpatialAudioObjectRenderStream *iface)
+{
+ SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
+ HRESULT hr;
+
+ TRACE("(%p)->()\n", This);
+
+ hr = IAudioClient_Start(This->client);
+ if(FAILED(hr)){
+ WARN("IAudioClient::Start failed: %08x\n", hr);
+ return hr;
+ }
+
+ return S_OK;
+}
+
+static HRESULT WINAPI SAORS_Stop(ISpatialAudioObjectRenderStream *iface)
+{
+ SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
+ HRESULT hr;
+
+ TRACE("(%p)->()\n", This);
+
+ hr = IAudioClient_Stop(This->client);
+ if(FAILED(hr)){
+ WARN("IAudioClient::Stop failed: %08x\n", hr);
+ return hr;
+ }
+
+ return S_OK;
+}
+
+static HRESULT WINAPI SAORS_Reset(ISpatialAudioObjectRenderStream *iface)
+{
+ SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
+ FIXME("(%p)->()\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SAORS_BeginUpdatingAudioObjects(ISpatialAudioObjectRenderStream *iface,
+ UINT32 *dyn_count, UINT32 *frames)
+{
+ static BOOL fixme_once = FALSE;
+ SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
+ SpatialAudioObjectImpl *object;
+ UINT32 pad;
+ HRESULT hr;
+
+ TRACE("(%p)->(%p, %p)\n", This, dyn_count, frames);
+
+ EnterCriticalSection(&This->lock);
+
+ if(This->update_frames != ~0){
+ LeaveCriticalSection(&This->lock);
+ return SPTLAUDCLNT_E_OUT_OF_ORDER;
+ }
+
+ hr = IAudioClient_GetCurrentPadding(This->client, &pad);
+ if(FAILED(hr)){
+ WARN("GetCurrentPadding failed: %08x\n", hr);
+ LeaveCriticalSection(&This->lock);
+ return hr;
+ }
+
+ if(pad < This->period_frames * MAX_PERIODS){
+ This->update_frames = This->period_frames * MAX_PERIODS - pad;
+ }else{
+ This->update_frames = 0;
+ }
+
+ if(This->update_frames > 0){
+ hr = IAudioRenderClient_GetBuffer(This->render, This->update_frames, (BYTE **)&This->buf);
+ if(FAILED(hr)){
+ WARN("GetBuffer failed: %08x\n", hr);
+ This->update_frames = ~0;
+ LeaveCriticalSection(&This->lock);
+ return hr;
+ }
+
+ LIST_FOR_EACH_ENTRY(object, &This->objects, SpatialAudioObjectImpl, entry){
+ memset(object->buf, 0, This->update_frames * This->sa_client->object_fmtex.Format.nBlockAlign);
+ }
+ }else if (!fixme_once){
+ fixme_once = TRUE;
+ FIXME("Zero frame update.\n");
+ }
+
+ *dyn_count = 0;
+ *frames = This->update_frames;
+
+ LeaveCriticalSection(&This->lock);
+
+ return S_OK;
+}
+
+static void mix_static_object(SpatialAudioStreamImpl *stream, SpatialAudioObjectImpl *object)
+{
+ float *in = object->buf, *out;
+ UINT32 i;
+ if(object->static_idx == ~0 ||
+ stream->static_object_map[object->static_idx] == ~0){
+ WARN("Got unmapped static object?! Not mixing. Type: 0x%x\n", object->type);
+ return;
+ }
+ out = stream->buf + stream->static_object_map[object->static_idx];
+ for(i = 0; i < stream->update_frames; ++i){
+ *out += *in;
+ ++in;
+ out += stream->stream_fmtex.Format.nChannels;
+ }
+}
+
+static HRESULT WINAPI SAORS_EndUpdatingAudioObjects(ISpatialAudioObjectRenderStream *iface)
+{
+ SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
+ SpatialAudioObjectImpl *object;
+ HRESULT hr;
+
+ TRACE("(%p)->()\n", This);
+
+ EnterCriticalSection(&This->lock);
+
+ if(This->update_frames == ~0){
+ LeaveCriticalSection(&This->lock);
+ return SPTLAUDCLNT_E_OUT_OF_ORDER;
+ }
+
+ if(This->update_frames > 0){
+ LIST_FOR_EACH_ENTRY(object, &This->objects, SpatialAudioObjectImpl, entry){
+ if(object->type != AudioObjectType_Dynamic)
+ mix_static_object(This, object);
+ else
+ WARN("Don't know how to mix dynamic object yet. %p\n", object);
+ }
+
+ hr = IAudioRenderClient_ReleaseBuffer(This->render, This->update_frames, 0);
+ if(FAILED(hr))
+ WARN("ReleaseBuffer failed: %08x\n", hr);
+ }
+
+ This->update_frames = ~0;
+
+ LeaveCriticalSection(&This->lock);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI SAORS_ActivateSpatialAudioObject(ISpatialAudioObjectRenderStream *iface,
+ AudioObjectType type, ISpatialAudioObject **object)
+{
+ SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
+ SpatialAudioObjectImpl *obj;
+
+ TRACE("(%p)->(0x%x, %p)\n", This, type, object);
+
+ if(type == AudioObjectType_Dynamic)
+ return SPTLAUDCLNT_E_NO_MORE_OBJECTS;
+
+ if(type & ~This->params.StaticObjectTypeMask)
+ return SPTLAUDCLNT_E_STATIC_OBJECT_NOT_AVAILABLE;
+
+ LIST_FOR_EACH_ENTRY(obj, &This->objects, SpatialAudioObjectImpl, entry){
+ if(obj->static_idx == AudioObjectType_to_index(type))
+ return SPTLAUDCLNT_E_OBJECT_ALREADY_ACTIVE;
+ }
+
+ obj = heap_alloc_zero(sizeof(*obj));
+ obj->ISpatialAudioObject_iface.lpVtbl = &ISpatialAudioObject_vtbl;
+ obj->ref = 1;
+ obj->type = type;
+ if(type == AudioObjectType_None){
+ FIXME("AudioObjectType_None not implemented yet!\n");
+ obj->static_idx = ~0;
+ }else{
+ obj->static_idx = AudioObjectType_to_index(type);
+ }
+
+ obj->sa_stream = This;
+ SAORS_AddRef(&This->ISpatialAudioObjectRenderStream_iface);
+
+ obj->buf = heap_alloc_zero(This->period_frames * MAX_PERIODS * This->sa_client->object_fmtex.Format.nBlockAlign);
+
+ EnterCriticalSection(&This->lock);
+
+ list_add_tail(&This->objects, &obj->entry);
+
+ LeaveCriticalSection(&This->lock);
+
+ *object = &obj->ISpatialAudioObject_iface;
+
+ return S_OK;
+}
+
+static ISpatialAudioObjectRenderStreamVtbl ISpatialAudioObjectRenderStream_vtbl = {
+ SAORS_QueryInterface,
+ SAORS_AddRef,
+ SAORS_Release,
+ SAORS_GetAvailableDynamicObjectCount,
+ SAORS_GetService,
+ SAORS_Start,
+ SAORS_Stop,
+ SAORS_Reset,
+ SAORS_BeginUpdatingAudioObjects,
+ SAORS_EndUpdatingAudioObjects,
+ SAORS_ActivateSpatialAudioObject,
+};
+
+static HRESULT WINAPI SAC_QueryInterface(ISpatialAudioClient *iface, REFIID riid, void **ppv)
+{
+ SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
+
+ TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppv);
+
+ if (!ppv)
+ return E_POINTER;
+
+ *ppv = NULL;
+
+ if (IsEqualIID(riid, &IID_IUnknown) ||
+ IsEqualIID(riid, &IID_ISpatialAudioClient)) {
+ *ppv = &This->ISpatialAudioClient_iface;
+ }
+ else
+ return E_NOINTERFACE;
+
+ IUnknown_AddRef((IUnknown *)*ppv);
+
+ return S_OK;
+}
+
+static ULONG WINAPI SAC_AddRef(ISpatialAudioClient *iface)
+{
+ SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+ TRACE("(%p) new ref %u\n", This, ref);
+ return ref;
+}
+
+static ULONG WINAPI SAC_Release(ISpatialAudioClient *iface)
+{
+ SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+ TRACE("(%p) new ref %u\n", This, ref);
+ if (!ref) {
+ IMMDevice_Release(This->mmdev);
+ heap_free(This);
+ }
+ return ref;
+}
+
+static HRESULT WINAPI SAC_GetStaticObjectPosition(ISpatialAudioClient *iface,
+ AudioObjectType type, float *x, float *y, float *z)
+{
+ SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
+ FIXME("(%p)->(0x%x, %p, %p, %p)\n", This, type, x, y, z);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SAC_GetNativeStaticObjectTypeMask(ISpatialAudioClient *iface,
+ AudioObjectType *mask)
+{
+ SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
+ FIXME("(%p)->(%p)\n", This, mask);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SAC_GetMaxDynamicObjectCount(ISpatialAudioClient *iface,
+ UINT32 *value)
+{
+ SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
+ FIXME("(%p)->(%p)\n", This, value);
+
+ *value = 0;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI SAC_GetSupportedAudioObjectFormatEnumerator(
+ ISpatialAudioClient *iface, IAudioFormatEnumerator **enumerator)
+{
+ SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
+
+ TRACE("(%p)->(%p)\n", This, enumerator);
+
+ *enumerator = &This->IAudioFormatEnumerator_iface;
+ SAC_AddRef(iface);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI SAC_GetMaxFrameCount(ISpatialAudioClient *iface,
+ const WAVEFORMATEX *format, UINT32 *count)
+{
+ SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
+
+ /* FIXME: should get device period from the device */
+ static const REFERENCE_TIME period = 100000;
+
+ TRACE("(%p)->(%p, %p)\n", This, format, count);
+
+ *count = MulDiv(period, format->nSamplesPerSec, 10000000) * MAX_PERIODS;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI SAC_IsAudioObjectFormatSupported(ISpatialAudioClient *iface,
+ const WAVEFORMATEX *format)
+{
+ SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
+ FIXME("(%p)->(%p)\n", This, format);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SAC_IsSpatialAudioStreamAvailable(ISpatialAudioClient *iface,
+ REFIID stream_uuid, const PROPVARIANT *info)
+{
+ SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
+ FIXME("(%p)->(%s, %p)\n", This, debugstr_guid(stream_uuid), info);
+ return E_NOTIMPL;
+}
+
+static WAVEFORMATEX *clone_fmtex(const WAVEFORMATEX *src)
+{
+ WAVEFORMATEX *r = heap_alloc(sizeof(WAVEFORMATEX) + src->cbSize);
+ memcpy(r, src, sizeof(WAVEFORMATEX) + src->cbSize);
+ return r;
+}
+
+static const char *debugstr_fmtex(const WAVEFORMATEX *fmt)
+{
+ static char buf[2048];
+ if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE){
+ const WAVEFORMATEXTENSIBLE *fmtex = (const WAVEFORMATEXTENSIBLE *)fmt;
+ snprintf(buf, sizeof(buf), "tag: 0x%x (%s), ch: %u (mask: 0x%x), rate: %u, depth: %u",
+ fmt->wFormatTag, debugstr_guid(&fmtex->SubFormat),
+ fmt->nChannels, fmtex->dwChannelMask, fmt->nSamplesPerSec,
+ fmt->wBitsPerSample);
+ }else{
+ snprintf(buf, sizeof(buf), "tag: 0x%x, ch: %u, rate: %u, depth: %u",
+ fmt->wFormatTag, fmt->nChannels, fmt->nSamplesPerSec,
+ fmt->wBitsPerSample);
+ }
+ return buf;
+}
+
+static void static_mask_to_channels(AudioObjectType static_mask, WORD *count, DWORD *mask, UINT32 *map)
+{
+ UINT32 out_chan = 0, map_idx = 0;
+ *count = 0;
+ *mask = 0;
+#define CONVERT_MASK(f, t) \
+ if(static_mask & f){ \
+ *count += 1; \
+ *mask |= t; \
+ map[map_idx++] = out_chan++; \
+ TRACE("mapping 0x%x to %u\n", f, out_chan - 1); \
+ }else{ \
+ map[map_idx++] = ~0; \
+ }
+ CONVERT_MASK(AudioObjectType_FrontLeft, SPEAKER_FRONT_LEFT);
+ CONVERT_MASK(AudioObjectType_FrontRight, SPEAKER_FRONT_RIGHT);
+ CONVERT_MASK(AudioObjectType_FrontCenter, SPEAKER_FRONT_CENTER);
+ CONVERT_MASK(AudioObjectType_LowFrequency, SPEAKER_LOW_FREQUENCY);
+ CONVERT_MASK(AudioObjectType_SideLeft, SPEAKER_SIDE_LEFT);
+ CONVERT_MASK(AudioObjectType_SideRight, SPEAKER_SIDE_RIGHT);
+ CONVERT_MASK(AudioObjectType_BackLeft, SPEAKER_BACK_LEFT);
+ CONVERT_MASK(AudioObjectType_BackRight, SPEAKER_BACK_RIGHT);
+ CONVERT_MASK(AudioObjectType_TopFrontLeft, SPEAKER_TOP_FRONT_LEFT);
+ CONVERT_MASK(AudioObjectType_TopFrontRight, SPEAKER_TOP_FRONT_RIGHT);
+ CONVERT_MASK(AudioObjectType_TopBackLeft, SPEAKER_TOP_BACK_LEFT);
+ CONVERT_MASK(AudioObjectType_TopBackRight, SPEAKER_TOP_BACK_RIGHT);
+ CONVERT_MASK(AudioObjectType_BackCenter, SPEAKER_BACK_CENTER);
+}
+
+static HRESULT activate_stream(SpatialAudioStreamImpl *stream)
+{
+ WAVEFORMATEXTENSIBLE *object_fmtex = (WAVEFORMATEXTENSIBLE *)stream->params.ObjectFormat;
+ HRESULT hr;
+ REFERENCE_TIME period;
+
+ if(!(object_fmtex->Format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
+ (object_fmtex->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
+ IsEqualGUID(&object_fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)))){
+ FIXME("Only float formats are supported for now\n");
+ return E_INVALIDARG;
+ }
+
+ hr = IMMDevice_Activate(stream->sa_client->mmdev, &IID_IAudioClient,
+ CLSCTX_INPROC_SERVER, NULL, (void**)&stream->client);
+ if(FAILED(hr)){
+ WARN("Activate failed: %08x\n", hr);
+ return hr;
+ }
+
+ hr = IAudioClient_GetDevicePeriod(stream->client, &period, NULL);
+ if(FAILED(hr)){
+ WARN("GetDevicePeriod failed: %08x\n", hr);
+ IAudioClient_Release(stream->client);
+ return hr;
+ }
+
+ stream->stream_fmtex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
+ static_mask_to_channels(stream->params.StaticObjectTypeMask,
+ &stream->stream_fmtex.Format.nChannels, &stream->stream_fmtex.dwChannelMask,
+ stream->static_object_map);
+ stream->stream_fmtex.Format.nSamplesPerSec = stream->params.ObjectFormat->nSamplesPerSec;
+ stream->stream_fmtex.Format.wBitsPerSample = stream->params.ObjectFormat->wBitsPerSample;
+ stream->stream_fmtex.Format.nBlockAlign = (stream->stream_fmtex.Format.nChannels * stream->stream_fmtex.Format.wBitsPerSample) / 8;
+ stream->stream_fmtex.Format.nAvgBytesPerSec = stream->stream_fmtex.Format.nSamplesPerSec * stream->stream_fmtex.Format.nBlockAlign;
+ stream->stream_fmtex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
+ stream->stream_fmtex.Samples.wValidBitsPerSample = stream->stream_fmtex.Format.wBitsPerSample;
+ stream->stream_fmtex.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
+
+ hr = IAudioClient_Initialize(stream->client, AUDCLNT_SHAREMODE_SHARED,
+ AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST,
+ period * MAX_PERIODS, 0, &stream->stream_fmtex.Format, NULL);
+ if(FAILED(hr)){
+ WARN("Initialize failed: %08x\n", hr);
+ IAudioClient_Release(stream->client);
+ return hr;
+ }
+
+ hr = IAudioClient_SetEventHandle(stream->client, stream->params.EventHandle);
+ if(FAILED(hr)){
+ WARN("SetEventHandle failed: %08x\n", hr);
+ IAudioClient_Release(stream->client);
+ return hr;
+ }
+
+ hr = IAudioClient_GetService(stream->client, &IID_IAudioRenderClient, (void**)&stream->render);
+ if(FAILED(hr)){
+ WARN("GetService(AudioRenderClient) failed: %08x\n", hr);
+ IAudioClient_Release(stream->client);
+ return hr;
+ }
+
+ stream->period_frames = MulDiv(period, stream->stream_fmtex.Format.nSamplesPerSec, 10000000);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI SAC_ActivateSpatialAudioStream(ISpatialAudioClient *iface,
+ const PROPVARIANT *prop, REFIID riid, void **stream)
+{
+ SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
+ SpatialAudioObjectRenderStreamActivationParams *params;
+ HRESULT hr;
+
+ TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), stream);
+
+ if(IsEqualIID(riid, &IID_ISpatialAudioObjectRenderStream)){
+ SpatialAudioStreamImpl *obj;
+
+ if(prop &&
+ (prop->vt != VT_BLOB ||
+ prop->u.blob.cbSize != sizeof(SpatialAudioObjectRenderStreamActivationParams))){
+ WARN("Got invalid params\n");
+ *stream = NULL;
+ return E_INVALIDARG;
+ }
+
+ params = (SpatialAudioObjectRenderStreamActivationParams*) prop->u.blob.pBlobData;
+
+ if(params->StaticObjectTypeMask & AudioObjectType_Dynamic){
+ *stream = NULL;
+ return E_INVALIDARG;
+ }
+
+ if(params->EventHandle == INVALID_HANDLE_VALUE ||
+ params->EventHandle == 0){
+ *stream = NULL;
+ return E_INVALIDARG;
+ }
+
+ if(!params->ObjectFormat ||
+ memcmp(params->ObjectFormat, &This->object_fmtex.Format, sizeof(*params->ObjectFormat) + params->ObjectFormat->cbSize)){
+ *stream = NULL;
+ return AUDCLNT_E_UNSUPPORTED_FORMAT;
+ }
+
+ obj = heap_alloc_zero(sizeof(SpatialAudioStreamImpl));
+
+ obj->ISpatialAudioObjectRenderStream_iface.lpVtbl = &ISpatialAudioObjectRenderStream_vtbl;
+ obj->ref = 1;
+ memcpy(&obj->params, params, sizeof(obj->params));
+
+ obj->update_frames = ~0;
+
+ InitializeCriticalSection(&obj->lock);
+ list_init(&obj->objects);
+
+ obj->sa_client = This;
+ SAC_AddRef(&This->ISpatialAudioClient_iface);
+
+ obj->params.ObjectFormat = clone_fmtex(obj->params.ObjectFormat);
+
+ DuplicateHandle(GetCurrentProcess(), obj->params.EventHandle,
+ GetCurrentProcess(), &obj->params.EventHandle, 0, FALSE,
+ DUPLICATE_SAME_ACCESS);
+
+ if(obj->params.NotifyObject)
+ ISpatialAudioObjectRenderStreamNotify_AddRef(obj->params.NotifyObject);
+
+ if(TRACE_ON(mmdevapi)){
+ TRACE("ObjectFormat: {%s}\n", debugstr_fmtex(obj->params.ObjectFormat));
+ TRACE("StaticObjectTypeMask: 0x%x\n", obj->params.StaticObjectTypeMask);
+ TRACE("MinDynamicObjectCount: 0x%x\n", obj->params.MinDynamicObjectCount);
+ TRACE("MaxDynamicObjectCount: 0x%x\n", obj->params.MaxDynamicObjectCount);
+ TRACE("Category: 0x%x\n", obj->params.Category);
+ TRACE("EventHandle: %p\n", obj->params.EventHandle);
+ TRACE("NotifyObject: %p\n", obj->params.NotifyObject);
+ }
+
+ hr = activate_stream(obj);
+ if(FAILED(hr)){
+ if(obj->params.NotifyObject)
+ ISpatialAudioObjectRenderStreamNotify_Release(obj->params.NotifyObject);
+ DeleteCriticalSection(&obj->lock);
+ heap_free((void*)obj->params.ObjectFormat);
+ CloseHandle(obj->params.EventHandle);
+ ISpatialAudioClient_Release(&obj->sa_client->ISpatialAudioClient_iface);
+ heap_free(obj);
+ *stream = NULL;
+ return hr;
+ }
+
+ *stream = &obj->ISpatialAudioObjectRenderStream_iface;
+ }else{
+ FIXME("Unsupported audio stream IID: %s\n", debugstr_guid(riid));
+ *stream = NULL;
+ return E_NOTIMPL;
+ }
+
+ return S_OK;
+}
+
+static ISpatialAudioClientVtbl ISpatialAudioClient_vtbl = {
+ SAC_QueryInterface,
+ SAC_AddRef,
+ SAC_Release,
+ SAC_GetStaticObjectPosition,
+ SAC_GetNativeStaticObjectTypeMask,
+ SAC_GetMaxDynamicObjectCount,
+ SAC_GetSupportedAudioObjectFormatEnumerator,
+ SAC_GetMaxFrameCount,
+ SAC_IsAudioObjectFormatSupported,
+ SAC_IsSpatialAudioStreamAvailable,
+ SAC_ActivateSpatialAudioStream,
+};
+
+static HRESULT WINAPI SAOFE_QueryInterface(IAudioFormatEnumerator *iface,
+ REFIID riid, void **ppvObject)
+{
+ SpatialAudioImpl *This = impl_from_IAudioFormatEnumerator(iface);
+ return SAC_QueryInterface(&This->ISpatialAudioClient_iface, riid, ppvObject);
+}
+
+static ULONG WINAPI SAOFE_AddRef(IAudioFormatEnumerator *iface)
+{
+ SpatialAudioImpl *This = impl_from_IAudioFormatEnumerator(iface);
+ return SAC_AddRef(&This->ISpatialAudioClient_iface);
+}
+
+static ULONG WINAPI SAOFE_Release(IAudioFormatEnumerator *iface)
+{
+ SpatialAudioImpl *This = impl_from_IAudioFormatEnumerator(iface);
+ return SAC_Release(&This->ISpatialAudioClient_iface);
+}
+
+static HRESULT WINAPI SAOFE_GetCount(IAudioFormatEnumerator *iface, UINT32 *count)
+{
+ SpatialAudioImpl *This = impl_from_IAudioFormatEnumerator(iface);
+
+ TRACE("(%p)->(%p)\n", This, count);
+
+ *count = 1;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI SAOFE_GetFormat(IAudioFormatEnumerator *iface,
+ UINT32 index, WAVEFORMATEX **format)
+{
+ SpatialAudioImpl *This = impl_from_IAudioFormatEnumerator(iface);
+
+ TRACE("(%p)->(%u, %p)\n", This, index, format);
+
+ if(index > 0)
+ return E_INVALIDARG;
+
+ *format = &This->object_fmtex.Format;
+
+ return S_OK;
+}
+
+static IAudioFormatEnumeratorVtbl IAudioFormatEnumerator_vtbl = {
+ SAOFE_QueryInterface,
+ SAOFE_AddRef,
+ SAOFE_Release,
+ SAOFE_GetCount,
+ SAOFE_GetFormat,
+};
+
+HRESULT SpatialAudioClient_Create(IMMDevice *mmdev, ISpatialAudioClient **out)
+{
+ SpatialAudioImpl *obj;
+ IAudioClient *aclient;
+ WAVEFORMATEX *closest;
+ HRESULT hr;
+
+ obj = heap_alloc_zero(sizeof(*obj));
+
+ obj->ref = 1;
+ obj->ISpatialAudioClient_iface.lpVtbl = &ISpatialAudioClient_vtbl;
+ obj->IAudioFormatEnumerator_iface.lpVtbl = &IAudioFormatEnumerator_vtbl;
+
+ obj->object_fmtex.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
+ obj->object_fmtex.Format.nChannels = 1;
+ obj->object_fmtex.Format.nSamplesPerSec = 48000;
+ obj->object_fmtex.Format.wBitsPerSample = sizeof(float) * 8;
+ obj->object_fmtex.Format.nBlockAlign = (obj->object_fmtex.Format.nChannels * obj->object_fmtex.Format.wBitsPerSample) / 8;
+ obj->object_fmtex.Format.nAvgBytesPerSec = obj->object_fmtex.Format.nSamplesPerSec * obj->object_fmtex.Format.nBlockAlign;
+ obj->object_fmtex.Format.cbSize = 0;
+
+ hr = IMMDevice_Activate(mmdev, &IID_IAudioClient,
+ CLSCTX_INPROC_SERVER, NULL, (void**)&aclient);
+ if(FAILED(hr)){
+ WARN("Activate failed: %08x\n", hr);
+ heap_free(obj);
+ return hr;
+ }
+
+ hr = IAudioClient_IsFormatSupported(aclient, AUDCLNT_SHAREMODE_SHARED, &obj->object_fmtex.Format, &closest);
+
+ IAudioClient_Release(aclient);
+
+ if(hr == S_FALSE){
+ if(sizeof(WAVEFORMATEX) + closest->cbSize > sizeof(obj->object_fmtex)){
+ ERR("Returned format too large: %s\n", debugstr_fmtex(closest));
+ CoTaskMemFree(closest);
+ heap_free(obj);
+ return AUDCLNT_E_UNSUPPORTED_FORMAT;
+ }else if(!((closest->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
+ (closest->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
+ IsEqualGUID(&((WAVEFORMATEXTENSIBLE *)closest)->SubFormat,
+ &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))) &&
+ closest->wBitsPerSample == 32)){
+ ERR("Returned format not 32-bit float: %s\n", debugstr_fmtex(closest));
+ CoTaskMemFree(closest);
+ heap_free(obj);
+ return AUDCLNT_E_UNSUPPORTED_FORMAT;
+ }
+ WARN("The audio stack doesn't support 48kHz 32bit float. Using the closest match. Audio may be glitchy. %s\n", debugstr_fmtex(closest));
+ memcpy(&obj->object_fmtex,
+ closest,
+ sizeof(WAVEFORMATEX) + closest->cbSize);
+ CoTaskMemFree(closest);
+ } else if(hr != S_OK){
+ WARN("Checking supported formats failed: %08x\n", hr);
+ heap_free(obj);
+ return hr;
+ }
+
+ obj->mmdev = mmdev;
+ IMMDevice_AddRef(mmdev);
+
+ *out = &obj->ISpatialAudioClient_iface;
+
+ return S_OK;
+}
diff --git a/include/spatialaudioclient.idl b/include/spatialaudioclient.idl
index 16a1541fd1d..08c84965566 100644
--- a/include/spatialaudioclient.idl
+++ b/include/spatialaudioclient.idl
@@ -43,6 +43,47 @@ typedef [v1_enum] enum AudioObjectType
AudioObjectType_BackCenter = 0x00020000,
} AudioObjectType;
+cpp_quote("#define SPTLAUDCLNT_E_DESTROYED AUDCLNT_ERR(0x100)")
+cpp_quote("#define SPTLAUDCLNT_E_OUT_OF_ORDER AUDCLNT_ERR(0x101)")
+cpp_quote("#define SPTLAUDCLNT_E_RESOURCES_INVALIDATED AUDCLNT_ERR(0x102)")
+cpp_quote("#define SPTLAUDCLNT_E_NO_MORE_OBJECTS AUDCLNT_ERR(0x103)")
+cpp_quote("#define SPTLAUDCLNT_E_PROPERTY_NOT_SUPPORTED AUDCLNT_ERR(0x104)")
+cpp_quote("#define SPTLAUDCLNT_E_ERRORS_IN_OBJECT_CALLS AUDCLNT_ERR(0x105)")
+cpp_quote("#define SPTLAUDCLNT_E_METADATA_FORMAT_NOT_SUPPORTED AUDCLNT_ERR(0x106)")
+cpp_quote("#define SPTLAUDCLNT_E_STREAM_NOT_AVAILABLE AUDCLNT_ERR(0x107)")
+cpp_quote("#define SPTLAUDCLNT_E_INVALID_LICENSE AUDCLNT_ERR(0x108)")
+cpp_quote("#define SPTLAUDCLNT_E_STREAM_NOT_STOPPED AUDCLNT_ERR(0x10a)")
+cpp_quote("#define SPTLAUDCLNT_E_STATIC_OBJECT_NOT_AVAILABLE AUDCLNT_ERR(0x10b)")
+cpp_quote("#define SPTLAUDCLNT_E_OBJECT_ALREADY_ACTIVE AUDCLNT_ERR(0x10c)")
+cpp_quote("#define SPTLAUDCLNT_E_INTERNAL AUDCLNT_ERR(0x10d)")
+
+interface ISpatialAudioObjectRenderStreamBase;
+
+[
+ object,
+ uuid(dddf83e6-68d7-4c70-883f-a1836afb4a50),
+ pointer_default(unique),
+ local
+]
+interface ISpatialAudioObjectRenderStreamNotify : IUnknown
+{
+ HRESULT OnAvailableDynamicObjectCountChange(
+ [in] ISpatialAudioObjectRenderStreamBase *stream,
+ [in] LONGLONG deadline,
+ [in] UINT32 object_count);
+}
+
+typedef struct tagSpatialAudioObjectRenderStreamActivationParams
+{
+ const WAVEFORMATEX *ObjectFormat;
+ AudioObjectType StaticObjectTypeMask;
+ UINT32 MinDynamicObjectCount;
+ UINT32 MaxDynamicObjectCount;
+ AUDIO_STREAM_CATEGORY Category;
+ HANDLE EventHandle;
+ ISpatialAudioObjectRenderStreamNotify *NotifyObject;
+} SpatialAudioObjectRenderStreamActivationParams;
+
[
object,
uuid(dcdaa858-895a-4a22-a5eb-67bda506096d),
@@ -98,3 +139,83 @@ interface ISpatialAudioClient : IUnknown
[in] REFIID riid,
[out, iid_is(riid)] void **stream);
}
+
+[
+ object,
+ uuid(cce0b8f2-8d4d-4efb-a8cf-3d6ecf1c30e0),
+ pointer_default(unique),
+ local
+]
+interface ISpatialAudioObjectBase : IUnknown
+{
+ HRESULT GetBuffer(
+ [out] BYTE **buffer,
+ [out] UINT32 *bytes);
+
+ HRESULT SetEndOfStream(
+ [in] UINT32 frames);
+
+ HRESULT IsActive(
+ [out] BOOL *active);
+
+ HRESULT GetAudioObjectType(
+ [out] AudioObjectType *type);
+}
+
+[
+ object,
+ uuid(dde28967-521b-46e5-8f00-bd6f2bc8ab1d),
+ pointer_default(unique),
+ local
+]
+interface ISpatialAudioObject : ISpatialAudioObjectBase
+{
+ HRESULT SetPosition(
+ [in] float x,
+ [in] float y,
+ [in] float z);
+
+ HRESULT SetVolume(
+ [in] float vol);
+}
+
+[
+ object,
+ uuid(feaaf403-c1d8-450d-aa05-e0ccee7502a8),
+ pointer_default(unique),
+ local
+]
+interface ISpatialAudioObjectRenderStreamBase : IUnknown
+{
+ HRESULT GetAvailableDynamicObjectCount(
+ [out] UINT32 *count);
+
+ HRESULT GetService(
+ [in] REFIID riid,
+ [out] void **service);
+
+ HRESULT Start();
+
+ HRESULT Stop();
+
+ HRESULT Reset();
+
+ HRESULT BeginUpdatingAudioObjects(
+ [out] UINT32 *count,
+ [out] UINT32 *frames);
+
+ HRESULT EndUpdatingAudioObjects();
+}
+
+[
+ object,
+ uuid(bab5f473-b423-477b-85f5-b5a332a04153),
+ pointer_default(unique),
+ local
+]
+interface ISpatialAudioObjectRenderStream : ISpatialAudioObjectRenderStreamBase
+{
+ HRESULT ActivateSpatialAudioObject(
+ [in] AudioObjectType type,
+ [out] ISpatialAudioObject **object);
+}
--
2.30.0
2
3
From: Andrew Eikum <aeikum(a)codeweavers.com>
This makes car radio / ambient noises audible in Cyberpunk 2077.
Signed-off-by: Arkadiusz Hiler <ahiler(a)codeweavers.com>
---
dlls/mmdevapi/Makefile.in | 3 +-
dlls/mmdevapi/audiovolume.c | 1 +
dlls/mmdevapi/devenum.c | 5 +
dlls/mmdevapi/main.c | 1 +
dlls/mmdevapi/mmdevapi.h | 1 +
dlls/mmdevapi/spatialaudio.c | 988 +++++++++++++++++++++++++++++++++
include/spatialaudioclient.idl | 121 ++++
7 files changed, 1119 insertions(+), 1 deletion(-)
create mode 100644 dlls/mmdevapi/spatialaudio.c
diff --git a/dlls/mmdevapi/Makefile.in b/dlls/mmdevapi/Makefile.in
index 5f44f7ba53b..903b14335a9 100644
--- a/dlls/mmdevapi/Makefile.in
+++ b/dlls/mmdevapi/Makefile.in
@@ -6,6 +6,7 @@ EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
audiovolume.c \
devenum.c \
- main.c
+ main.c \
+ spatialaudio.c
IDL_SRCS = mmdevapi_classes.idl
diff --git a/dlls/mmdevapi/audiovolume.c b/dlls/mmdevapi/audiovolume.c
index 9214980120e..6f403cf348a 100644
--- a/dlls/mmdevapi/audiovolume.c
+++ b/dlls/mmdevapi/audiovolume.c
@@ -33,6 +33,7 @@
#include "audioclient.h"
#include "endpointvolume.h"
#include "audiopolicy.h"
+#include "spatialaudioclient.h"
#include "mmdevapi.h"
diff --git a/dlls/mmdevapi/devenum.c b/dlls/mmdevapi/devenum.c
index 9e4a29816ce..07b4dca028b 100644
--- a/dlls/mmdevapi/devenum.c
+++ b/dlls/mmdevapi/devenum.c
@@ -35,6 +35,7 @@
#include "audioclient.h"
#include "endpointvolume.h"
#include "audiopolicy.h"
+#include "spatialaudioclient.h"
#include "mmdevapi.h"
#include "devpkey.h"
@@ -635,6 +636,10 @@ static HRESULT WINAPI MMDevice_Activate(IMMDevice *iface, REFIID riid, DWORD cls
IDirectSoundCapture_Release((IDirectSoundCapture*)*ppv);
}
}
+ else if (IsEqualIID(riid, &IID_ISpatialAudioClient))
+ {
+ hr = SpatialAudioClient_Create(iface, (ISpatialAudioClient**)ppv);
+ }
else
ERR("Invalid/unknown iid %s\n", debugstr_guid(riid));
diff --git a/dlls/mmdevapi/main.c b/dlls/mmdevapi/main.c
index 247ebc3b001..eac1da28f18 100644
--- a/dlls/mmdevapi/main.c
+++ b/dlls/mmdevapi/main.c
@@ -37,6 +37,7 @@
#include "audiopolicy.h"
#include "devpkey.h"
#include "winreg.h"
+#include "spatialaudioclient.h"
#include "mmdevapi.h"
#include "wine/debug.h"
diff --git a/dlls/mmdevapi/mmdevapi.h b/dlls/mmdevapi/mmdevapi.h
index bc9788e95c8..3bcf568cddf 100644
--- a/dlls/mmdevapi/mmdevapi.h
+++ b/dlls/mmdevapi/mmdevapi.h
@@ -71,5 +71,6 @@ typedef struct MMDevice {
extern HRESULT AudioClient_Create(MMDevice *parent, IAudioClient **ppv) DECLSPEC_HIDDEN;
extern HRESULT AudioEndpointVolume_Create(MMDevice *parent, IAudioEndpointVolumeEx **ppv) DECLSPEC_HIDDEN;
+extern HRESULT SpatialAudioClient_Create(IMMDevice *device, ISpatialAudioClient **out) DECLSPEC_HIDDEN;
extern const WCHAR drv_keyW[] DECLSPEC_HIDDEN;
diff --git a/dlls/mmdevapi/spatialaudio.c b/dlls/mmdevapi/spatialaudio.c
new file mode 100644
index 00000000000..cbca57b4890
--- /dev/null
+++ b/dlls/mmdevapi/spatialaudio.c
@@ -0,0 +1,988 @@
+/*
+ * Copyright 2020 Andrew Eikum for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ */
+
+#define COBJMACROS
+#define NONAMELESSUNION
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winnls.h"
+#include "winreg.h"
+#include "wine/heap.h"
+#include "wine/debug.h"
+#include "wine/list.h"
+
+#include "ole2.h"
+#include "mmdeviceapi.h"
+#include "mmsystem.h"
+#include "audioclient.h"
+#include "endpointvolume.h"
+#include "audiopolicy.h"
+#include "spatialaudioclient.h"
+
+#include "mmdevapi.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi);
+
+#define MAX_PERIODS 3
+
+static UINT32 AudioObjectType_to_index(AudioObjectType type)
+{
+ UINT32 o = 0;
+ while(type){
+ type >>= 1;
+ ++o;
+ }
+ return o - 2;
+}
+
+typedef struct SpatialAudioImpl SpatialAudioImpl;
+typedef struct SpatialAudioStreamImpl SpatialAudioStreamImpl;
+typedef struct SpatialAudioObjectImpl SpatialAudioObjectImpl;
+
+struct SpatialAudioObjectImpl {
+ ISpatialAudioObject ISpatialAudioObject_iface;
+ LONG ref;
+
+ SpatialAudioStreamImpl *sa_stream;
+ AudioObjectType type;
+ UINT32 static_idx;
+
+ float *buf;
+
+ struct list entry;
+};
+
+struct SpatialAudioStreamImpl {
+ ISpatialAudioObjectRenderStream ISpatialAudioObjectRenderStream_iface;
+ LONG ref;
+ CRITICAL_SECTION lock;
+
+ SpatialAudioImpl *sa_client;
+ SpatialAudioObjectRenderStreamActivationParams params;
+
+ IAudioClient *client;
+ IAudioRenderClient *render;
+
+ UINT32 period_frames, update_frames;
+ WAVEFORMATEXTENSIBLE stream_fmtex;
+
+ float *buf;
+
+ UINT32 static_object_map[17];
+
+ struct list objects;
+};
+
+struct SpatialAudioImpl {
+ ISpatialAudioClient ISpatialAudioClient_iface;
+ IAudioFormatEnumerator IAudioFormatEnumerator_iface;
+ IMMDevice *mmdev;
+ LONG ref;
+ WAVEFORMATEXTENSIBLE object_fmtex;
+};
+
+static inline SpatialAudioObjectImpl *impl_from_ISpatialAudioObject(ISpatialAudioObject *iface)
+{
+ return CONTAINING_RECORD(iface, SpatialAudioObjectImpl, ISpatialAudioObject_iface);
+}
+
+static inline SpatialAudioStreamImpl *impl_from_ISpatialAudioObjectRenderStream(ISpatialAudioObjectRenderStream *iface)
+{
+ return CONTAINING_RECORD(iface, SpatialAudioStreamImpl, ISpatialAudioObjectRenderStream_iface);
+}
+
+static inline SpatialAudioImpl *impl_from_ISpatialAudioClient(ISpatialAudioClient *iface)
+{
+ return CONTAINING_RECORD(iface, SpatialAudioImpl, ISpatialAudioClient_iface);
+}
+
+static inline SpatialAudioImpl *impl_from_IAudioFormatEnumerator(IAudioFormatEnumerator *iface)
+{
+ return CONTAINING_RECORD(iface, SpatialAudioImpl, IAudioFormatEnumerator_iface);
+}
+
+static HRESULT WINAPI SAO_QueryInterface(ISpatialAudioObject *iface,
+ REFIID riid, void **ppv)
+{
+ SpatialAudioObjectImpl *This = impl_from_ISpatialAudioObject(iface);
+
+ TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppv);
+
+ if (!ppv)
+ return E_POINTER;
+
+ *ppv = NULL;
+
+ if (IsEqualIID(riid, &IID_IUnknown) ||
+ IsEqualIID(riid, &IID_ISpatialAudioObjectBase) ||
+ IsEqualIID(riid, &IID_ISpatialAudioObject)) {
+ *ppv = &This->ISpatialAudioObject_iface;
+ }
+ else
+ return E_NOINTERFACE;
+
+ IUnknown_AddRef((IUnknown *)*ppv);
+
+ return S_OK;
+}
+
+static ULONG WINAPI SAO_AddRef(ISpatialAudioObject *iface)
+{
+ SpatialAudioObjectImpl *This = impl_from_ISpatialAudioObject(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+ TRACE("(%p) new ref %u\n", This, ref);
+ return ref;
+}
+
+static ULONG WINAPI SAO_Release(ISpatialAudioObject *iface)
+{
+ SpatialAudioObjectImpl *This = impl_from_ISpatialAudioObject(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+ TRACE("(%p) new ref %u\n", This, ref);
+ if(!ref){
+ EnterCriticalSection(&This->sa_stream->lock);
+ list_remove(&This->entry);
+ LeaveCriticalSection(&This->sa_stream->lock);
+
+ ISpatialAudioObjectRenderStream_Release(&This->sa_stream->ISpatialAudioObjectRenderStream_iface);
+ heap_free(This->buf);
+ heap_free(This);
+ }
+ return ref;
+}
+
+static HRESULT WINAPI SAO_GetBuffer(ISpatialAudioObject *iface,
+ BYTE **buffer, UINT32 *bytes)
+{
+ SpatialAudioObjectImpl *This = impl_from_ISpatialAudioObject(iface);
+
+ TRACE("(%p)->(%p, %p)\n", This, buffer, bytes);
+
+ EnterCriticalSection(&This->sa_stream->lock);
+
+ if(This->sa_stream->update_frames == ~0){
+ LeaveCriticalSection(&This->sa_stream->lock);
+ return SPTLAUDCLNT_E_OUT_OF_ORDER;
+ }
+
+ *buffer = (BYTE *)This->buf;
+ *bytes = This->sa_stream->update_frames *
+ This->sa_stream->sa_client->object_fmtex.Format.nBlockAlign;
+
+ LeaveCriticalSection(&This->sa_stream->lock);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI SAO_SetEndOfStream(ISpatialAudioObject *iface, UINT32 frames)
+{
+ SpatialAudioObjectImpl *This = impl_from_ISpatialAudioObject(iface);
+ FIXME("(%p)->(%u)\n", This, frames);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SAO_IsActive(ISpatialAudioObject *iface, BOOL *active)
+{
+ SpatialAudioObjectImpl *This = impl_from_ISpatialAudioObject(iface);
+ FIXME("(%p)->(%p)\n", This, active);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SAO_GetAudioObjectType(ISpatialAudioObject *iface,
+ AudioObjectType *type)
+{
+ SpatialAudioObjectImpl *This = impl_from_ISpatialAudioObject(iface);
+
+ TRACE("(%p)->(%p)\n", This, type);
+
+ *type = This->type;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI SAO_SetPosition(ISpatialAudioObject *iface, float x,
+ float y, float z)
+{
+ SpatialAudioObjectImpl *This = impl_from_ISpatialAudioObject(iface);
+ FIXME("(%p)->(%f, %f, %f)\n", This, x, y, z);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SAO_SetVolume(ISpatialAudioObject *iface, float vol)
+{
+ SpatialAudioObjectImpl *This = impl_from_ISpatialAudioObject(iface);
+ FIXME("(%p)->(%f)\n", This, vol);
+ return E_NOTIMPL;
+}
+
+static ISpatialAudioObjectVtbl ISpatialAudioObject_vtbl = {
+ SAO_QueryInterface,
+ SAO_AddRef,
+ SAO_Release,
+ SAO_GetBuffer,
+ SAO_SetEndOfStream,
+ SAO_IsActive,
+ SAO_GetAudioObjectType,
+ SAO_SetPosition,
+ SAO_SetVolume,
+};
+
+static HRESULT WINAPI SAORS_QueryInterface(ISpatialAudioObjectRenderStream *iface,
+ REFIID riid, void **ppv)
+{
+ SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
+
+ TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppv);
+
+ if (!ppv)
+ return E_POINTER;
+
+ *ppv = NULL;
+
+ if (IsEqualIID(riid, &IID_IUnknown) ||
+ IsEqualIID(riid, &IID_ISpatialAudioObjectRenderStreamBase) ||
+ IsEqualIID(riid, &IID_ISpatialAudioObjectRenderStream)) {
+ *ppv = &This->ISpatialAudioObjectRenderStream_iface;
+ }
+ else
+ return E_NOINTERFACE;
+
+ IUnknown_AddRef((IUnknown *)*ppv);
+
+ return S_OK;
+}
+
+static ULONG WINAPI SAORS_AddRef(ISpatialAudioObjectRenderStream *iface)
+{
+ SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+ TRACE("(%p) new ref %u\n", This, ref);
+ return ref;
+}
+
+static ULONG WINAPI SAORS_Release(ISpatialAudioObjectRenderStream *iface)
+{
+ SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+ TRACE("(%p) new ref %u\n", This, ref);
+ if(!ref){
+ IAudioClient_Stop(This->client);
+ if(This->update_frames != ~0 && This->update_frames > 0)
+ IAudioRenderClient_ReleaseBuffer(This->render, This->update_frames, 0);
+ IAudioRenderClient_Release(This->render);
+ IAudioClient_Release(This->client);
+ if(This->params.NotifyObject)
+ ISpatialAudioObjectRenderStreamNotify_Release(This->params.NotifyObject);
+ heap_free((void*)This->params.ObjectFormat);
+ CloseHandle(This->params.EventHandle);
+ DeleteCriticalSection(&This->lock);
+ ISpatialAudioClient_Release(&This->sa_client->ISpatialAudioClient_iface);
+ heap_free(This);
+ }
+ return ref;
+}
+
+static HRESULT WINAPI SAORS_GetAvailableDynamicObjectCount(
+ ISpatialAudioObjectRenderStream *iface, UINT32 *count)
+{
+ SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
+ FIXME("(%p)->(%p)\n", This, count);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SAORS_GetService(ISpatialAudioObjectRenderStream *iface,
+ REFIID riid, void **service)
+{
+ SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
+ FIXME("(%p)->(%s, %p)\n", This, debugstr_guid(riid), service);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SAORS_Start(ISpatialAudioObjectRenderStream *iface)
+{
+ SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
+ HRESULT hr;
+
+ TRACE("(%p)->()\n", This);
+
+ hr = IAudioClient_Start(This->client);
+ if(FAILED(hr)){
+ WARN("IAudioClient::Start failed: %08x\n", hr);
+ return hr;
+ }
+
+ return S_OK;
+}
+
+static HRESULT WINAPI SAORS_Stop(ISpatialAudioObjectRenderStream *iface)
+{
+ SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
+ HRESULT hr;
+
+ TRACE("(%p)->()\n", This);
+
+ hr = IAudioClient_Stop(This->client);
+ if(FAILED(hr)){
+ WARN("IAudioClient::Stop failed: %08x\n", hr);
+ return hr;
+ }
+
+ return S_OK;
+}
+
+static HRESULT WINAPI SAORS_Reset(ISpatialAudioObjectRenderStream *iface)
+{
+ SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
+ FIXME("(%p)->()\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SAORS_BeginUpdatingAudioObjects(ISpatialAudioObjectRenderStream *iface,
+ UINT32 *dyn_count, UINT32 *frames)
+{
+ static BOOL fixme_once = FALSE;
+ SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
+ SpatialAudioObjectImpl *object;
+ UINT32 pad;
+ HRESULT hr;
+
+ TRACE("(%p)->(%p, %p)\n", This, dyn_count, frames);
+
+ EnterCriticalSection(&This->lock);
+
+ if(This->update_frames != ~0){
+ LeaveCriticalSection(&This->lock);
+ return SPTLAUDCLNT_E_OUT_OF_ORDER;
+ }
+
+ hr = IAudioClient_GetCurrentPadding(This->client, &pad);
+ if(FAILED(hr)){
+ WARN("GetCurrentPadding failed: %08x\n", hr);
+ LeaveCriticalSection(&This->lock);
+ return hr;
+ }
+
+ if(pad < This->period_frames * MAX_PERIODS){
+ This->update_frames = This->period_frames * MAX_PERIODS - pad;
+ }else{
+ This->update_frames = 0;
+ }
+
+ if(This->update_frames > 0){
+ hr = IAudioRenderClient_GetBuffer(This->render, This->update_frames, (BYTE **)&This->buf);
+ if(FAILED(hr)){
+ WARN("GetBuffer failed: %08x\n", hr);
+ This->update_frames = ~0;
+ LeaveCriticalSection(&This->lock);
+ return hr;
+ }
+
+ LIST_FOR_EACH_ENTRY(object, &This->objects, SpatialAudioObjectImpl, entry){
+ memset(object->buf, 0, This->update_frames * This->sa_client->object_fmtex.Format.nBlockAlign);
+ }
+ }else if (!fixme_once){
+ fixme_once = TRUE;
+ FIXME("Zero frame update.\n");
+ }
+
+ *dyn_count = 0;
+ *frames = This->update_frames;
+
+ LeaveCriticalSection(&This->lock);
+
+ return S_OK;
+}
+
+static void mix_static_object(SpatialAudioStreamImpl *stream, SpatialAudioObjectImpl *object)
+{
+ float *in = object->buf, *out;
+ UINT32 i;
+ if(object->static_idx == ~0 ||
+ stream->static_object_map[object->static_idx] == ~0){
+ WARN("Got unmapped static object?! Not mixing. Type: 0x%x\n", object->type);
+ return;
+ }
+ out = stream->buf + stream->static_object_map[object->static_idx];
+ for(i = 0; i < stream->update_frames; ++i){
+ *out += *in;
+ ++in;
+ out += stream->stream_fmtex.Format.nChannels;
+ }
+}
+
+static HRESULT WINAPI SAORS_EndUpdatingAudioObjects(ISpatialAudioObjectRenderStream *iface)
+{
+ SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
+ SpatialAudioObjectImpl *object;
+ HRESULT hr;
+
+ TRACE("(%p)->()\n", This);
+
+ EnterCriticalSection(&This->lock);
+
+ if(This->update_frames == ~0){
+ LeaveCriticalSection(&This->lock);
+ return SPTLAUDCLNT_E_OUT_OF_ORDER;
+ }
+
+ if(This->update_frames > 0){
+ LIST_FOR_EACH_ENTRY(object, &This->objects, SpatialAudioObjectImpl, entry){
+ if(object->type != AudioObjectType_Dynamic)
+ mix_static_object(This, object);
+ else
+ WARN("Don't know how to mix dynamic object yet. %p\n", object);
+ }
+
+ hr = IAudioRenderClient_ReleaseBuffer(This->render, This->update_frames, 0);
+ if(FAILED(hr))
+ WARN("ReleaseBuffer failed: %08x\n", hr);
+ }
+
+ This->update_frames = ~0;
+
+ LeaveCriticalSection(&This->lock);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI SAORS_ActivateSpatialAudioObject(ISpatialAudioObjectRenderStream *iface,
+ AudioObjectType type, ISpatialAudioObject **object)
+{
+ SpatialAudioStreamImpl *This = impl_from_ISpatialAudioObjectRenderStream(iface);
+ SpatialAudioObjectImpl *obj;
+
+ TRACE("(%p)->(0x%x, %p)\n", This, type, object);
+
+ if(type == AudioObjectType_Dynamic)
+ return SPTLAUDCLNT_E_NO_MORE_OBJECTS;
+
+ if(type & ~This->params.StaticObjectTypeMask)
+ return SPTLAUDCLNT_E_STATIC_OBJECT_NOT_AVAILABLE;
+
+ LIST_FOR_EACH_ENTRY(obj, &This->objects, SpatialAudioObjectImpl, entry){
+ if(obj->static_idx == AudioObjectType_to_index(type))
+ return SPTLAUDCLNT_E_OBJECT_ALREADY_ACTIVE;
+ }
+
+ obj = heap_alloc_zero(sizeof(*obj));
+ obj->ISpatialAudioObject_iface.lpVtbl = &ISpatialAudioObject_vtbl;
+ obj->ref = 1;
+ obj->type = type;
+ if(type == AudioObjectType_None){
+ FIXME("AudioObjectType_None not implemented yet!\n");
+ obj->static_idx = ~0;
+ }else{
+ obj->static_idx = AudioObjectType_to_index(type);
+ }
+
+ obj->sa_stream = This;
+ SAORS_AddRef(&This->ISpatialAudioObjectRenderStream_iface);
+
+ obj->buf = heap_alloc_zero(This->period_frames * MAX_PERIODS * This->sa_client->object_fmtex.Format.nBlockAlign);
+
+ EnterCriticalSection(&This->lock);
+
+ list_add_tail(&This->objects, &obj->entry);
+
+ LeaveCriticalSection(&This->lock);
+
+ *object = &obj->ISpatialAudioObject_iface;
+
+ return S_OK;
+}
+
+static ISpatialAudioObjectRenderStreamVtbl ISpatialAudioObjectRenderStream_vtbl = {
+ SAORS_QueryInterface,
+ SAORS_AddRef,
+ SAORS_Release,
+ SAORS_GetAvailableDynamicObjectCount,
+ SAORS_GetService,
+ SAORS_Start,
+ SAORS_Stop,
+ SAORS_Reset,
+ SAORS_BeginUpdatingAudioObjects,
+ SAORS_EndUpdatingAudioObjects,
+ SAORS_ActivateSpatialAudioObject,
+};
+
+static HRESULT WINAPI SAC_QueryInterface(ISpatialAudioClient *iface, REFIID riid, void **ppv)
+{
+ SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
+
+ TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppv);
+
+ if (!ppv)
+ return E_POINTER;
+
+ *ppv = NULL;
+
+ if (IsEqualIID(riid, &IID_IUnknown) ||
+ IsEqualIID(riid, &IID_ISpatialAudioClient)) {
+ *ppv = &This->ISpatialAudioClient_iface;
+ }
+ else
+ return E_NOINTERFACE;
+
+ IUnknown_AddRef((IUnknown *)*ppv);
+
+ return S_OK;
+}
+
+static ULONG WINAPI SAC_AddRef(ISpatialAudioClient *iface)
+{
+ SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
+ ULONG ref = InterlockedIncrement(&This->ref);
+ TRACE("(%p) new ref %u\n", This, ref);
+ return ref;
+}
+
+static ULONG WINAPI SAC_Release(ISpatialAudioClient *iface)
+{
+ SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
+ ULONG ref = InterlockedDecrement(&This->ref);
+ TRACE("(%p) new ref %u\n", This, ref);
+ if (!ref) {
+ IMMDevice_Release(This->mmdev);
+ heap_free(This);
+ }
+ return ref;
+}
+
+static HRESULT WINAPI SAC_GetStaticObjectPosition(ISpatialAudioClient *iface,
+ AudioObjectType type, float *x, float *y, float *z)
+{
+ SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
+ FIXME("(%p)->(0x%x, %p, %p, %p)\n", This, type, x, y, z);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SAC_GetNativeStaticObjectTypeMask(ISpatialAudioClient *iface,
+ AudioObjectType *mask)
+{
+ SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
+ FIXME("(%p)->(%p)\n", This, mask);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SAC_GetMaxDynamicObjectCount(ISpatialAudioClient *iface,
+ UINT32 *value)
+{
+ SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
+ FIXME("(%p)->(%p)\n", This, value);
+
+ *value = 0;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI SAC_GetSupportedAudioObjectFormatEnumerator(
+ ISpatialAudioClient *iface, IAudioFormatEnumerator **enumerator)
+{
+ SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
+
+ TRACE("(%p)->(%p)\n", This, enumerator);
+
+ *enumerator = &This->IAudioFormatEnumerator_iface;
+ SAC_AddRef(iface);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI SAC_GetMaxFrameCount(ISpatialAudioClient *iface,
+ const WAVEFORMATEX *format, UINT32 *count)
+{
+ SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
+
+ /* FIXME: should get device period from the device */
+ static const REFERENCE_TIME period = 100000;
+
+ TRACE("(%p)->(%p, %p)\n", This, format, count);
+
+ *count = MulDiv(period, format->nSamplesPerSec, 10000000) * MAX_PERIODS;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI SAC_IsAudioObjectFormatSupported(ISpatialAudioClient *iface,
+ const WAVEFORMATEX *format)
+{
+ SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
+ FIXME("(%p)->(%p)\n", This, format);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI SAC_IsSpatialAudioStreamAvailable(ISpatialAudioClient *iface,
+ REFIID stream_uuid, const PROPVARIANT *info)
+{
+ SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
+ FIXME("(%p)->(%s, %p)\n", This, debugstr_guid(stream_uuid), info);
+ return E_NOTIMPL;
+}
+
+static WAVEFORMATEX *clone_fmtex(const WAVEFORMATEX *src)
+{
+ WAVEFORMATEX *r = heap_alloc(sizeof(WAVEFORMATEX) + src->cbSize);
+ memcpy(r, src, sizeof(WAVEFORMATEX) + src->cbSize);
+ return r;
+}
+
+static const char *debugstr_fmtex(const WAVEFORMATEX *fmt)
+{
+ static char buf[2048];
+ if(fmt->wFormatTag == WAVE_FORMAT_EXTENSIBLE){
+ const WAVEFORMATEXTENSIBLE *fmtex = (const WAVEFORMATEXTENSIBLE *)fmt;
+ snprintf(buf, sizeof(buf), "tag: 0x%x (%s), ch: %u (mask: 0x%x), rate: %u, depth: %u",
+ fmt->wFormatTag, debugstr_guid(&fmtex->SubFormat),
+ fmt->nChannels, fmtex->dwChannelMask, fmt->nSamplesPerSec,
+ fmt->wBitsPerSample);
+ }else{
+ snprintf(buf, sizeof(buf), "tag: 0x%x, ch: %u, rate: %u, depth: %u",
+ fmt->wFormatTag, fmt->nChannels, fmt->nSamplesPerSec,
+ fmt->wBitsPerSample);
+ }
+ return buf;
+}
+
+static void static_mask_to_channels(AudioObjectType static_mask, WORD *count, DWORD *mask, UINT32 *map)
+{
+ UINT32 out_chan = 0, map_idx = 0;
+ *count = 0;
+ *mask = 0;
+#define CONVERT_MASK(f, t) \
+ if(static_mask & f){ \
+ *count += 1; \
+ *mask |= t; \
+ map[map_idx++] = out_chan++; \
+ TRACE("mapping 0x%x to %u\n", f, out_chan - 1); \
+ }else{ \
+ map[map_idx++] = ~0; \
+ }
+ CONVERT_MASK(AudioObjectType_FrontLeft, SPEAKER_FRONT_LEFT);
+ CONVERT_MASK(AudioObjectType_FrontRight, SPEAKER_FRONT_RIGHT);
+ CONVERT_MASK(AudioObjectType_FrontCenter, SPEAKER_FRONT_CENTER);
+ CONVERT_MASK(AudioObjectType_LowFrequency, SPEAKER_LOW_FREQUENCY);
+ CONVERT_MASK(AudioObjectType_SideLeft, SPEAKER_SIDE_LEFT);
+ CONVERT_MASK(AudioObjectType_SideRight, SPEAKER_SIDE_RIGHT);
+ CONVERT_MASK(AudioObjectType_BackLeft, SPEAKER_BACK_LEFT);
+ CONVERT_MASK(AudioObjectType_BackRight, SPEAKER_BACK_RIGHT);
+ CONVERT_MASK(AudioObjectType_TopFrontLeft, SPEAKER_TOP_FRONT_LEFT);
+ CONVERT_MASK(AudioObjectType_TopFrontRight, SPEAKER_TOP_FRONT_RIGHT);
+ CONVERT_MASK(AudioObjectType_TopBackLeft, SPEAKER_TOP_BACK_LEFT);
+ CONVERT_MASK(AudioObjectType_TopBackRight, SPEAKER_TOP_BACK_RIGHT);
+ CONVERT_MASK(AudioObjectType_BackCenter, SPEAKER_BACK_CENTER);
+}
+
+static HRESULT activate_stream(SpatialAudioStreamImpl *stream)
+{
+ WAVEFORMATEXTENSIBLE *object_fmtex = (WAVEFORMATEXTENSIBLE *)stream->params.ObjectFormat;
+ HRESULT hr;
+ REFERENCE_TIME period;
+
+ if(!(object_fmtex->Format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
+ (object_fmtex->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
+ IsEqualGUID(&object_fmtex->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)))){
+ FIXME("Only float formats are supported for now\n");
+ return E_INVALIDARG;
+ }
+
+ hr = IMMDevice_Activate(stream->sa_client->mmdev, &IID_IAudioClient,
+ CLSCTX_INPROC_SERVER, NULL, (void**)&stream->client);
+ if(FAILED(hr)){
+ WARN("Activate failed: %08x\n", hr);
+ return hr;
+ }
+
+ hr = IAudioClient_GetDevicePeriod(stream->client, &period, NULL);
+ if(FAILED(hr)){
+ WARN("GetDevicePeriod failed: %08x\n", hr);
+ IAudioClient_Release(stream->client);
+ return hr;
+ }
+
+ stream->stream_fmtex.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
+ static_mask_to_channels(stream->params.StaticObjectTypeMask,
+ &stream->stream_fmtex.Format.nChannels, &stream->stream_fmtex.dwChannelMask,
+ stream->static_object_map);
+ stream->stream_fmtex.Format.nSamplesPerSec = stream->params.ObjectFormat->nSamplesPerSec;
+ stream->stream_fmtex.Format.wBitsPerSample = stream->params.ObjectFormat->wBitsPerSample;
+ stream->stream_fmtex.Format.nBlockAlign = (stream->stream_fmtex.Format.nChannels * stream->stream_fmtex.Format.wBitsPerSample) / 8;
+ stream->stream_fmtex.Format.nAvgBytesPerSec = stream->stream_fmtex.Format.nSamplesPerSec * stream->stream_fmtex.Format.nBlockAlign;
+ stream->stream_fmtex.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
+ stream->stream_fmtex.Samples.wValidBitsPerSample = stream->stream_fmtex.Format.wBitsPerSample;
+ stream->stream_fmtex.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
+
+ hr = IAudioClient_Initialize(stream->client, AUDCLNT_SHAREMODE_SHARED,
+ AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST,
+ period * MAX_PERIODS, 0, &stream->stream_fmtex.Format, NULL);
+ if(FAILED(hr)){
+ WARN("Initialize failed: %08x\n", hr);
+ IAudioClient_Release(stream->client);
+ return hr;
+ }
+
+ hr = IAudioClient_SetEventHandle(stream->client, stream->params.EventHandle);
+ if(FAILED(hr)){
+ WARN("SetEventHandle failed: %08x\n", hr);
+ IAudioClient_Release(stream->client);
+ return hr;
+ }
+
+ hr = IAudioClient_GetService(stream->client, &IID_IAudioRenderClient, (void**)&stream->render);
+ if(FAILED(hr)){
+ WARN("GetService(AudioRenderClient) failed: %08x\n", hr);
+ IAudioClient_Release(stream->client);
+ return hr;
+ }
+
+ stream->period_frames = MulDiv(period, stream->stream_fmtex.Format.nSamplesPerSec, 10000000);
+
+ return S_OK;
+}
+
+static HRESULT WINAPI SAC_ActivateSpatialAudioStream(ISpatialAudioClient *iface,
+ const PROPVARIANT *prop, REFIID riid, void **stream)
+{
+ SpatialAudioImpl *This = impl_from_ISpatialAudioClient(iface);
+ SpatialAudioObjectRenderStreamActivationParams *params;
+ HRESULT hr;
+
+ TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), stream);
+
+ if(IsEqualIID(riid, &IID_ISpatialAudioObjectRenderStream)){
+ SpatialAudioStreamImpl *obj;
+
+ if(prop &&
+ (prop->vt != VT_BLOB ||
+ prop->u.blob.cbSize != sizeof(SpatialAudioObjectRenderStreamActivationParams))){
+ WARN("Got invalid params\n");
+ *stream = NULL;
+ return E_INVALIDARG;
+ }
+
+ params = (SpatialAudioObjectRenderStreamActivationParams*) prop->u.blob.pBlobData;
+
+ if(params->StaticObjectTypeMask & AudioObjectType_Dynamic){
+ *stream = NULL;
+ return E_INVALIDARG;
+ }
+
+ if(params->EventHandle == INVALID_HANDLE_VALUE ||
+ params->EventHandle == 0){
+ *stream = NULL;
+ return E_INVALIDARG;
+ }
+
+ if(!params->ObjectFormat ||
+ memcmp(params->ObjectFormat, &This->object_fmtex.Format, sizeof(*params->ObjectFormat) + params->ObjectFormat->cbSize)){
+ *stream = NULL;
+ return AUDCLNT_E_UNSUPPORTED_FORMAT;
+ }
+
+ obj = heap_alloc_zero(sizeof(SpatialAudioStreamImpl));
+
+ obj->ISpatialAudioObjectRenderStream_iface.lpVtbl = &ISpatialAudioObjectRenderStream_vtbl;
+ obj->ref = 1;
+ memcpy(&obj->params, params, sizeof(obj->params));
+
+ obj->update_frames = ~0;
+
+ InitializeCriticalSection(&obj->lock);
+ list_init(&obj->objects);
+
+ obj->sa_client = This;
+ SAC_AddRef(&This->ISpatialAudioClient_iface);
+
+ obj->params.ObjectFormat = clone_fmtex(obj->params.ObjectFormat);
+
+ DuplicateHandle(GetCurrentProcess(), obj->params.EventHandle,
+ GetCurrentProcess(), &obj->params.EventHandle, 0, FALSE,
+ DUPLICATE_SAME_ACCESS);
+
+ if(obj->params.NotifyObject)
+ ISpatialAudioObjectRenderStreamNotify_AddRef(obj->params.NotifyObject);
+
+ if(TRACE_ON(mmdevapi)){
+ TRACE("ObjectFormat: {%s}\n", debugstr_fmtex(obj->params.ObjectFormat));
+ TRACE("StaticObjectTypeMask: 0x%x\n", obj->params.StaticObjectTypeMask);
+ TRACE("MinDynamicObjectCount: 0x%x\n", obj->params.MinDynamicObjectCount);
+ TRACE("MaxDynamicObjectCount: 0x%x\n", obj->params.MaxDynamicObjectCount);
+ TRACE("Category: 0x%x\n", obj->params.Category);
+ TRACE("EventHandle: %p\n", obj->params.EventHandle);
+ TRACE("NotifyObject: %p\n", obj->params.NotifyObject);
+ }
+
+ hr = activate_stream(obj);
+ if(FAILED(hr)){
+ if(obj->params.NotifyObject)
+ ISpatialAudioObjectRenderStreamNotify_Release(obj->params.NotifyObject);
+ DeleteCriticalSection(&obj->lock);
+ heap_free((void*)obj->params.ObjectFormat);
+ CloseHandle(obj->params.EventHandle);
+ ISpatialAudioClient_Release(&obj->sa_client->ISpatialAudioClient_iface);
+ heap_free(obj);
+ *stream = NULL;
+ return hr;
+ }
+
+ *stream = &obj->ISpatialAudioObjectRenderStream_iface;
+ }else{
+ FIXME("Unsupported audio stream IID: %s\n", debugstr_guid(riid));
+ *stream = NULL;
+ return E_NOTIMPL;
+ }
+
+ return S_OK;
+}
+
+static ISpatialAudioClientVtbl ISpatialAudioClient_vtbl = {
+ SAC_QueryInterface,
+ SAC_AddRef,
+ SAC_Release,
+ SAC_GetStaticObjectPosition,
+ SAC_GetNativeStaticObjectTypeMask,
+ SAC_GetMaxDynamicObjectCount,
+ SAC_GetSupportedAudioObjectFormatEnumerator,
+ SAC_GetMaxFrameCount,
+ SAC_IsAudioObjectFormatSupported,
+ SAC_IsSpatialAudioStreamAvailable,
+ SAC_ActivateSpatialAudioStream,
+};
+
+static HRESULT WINAPI SAOFE_QueryInterface(IAudioFormatEnumerator *iface,
+ REFIID riid, void **ppvObject)
+{
+ SpatialAudioImpl *This = impl_from_IAudioFormatEnumerator(iface);
+ return SAC_QueryInterface(&This->ISpatialAudioClient_iface, riid, ppvObject);
+}
+
+static ULONG WINAPI SAOFE_AddRef(IAudioFormatEnumerator *iface)
+{
+ SpatialAudioImpl *This = impl_from_IAudioFormatEnumerator(iface);
+ return SAC_AddRef(&This->ISpatialAudioClient_iface);
+}
+
+static ULONG WINAPI SAOFE_Release(IAudioFormatEnumerator *iface)
+{
+ SpatialAudioImpl *This = impl_from_IAudioFormatEnumerator(iface);
+ return SAC_Release(&This->ISpatialAudioClient_iface);
+}
+
+static HRESULT WINAPI SAOFE_GetCount(IAudioFormatEnumerator *iface, UINT32 *count)
+{
+ SpatialAudioImpl *This = impl_from_IAudioFormatEnumerator(iface);
+
+ TRACE("(%p)->(%p)\n", This, count);
+
+ *count = 1;
+
+ return S_OK;
+}
+
+static HRESULT WINAPI SAOFE_GetFormat(IAudioFormatEnumerator *iface,
+ UINT32 index, WAVEFORMATEX **format)
+{
+ SpatialAudioImpl *This = impl_from_IAudioFormatEnumerator(iface);
+
+ TRACE("(%p)->(%u, %p)\n", This, index, format);
+
+ if(index > 0)
+ return E_INVALIDARG;
+
+ *format = &This->object_fmtex.Format;
+
+ return S_OK;
+}
+
+static IAudioFormatEnumeratorVtbl IAudioFormatEnumerator_vtbl = {
+ SAOFE_QueryInterface,
+ SAOFE_AddRef,
+ SAOFE_Release,
+ SAOFE_GetCount,
+ SAOFE_GetFormat,
+};
+
+HRESULT SpatialAudioClient_Create(IMMDevice *mmdev, ISpatialAudioClient **out)
+{
+ SpatialAudioImpl *obj;
+ IAudioClient *aclient;
+ WAVEFORMATEX *closest;
+ HRESULT hr;
+
+ obj = heap_alloc_zero(sizeof(*obj));
+
+ obj->ref = 1;
+ obj->ISpatialAudioClient_iface.lpVtbl = &ISpatialAudioClient_vtbl;
+ obj->IAudioFormatEnumerator_iface.lpVtbl = &IAudioFormatEnumerator_vtbl;
+
+ obj->object_fmtex.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
+ obj->object_fmtex.Format.nChannels = 1;
+ obj->object_fmtex.Format.nSamplesPerSec = 48000;
+ obj->object_fmtex.Format.wBitsPerSample = sizeof(float) * 8;
+ obj->object_fmtex.Format.nBlockAlign = (obj->object_fmtex.Format.nChannels * obj->object_fmtex.Format.wBitsPerSample) / 8;
+ obj->object_fmtex.Format.nAvgBytesPerSec = obj->object_fmtex.Format.nSamplesPerSec * obj->object_fmtex.Format.nBlockAlign;
+ obj->object_fmtex.Format.cbSize = 0;
+
+ hr = IMMDevice_Activate(mmdev, &IID_IAudioClient,
+ CLSCTX_INPROC_SERVER, NULL, (void**)&aclient);
+ if(FAILED(hr)){
+ WARN("Activate failed: %08x\n", hr);
+ heap_free(obj);
+ return hr;
+ }
+
+ hr = IAudioClient_IsFormatSupported(aclient, AUDCLNT_SHAREMODE_SHARED, &obj->object_fmtex.Format, &closest);
+
+ IAudioClient_Release(aclient);
+
+ if(hr == S_FALSE){
+ if(sizeof(WAVEFORMATEX) + closest->cbSize > sizeof(obj->object_fmtex)){
+ ERR("Returned format too large: %s\n", debugstr_fmtex(closest));
+ CoTaskMemFree(closest);
+ heap_free(obj);
+ return AUDCLNT_E_UNSUPPORTED_FORMAT;
+ }else if(!((closest->wFormatTag == WAVE_FORMAT_IEEE_FLOAT ||
+ (closest->wFormatTag == WAVE_FORMAT_EXTENSIBLE &&
+ IsEqualGUID(&((WAVEFORMATEXTENSIBLE *)closest)->SubFormat,
+ &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))) &&
+ closest->wBitsPerSample == 32)){
+ ERR("Returned format not 32-bit float: %s\n", debugstr_fmtex(closest));
+ CoTaskMemFree(closest);
+ heap_free(obj);
+ return AUDCLNT_E_UNSUPPORTED_FORMAT;
+ }
+ WARN("The audio stack doesn't support 48kHz 32bit float. Using the closest match. Audio may be glitchy. %s\n", debugstr_fmtex(closest));
+ memcpy(&obj->object_fmtex,
+ closest,
+ sizeof(WAVEFORMATEX) + closest->cbSize);
+ CoTaskMemFree(closest);
+ } else if(hr != S_OK){
+ WARN("Checking supported formats failed: %08x\n", hr);
+ heap_free(obj);
+ return hr;
+ }
+
+ obj->mmdev = mmdev;
+ IMMDevice_AddRef(mmdev);
+
+ *out = &obj->ISpatialAudioClient_iface;
+
+ return S_OK;
+}
diff --git a/include/spatialaudioclient.idl b/include/spatialaudioclient.idl
index 16a1541fd1d..08c84965566 100644
--- a/include/spatialaudioclient.idl
+++ b/include/spatialaudioclient.idl
@@ -43,6 +43,47 @@ typedef [v1_enum] enum AudioObjectType
AudioObjectType_BackCenter = 0x00020000,
} AudioObjectType;
+cpp_quote("#define SPTLAUDCLNT_E_DESTROYED AUDCLNT_ERR(0x100)")
+cpp_quote("#define SPTLAUDCLNT_E_OUT_OF_ORDER AUDCLNT_ERR(0x101)")
+cpp_quote("#define SPTLAUDCLNT_E_RESOURCES_INVALIDATED AUDCLNT_ERR(0x102)")
+cpp_quote("#define SPTLAUDCLNT_E_NO_MORE_OBJECTS AUDCLNT_ERR(0x103)")
+cpp_quote("#define SPTLAUDCLNT_E_PROPERTY_NOT_SUPPORTED AUDCLNT_ERR(0x104)")
+cpp_quote("#define SPTLAUDCLNT_E_ERRORS_IN_OBJECT_CALLS AUDCLNT_ERR(0x105)")
+cpp_quote("#define SPTLAUDCLNT_E_METADATA_FORMAT_NOT_SUPPORTED AUDCLNT_ERR(0x106)")
+cpp_quote("#define SPTLAUDCLNT_E_STREAM_NOT_AVAILABLE AUDCLNT_ERR(0x107)")
+cpp_quote("#define SPTLAUDCLNT_E_INVALID_LICENSE AUDCLNT_ERR(0x108)")
+cpp_quote("#define SPTLAUDCLNT_E_STREAM_NOT_STOPPED AUDCLNT_ERR(0x10a)")
+cpp_quote("#define SPTLAUDCLNT_E_STATIC_OBJECT_NOT_AVAILABLE AUDCLNT_ERR(0x10b)")
+cpp_quote("#define SPTLAUDCLNT_E_OBJECT_ALREADY_ACTIVE AUDCLNT_ERR(0x10c)")
+cpp_quote("#define SPTLAUDCLNT_E_INTERNAL AUDCLNT_ERR(0x10d)")
+
+interface ISpatialAudioObjectRenderStreamBase;
+
+[
+ object,
+ uuid(dddf83e6-68d7-4c70-883f-a1836afb4a50),
+ pointer_default(unique),
+ local
+]
+interface ISpatialAudioObjectRenderStreamNotify : IUnknown
+{
+ HRESULT OnAvailableDynamicObjectCountChange(
+ [in] ISpatialAudioObjectRenderStreamBase *stream,
+ [in] LONGLONG deadline,
+ [in] UINT32 object_count);
+}
+
+typedef struct tagSpatialAudioObjectRenderStreamActivationParams
+{
+ const WAVEFORMATEX *ObjectFormat;
+ AudioObjectType StaticObjectTypeMask;
+ UINT32 MinDynamicObjectCount;
+ UINT32 MaxDynamicObjectCount;
+ AUDIO_STREAM_CATEGORY Category;
+ HANDLE EventHandle;
+ ISpatialAudioObjectRenderStreamNotify *NotifyObject;
+} SpatialAudioObjectRenderStreamActivationParams;
+
[
object,
uuid(dcdaa858-895a-4a22-a5eb-67bda506096d),
@@ -98,3 +139,83 @@ interface ISpatialAudioClient : IUnknown
[in] REFIID riid,
[out, iid_is(riid)] void **stream);
}
+
+[
+ object,
+ uuid(cce0b8f2-8d4d-4efb-a8cf-3d6ecf1c30e0),
+ pointer_default(unique),
+ local
+]
+interface ISpatialAudioObjectBase : IUnknown
+{
+ HRESULT GetBuffer(
+ [out] BYTE **buffer,
+ [out] UINT32 *bytes);
+
+ HRESULT SetEndOfStream(
+ [in] UINT32 frames);
+
+ HRESULT IsActive(
+ [out] BOOL *active);
+
+ HRESULT GetAudioObjectType(
+ [out] AudioObjectType *type);
+}
+
+[
+ object,
+ uuid(dde28967-521b-46e5-8f00-bd6f2bc8ab1d),
+ pointer_default(unique),
+ local
+]
+interface ISpatialAudioObject : ISpatialAudioObjectBase
+{
+ HRESULT SetPosition(
+ [in] float x,
+ [in] float y,
+ [in] float z);
+
+ HRESULT SetVolume(
+ [in] float vol);
+}
+
+[
+ object,
+ uuid(feaaf403-c1d8-450d-aa05-e0ccee7502a8),
+ pointer_default(unique),
+ local
+]
+interface ISpatialAudioObjectRenderStreamBase : IUnknown
+{
+ HRESULT GetAvailableDynamicObjectCount(
+ [out] UINT32 *count);
+
+ HRESULT GetService(
+ [in] REFIID riid,
+ [out] void **service);
+
+ HRESULT Start();
+
+ HRESULT Stop();
+
+ HRESULT Reset();
+
+ HRESULT BeginUpdatingAudioObjects(
+ [out] UINT32 *count,
+ [out] UINT32 *frames);
+
+ HRESULT EndUpdatingAudioObjects();
+}
+
+[
+ object,
+ uuid(bab5f473-b423-477b-85f5-b5a332a04153),
+ pointer_default(unique),
+ local
+]
+interface ISpatialAudioObjectRenderStream : ISpatialAudioObjectRenderStreamBase
+{
+ HRESULT ActivateSpatialAudioObject(
+ [in] AudioObjectType type,
+ [out] ISpatialAudioObject **object);
+}
--
2.30.0
1
1
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
Updating this patch with the suggested change, and adding a few more.
tools/widl/header.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 63389440c94..e6394991317 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -1702,6 +1702,7 @@ static void write_runtimeclass(FILE *header, type_t *runtimeclass)
{
expr_t *contract = get_attrp(runtimeclass->attrs, ATTR_CONTRACT);
char *name, *c_name;
+ size_t i, len;
name = format_namespace(runtimeclass->namespace, "", ".", runtimeclass->name, NULL);
c_name = format_namespace(runtimeclass->namespace, "", "_", runtimeclass->name, NULL);
fprintf(header, "/*\n");
@@ -1710,6 +1711,14 @@ static void write_runtimeclass(FILE *header, type_t *runtimeclass)
if (contract) write_apicontract_guard_start(header, contract);
fprintf(header, "#ifndef RUNTIMECLASS_%s_DEFINED\n", c_name);
fprintf(header, "#define RUNTIMECLASS_%s_DEFINED\n", c_name);
+ fprintf(header, "#if defined(_MSC_VER) || defined(__MINGW32__)\n");
+ /* FIXME: MIDL generates extern const here but GCC warns if extern is initialized */
+ fprintf(header, "const DECLSPEC_SELECTANY WCHAR RuntimeClass_%s[] = L\"%s\";\n", c_name, name);
+ fprintf(header, "#else\n");
+ fprintf(header, "static const WCHAR RuntimeClass_%s[] = {", c_name);
+ for (i = 0, len = strlen(name); i < len; ++i) fprintf(header, "'%c',", name[i]);
+ fprintf(header, "0};\n");
+ fprintf(header, "#endif\n");
fprintf(header, "#endif /* RUNTIMECLASS_%s_DEFINED */\n", c_name);
free(c_name);
free(name);
--
2.30.0
2
13
Since quite some time I keep splitting/cleaning up/rebasing and fixing the 2 year old PowerPC64le
patchset from 2019 (done by Timothy Pearson): [1]
The goal is to have a winelib base for Hangover [2] on PowerPC64 and there's also interest in having
winelib for crosscompiling [3].
This rebase meanwhile matured, especially end of last year, and I hope it can get upstreamed now
that wine-6.0 is out and the patch flood after it calmed down a bit.
[1] https://github.com/madscientist159/wine/commits/master
[2] https://github.com/AndreRH/hangover
[3] https://wiki.raptorcs.com/wiki/Porting/Wine
4
27
04 Feb '21
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/analyzer.c | 50 +++++++++++++++++++-----------------
dlls/dwrite/font.c | 58 ++++++++++++++++++++----------------------
dlls/dwrite/layout.c | 4 +--
dlls/dwrite/main.c | 2 +-
dlls/dwrite/opentype.c | 2 +-
5 files changed, 58 insertions(+), 58 deletions(-)
diff --git a/dlls/dwrite/analyzer.c b/dlls/dwrite/analyzer.c
index 8d573ed530d..f717bb47c80 100644
--- a/dlls/dwrite/analyzer.c
+++ b/dlls/dwrite/analyzer.c
@@ -820,7 +820,7 @@ static HRESULT analyze_linebreaks(const WCHAR *text, UINT32 count, DWRITE_LINE_B
static HRESULT WINAPI dwritetextanalyzer_QueryInterface(IDWriteTextAnalyzer2 *iface, REFIID riid, void **obj)
{
- TRACE("(%s %p)\n", debugstr_guid(riid), obj);
+ TRACE("%s, %p.\n", debugstr_guid(riid), obj);
if (IsEqualIID(riid, &IID_IDWriteTextAnalyzer2) ||
IsEqualIID(riid, &IID_IDWriteTextAnalyzer1) ||
@@ -894,7 +894,7 @@ static HRESULT WINAPI dwritetextanalyzer_AnalyzeScript(IDWriteTextAnalyzer2 *ifa
const WCHAR *text;
HRESULT hr;
- TRACE("(%p %u %u %p)\n", source, position, length, sink);
+ TRACE("%p, %u, %u, %p.\n", source, position, length, sink);
if (length == 0)
return S_OK;
@@ -919,7 +919,7 @@ static HRESULT WINAPI dwritetextanalyzer_AnalyzeBidi(IDWriteTextAnalyzer2 *iface
const WCHAR *text;
HRESULT hr;
- TRACE("(%p %u %u %p)\n", source, position, length, sink);
+ TRACE("%p, %u, %u, %p.\n", source, position, length, sink);
if (!length)
return S_OK;
@@ -990,7 +990,7 @@ static HRESULT WINAPI dwritetextanalyzer_AnalyzeLineBreakpoints(IDWriteTextAnaly
HRESULT hr;
UINT32 len;
- TRACE("(%p %u %u %p)\n", source, position, length, sink);
+ TRACE("%p, %u, %u, %p.\n", source, position, length, sink);
if (length == 0)
return S_OK;
@@ -1156,7 +1156,7 @@ static HRESULT WINAPI dwritetextanalyzer_GetGlyphs(IDWriteTextAnalyzer2 *iface,
WCHAR digits[NATIVE_DIGITS_LEN];
HRESULT hr;
- TRACE("(%s:%u %p %d %d %s %s %p %p %p %u %u %p %p %p %p %p)\n", debugstr_wn(text, length),
+ TRACE("%s:%u, %p, %d, %d, %s, %s, %p, %p, %p, %u, %u, %p, %p, %p, %p, %p.\n", debugstr_wn(text, length),
length, fontface, is_sideways, is_rtl, debugstr_sa_script(analysis->script), debugstr_w(locale), substitution,
features, feature_range_lengths, feature_ranges, max_glyph_count, clustermap, text_props, glyphs,
glyph_props, actual_glyph_count);
@@ -1512,7 +1512,7 @@ static HRESULT WINAPI dwritetextanalyzer1_ApplyCharacterSpacing(IDWriteTextAnaly
{
unsigned int i;
- TRACE("(%.2f %.2f %.2f %u %u %p %p %p %p %p %p)\n", leading_spacing, trailing_spacing, min_advance_width,
+ TRACE("%.2f, %.2f, %.2f, %u, %u, %p, %p, %p, %p, %p, %p.\n", leading_spacing, trailing_spacing, min_advance_width,
len, glyph_count, clustermap, advances, offsets, props, modified_advances, modified_offsets);
if (min_advance_width < 0.0f) {
@@ -1607,14 +1607,15 @@ static HRESULT WINAPI dwritetextanalyzer1_AnalyzeVerticalGlyphOrientation(IDWrit
static HRESULT WINAPI dwritetextanalyzer1_GetGlyphOrientationTransform(IDWriteTextAnalyzer2 *iface,
DWRITE_GLYPH_ORIENTATION_ANGLE angle, BOOL is_sideways, DWRITE_MATRIX *transform)
{
- TRACE("(%d %d %p)\n", angle, is_sideways, transform);
+ TRACE("%d, %d, %p.\n", angle, is_sideways, transform);
+
return IDWriteTextAnalyzer2_GetGlyphOrientationTransform(iface, angle, is_sideways, 0.0, 0.0, transform);
}
static HRESULT WINAPI dwritetextanalyzer1_GetScriptProperties(IDWriteTextAnalyzer2 *iface, DWRITE_SCRIPT_ANALYSIS sa,
DWRITE_SCRIPT_PROPERTIES *props)
{
- TRACE("(%u %p)\n", sa.script, props);
+ TRACE("%u, %p.\n", sa.script, props);
if (sa.script > Script_LastId)
return E_INVALIDARG;
@@ -1641,7 +1642,7 @@ static HRESULT WINAPI dwritetextanalyzer1_GetTextComplexity(IDWriteTextAnalyzer2
HRESULT hr = S_OK;
int i;
- TRACE("(%s:%u %p %p %p %p)\n", debugstr_wn(text, len), len, face, is_simple, len_read, indices);
+ TRACE("%s:%u, %p, %p, %p, %p.\n", debugstr_wn(text, len), len, face, is_simple, len_read, indices);
*is_simple = FALSE;
*len_read = 0;
@@ -1723,7 +1724,7 @@ static HRESULT WINAPI dwritetextanalyzer2_GetGlyphOrientationTransform(IDWriteTe
{ 0.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f }
};
- TRACE("(%d %d %.2f %.2f %p)\n", angle, is_sideways, originX, originY, m);
+ TRACE("%d, %d, %.2f, %.2f, %p.\n", angle, is_sideways, originX, originY, m);
if ((UINT32)angle > DWRITE_GLYPH_ORIENTATION_ANGLE_270_DEGREES) {
memset(m, 0, sizeof(*m));
@@ -1850,9 +1851,7 @@ IDWriteTextAnalyzer *get_text_analyzer(void)
static HRESULT WINAPI dwritenumbersubstitution_QueryInterface(IDWriteNumberSubstitution *iface, REFIID riid, void **obj)
{
- struct dwrite_numbersubstitution *This = impl_from_IDWriteNumberSubstitution(iface);
-
- TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
+ TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
if (IsEqualIID(riid, &IID_IDWriteNumberSubstitution) ||
IsEqualIID(riid, &IID_IUnknown))
@@ -1871,25 +1870,28 @@ static HRESULT WINAPI dwritenumbersubstitution_QueryInterface(IDWriteNumberSubst
static ULONG WINAPI dwritenumbersubstitution_AddRef(IDWriteNumberSubstitution *iface)
{
- struct dwrite_numbersubstitution *This = impl_from_IDWriteNumberSubstitution(iface);
- ULONG ref = InterlockedIncrement(&This->ref);
- TRACE("(%p)->(%d)\n", This, ref);
- return ref;
+ struct dwrite_numbersubstitution *object = impl_from_IDWriteNumberSubstitution(iface);
+ ULONG refcount = InterlockedIncrement(&object->ref);
+
+ TRACE("%p, refcount %d.\n", iface, refcount);
+
+ return refcount;
}
static ULONG WINAPI dwritenumbersubstitution_Release(IDWriteNumberSubstitution *iface)
{
- struct dwrite_numbersubstitution *This = impl_from_IDWriteNumberSubstitution(iface);
- ULONG ref = InterlockedDecrement(&This->ref);
+ struct dwrite_numbersubstitution *object = impl_from_IDWriteNumberSubstitution(iface);
+ ULONG refcount = InterlockedDecrement(&object->ref);
- TRACE("(%p)->(%d)\n", This, ref);
+ TRACE("%p, refcount %d.\n", iface, refcount);
- if (!ref) {
- heap_free(This->locale);
- heap_free(This);
+ if (!refcount)
+ {
+ heap_free(object->locale);
+ heap_free(object);
}
- return ref;
+ return refcount;
}
static const IDWriteNumberSubstitutionVtbl numbersubstitutionvtbl =
diff --git a/dlls/dwrite/font.c b/dlls/dwrite/font.c
index f1db6dd732b..e22e4abf271 100644
--- a/dlls/dwrite/font.c
+++ b/dlls/dwrite/font.c
@@ -6662,9 +6662,7 @@ HRESULT create_fontfacereference(IDWriteFactory7 *factory, IDWriteFontFile *file
static HRESULT WINAPI inmemoryfilestream_QueryInterface(IDWriteFontFileStream *iface, REFIID riid, void **obj)
{
- struct dwrite_inmemory_filestream *stream = inmemory_impl_from_IDWriteFontFileStream(iface);
-
- TRACE_(dwrite_file)("(%p)->(%s, %p)\n", stream, debugstr_guid(riid), obj);
+ TRACE_(dwrite_file)("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
if (IsEqualIID(riid, &IID_IDWriteFontFileStream) || IsEqualIID(riid, &IID_IUnknown)) {
*obj = iface;
@@ -6681,24 +6679,27 @@ static HRESULT WINAPI inmemoryfilestream_QueryInterface(IDWriteFontFileStream *i
static ULONG WINAPI inmemoryfilestream_AddRef(IDWriteFontFileStream *iface)
{
struct dwrite_inmemory_filestream *stream = inmemory_impl_from_IDWriteFontFileStream(iface);
- ULONG ref = InterlockedIncrement(&stream->ref);
- TRACE_(dwrite_file)("(%p)->(%u)\n", stream, ref);
- return ref;
+ ULONG refcount = InterlockedIncrement(&stream->ref);
+
+ TRACE_(dwrite_file)("%p, refcount %u.\n", iface, refcount);
+
+ return refcount;
}
static ULONG WINAPI inmemoryfilestream_Release(IDWriteFontFileStream *iface)
{
struct dwrite_inmemory_filestream *stream = inmemory_impl_from_IDWriteFontFileStream(iface);
- ULONG ref = InterlockedDecrement(&stream->ref);
+ ULONG refcount = InterlockedDecrement(&stream->ref);
- TRACE_(dwrite_file)("(%p)->(%u)\n", stream, ref);
+ TRACE_(dwrite_file)("%p, refcount %u.\n", iface, refcount);
- if (!ref) {
+ if (!refcount)
+ {
release_inmemory_stream(stream->data);
heap_free(stream);
}
- return ref;
+ return refcount;
}
static HRESULT WINAPI inmemoryfilestream_ReadFileFragment(IDWriteFontFileStream *iface, void const **fragment_start,
@@ -6706,7 +6707,7 @@ static HRESULT WINAPI inmemoryfilestream_ReadFileFragment(IDWriteFontFileStream
{
struct dwrite_inmemory_filestream *stream = inmemory_impl_from_IDWriteFontFileStream(iface);
- TRACE_(dwrite_file)("(%p)->(%p, 0x%s, 0x%s, %p)\n", stream, fragment_start,
+ TRACE_(dwrite_file)("%p, %p, 0x%s, 0x%s, %p.\n", iface, fragment_start,
wine_dbgstr_longlong(offset), wine_dbgstr_longlong(fragment_size), fragment_context);
*fragment_context = NULL;
@@ -6722,16 +6723,14 @@ static HRESULT WINAPI inmemoryfilestream_ReadFileFragment(IDWriteFontFileStream
static void WINAPI inmemoryfilestream_ReleaseFileFragment(IDWriteFontFileStream *iface, void *fragment_context)
{
- struct dwrite_inmemory_filestream *stream = inmemory_impl_from_IDWriteFontFileStream(iface);
-
- TRACE_(dwrite_file)("(%p)->(%p)\n", stream, fragment_context);
+ TRACE_(dwrite_file)("%p, %p.\n", iface, fragment_context);
}
static HRESULT WINAPI inmemoryfilestream_GetFileSize(IDWriteFontFileStream *iface, UINT64 *size)
{
struct dwrite_inmemory_filestream *stream = inmemory_impl_from_IDWriteFontFileStream(iface);
- TRACE_(dwrite_file)("(%p)->(%p)\n", stream, size);
+ TRACE_(dwrite_file)("%p, %p.\n", iface, size);
*size = stream->data->size;
@@ -6740,9 +6739,7 @@ static HRESULT WINAPI inmemoryfilestream_GetFileSize(IDWriteFontFileStream *ifac
static HRESULT WINAPI inmemoryfilestream_GetLastWriteTime(IDWriteFontFileStream *iface, UINT64 *last_writetime)
{
- struct dwrite_inmemory_filestream *stream = inmemory_impl_from_IDWriteFontFileStream(iface);
-
- TRACE_(dwrite_file)("(%p)->(%p)\n", stream, last_writetime);
+ TRACE_(dwrite_file)("%p, %p.\n", iface, last_writetime);
*last_writetime = 0;
@@ -6762,9 +6759,7 @@ static const IDWriteFontFileStreamVtbl inmemoryfilestreamvtbl = {
static HRESULT WINAPI inmemoryfontfileloader_QueryInterface(IDWriteInMemoryFontFileLoader *iface,
REFIID riid, void **obj)
{
- struct dwrite_inmemory_fileloader *loader = impl_from_IDWriteInMemoryFontFileLoader(iface);
-
- TRACE("(%p)->(%s, %p)\n", loader, debugstr_guid(riid), obj);
+ TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
if (IsEqualIID(riid, &IID_IDWriteInMemoryFontFileLoader) ||
IsEqualIID(riid, &IID_IDWriteFontFileLoader) ||
@@ -6785,27 +6780,30 @@ static HRESULT WINAPI inmemoryfontfileloader_QueryInterface(IDWriteInMemoryFontF
static ULONG WINAPI inmemoryfontfileloader_AddRef(IDWriteInMemoryFontFileLoader *iface)
{
struct dwrite_inmemory_fileloader *loader = impl_from_IDWriteInMemoryFontFileLoader(iface);
- ULONG ref = InterlockedIncrement(&loader->ref);
- TRACE("(%p)->(%u)\n", loader, ref);
- return ref;
+ ULONG refcount = InterlockedIncrement(&loader->ref);
+
+ TRACE("%p, refcount %u.\n", iface, refcount);
+
+ return refcount;
}
static ULONG WINAPI inmemoryfontfileloader_Release(IDWriteInMemoryFontFileLoader *iface)
{
struct dwrite_inmemory_fileloader *loader = impl_from_IDWriteInMemoryFontFileLoader(iface);
- ULONG ref = InterlockedDecrement(&loader->ref);
+ ULONG refcount = InterlockedDecrement(&loader->ref);
size_t i;
- TRACE("(%p)->(%u)\n", loader, ref);
+ TRACE("%p, refcount %u.\n", iface, refcount);
- if (!ref) {
+ if (!refcount)
+ {
for (i = 0; i < loader->count; ++i)
release_inmemory_stream(loader->streams[i]);
heap_free(loader->streams);
heap_free(loader);
}
- return ref;
+ return refcount;
}
static HRESULT WINAPI inmemoryfontfileloader_CreateStreamFromKey(IDWriteInMemoryFontFileLoader *iface,
@@ -6815,7 +6813,7 @@ static HRESULT WINAPI inmemoryfontfileloader_CreateStreamFromKey(IDWriteInMemory
struct dwrite_inmemory_filestream *stream;
DWORD index;
- TRACE("(%p)->(%p, %u, %p)\n", loader, key, key_size, ret);
+ TRACE("%p, %p, %u, %p.\n", iface, key, key_size, ret);
*ret = NULL;
@@ -6847,7 +6845,7 @@ static HRESULT WINAPI inmemoryfontfileloader_CreateInMemoryFontFileReference(IDW
struct dwrite_inmemory_stream_data *stream;
DWORD key;
- TRACE("(%p)->(%p, %p, %u, %p, %p)\n", loader, factory, data, data_size, owner, fontfile);
+ TRACE("%p, %p, %p, %u, %p, %p.\n", iface, factory, data, data_size, owner, fontfile);
*fontfile = NULL;
diff --git a/dlls/dwrite/layout.c b/dlls/dwrite/layout.c
index 0b5bad80339..b68daf0345b 100644
--- a/dlls/dwrite/layout.c
+++ b/dlls/dwrite/layout.c
@@ -4935,7 +4935,7 @@ static HRESULT WINAPI dwritetextlayout_source_GetTextAtPosition(IDWriteTextAnaly
{
struct dwrite_textlayout *layout = impl_from_IDWriteTextAnalysisSource1(iface);
- TRACE("(%p)->(%u %p %p)\n", layout, position, text, text_len);
+ TRACE("%p, %u, %p, %p.\n", iface, position, text, text_len);
if (position < layout->len) {
*text = &layout->str[position];
@@ -4954,7 +4954,7 @@ static HRESULT WINAPI dwritetextlayout_source_GetTextBeforePosition(IDWriteTextA
{
struct dwrite_textlayout *layout = impl_from_IDWriteTextAnalysisSource1(iface);
- TRACE("(%p)->(%u %p %p)\n", layout, position, text, text_len);
+ TRACE("%p, %u, %p, %p.\n", iface, position, text, text_len);
if (position > 0 && position < layout->len) {
*text = layout->str;
diff --git a/dlls/dwrite/main.c b/dlls/dwrite/main.c
index f550c204b6d..40c82b6cd05 100644
--- a/dlls/dwrite/main.c
+++ b/dlls/dwrite/main.c
@@ -1931,7 +1931,7 @@ HRESULT WINAPI DWriteCreateFactory(DWRITE_FACTORY_TYPE type, REFIID riid, IUnkno
struct dwritefactory *factory;
HRESULT hr;
- TRACE("(%d, %s, %p)\n", type, debugstr_guid(riid), ret);
+ TRACE("%d, %s, %p.\n", type, debugstr_guid(riid), ret);
*ret = NULL;
diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index ae9a88a876c..0e5b8c75f62 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -2159,7 +2159,7 @@ void opentype_get_font_properties(struct file_stream_desc *stream_desc, struct d
IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, colr.context);
}
- TRACE("stretch=%d, weight=%d, style %d\n", props->stretch, props->weight, props->style);
+ TRACE("stretch %d, weight %d, style %d\n", props->stretch, props->weight, props->style);
if (os2.data)
IDWriteFontFileStream_ReleaseFileFragment(stream_desc->stream, os2.context);
--
2.30.0
1
1
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/mfplat/tests/mfplat.c | 36 +++++++++++++++++++++---------------
1 file changed, 21 insertions(+), 15 deletions(-)
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index deb9e78efba..0464293b37f 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -136,6 +136,7 @@ static DXGI_FORMAT (WINAPI *pMFMapDX9FormatToDXGIFormat)(DWORD format);
static HRESULT (WINAPI *pMFCreateVideoSampleAllocatorEx)(REFIID riid, void **allocator);
static HRESULT (WINAPI *pMFCreateDXGISurfaceBuffer)(REFIID riid, IUnknown *surface, UINT subresource, BOOL bottomup,
IMFMediaBuffer **buffer);
+static HRESULT (WINAPI *pMFCreateVideoMediaTypeFromSubtype)(const GUID *subtype, IMFVideoMediaType **media_type);
static HWND create_window(void)
{
@@ -799,6 +800,7 @@ static void init_functions(void)
X(MFCreateMFByteStreamOnStream);
X(MFCreateTrackedSample);
X(MFCreateTransformActivate);
+ X(MFCreateVideoMediaTypeFromSubtype);
X(MFCreateVideoSampleAllocatorEx);
X(MFGetPlaneSize);
X(MFGetStrideForBitmapInfoHeader);
@@ -965,28 +967,32 @@ if(0)
IUnknown_Release(unk2);
IUnknown_Release(unk);
+ IMFMediaType_Release(mediatype);
- hr = MFCreateVideoMediaTypeFromSubtype(&MFVideoFormat_RGB555, &video_type);
- ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
-
- check_interface(video_type, &IID_IMFMediaType, TRUE);
- check_interface(video_type, &IID_IMFVideoMediaType, TRUE);
+ if (pMFCreateVideoMediaTypeFromSubtype)
+ {
+ hr = pMFCreateVideoMediaTypeFromSubtype(&MFVideoFormat_RGB555, &video_type);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
- /* Major and subtype are set on creation. */
- hr = IMFVideoMediaType_GetCount(video_type, &count);
- ok(count == 2, "Unexpected attribute count %#x.\n", hr);
+ check_interface(video_type, &IID_IMFMediaType, TRUE);
+ check_interface(video_type, &IID_IMFVideoMediaType, TRUE);
- hr = IMFVideoMediaType_DeleteAllItems(video_type);
- ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ /* Major and subtype are set on creation. */
+ hr = IMFVideoMediaType_GetCount(video_type, &count);
+ ok(count == 2, "Unexpected attribute count %#x.\n", hr);
- hr = IMFVideoMediaType_GetCount(video_type, &count);
- ok(!count, "Unexpected attribute count %#x.\n", hr);
+ hr = IMFVideoMediaType_DeleteAllItems(video_type);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
- check_interface(video_type, &IID_IMFVideoMediaType, FALSE);
+ hr = IMFVideoMediaType_GetCount(video_type, &count);
+ ok(!count, "Unexpected attribute count %#x.\n", hr);
- IMFVideoMediaType_Release(video_type);
+ check_interface(video_type, &IID_IMFVideoMediaType, FALSE);
- IMFMediaType_Release(mediatype);
+ IMFVideoMediaType_Release(video_type);
+ }
+ else
+ win_skip("MFCreateVideoMediaTypeFromSubtype() is not available.\n");
/* IMFAudioMediaType */
hr = MFCreateMediaType(&mediatype);
--
2.30.0
1
0
Signed-off-by: Byeongsik Jeon <bsjeon(a)hanmail.net>
---
po/ko.po | 252 +++++++++++++++++++++++++++----------------------------
1 file changed, 126 insertions(+), 126 deletions(-)
diff --git a/po/ko.po b/po/ko.po
index 40962ead745..8cc8c6d5099 100644
--- a/po/ko.po
+++ b/po/ko.po
@@ -5,7 +5,7 @@ msgstr ""
"Project-Id-Version: Wine\n"
"Report-Msgid-Bugs-To: https://bugs.winehq.org\n"
"POT-Creation-Date: N/A\n"
-"PO-Revision-Date: 2020-12-29 16:25+0900\n"
+"PO-Revision-Date: 2021-02-04 15:08+0900\n"
"Last-Translator: Byeongsik Jeon <bsjeon(a)hanmail.net>\n"
"Language-Team: Korean\n"
"Language: ko\n"
@@ -6709,7 +6709,7 @@ msgstr "RPC 호출이 취소되었습니다.\n"
#: dlls/kernel32/winerror.mc:3508
msgid "Binding incomplete.\n"
-msgstr "Binding incomplete.\n"
+msgstr "바인딩이 완료되지 않았습니다.\n"
#: dlls/kernel32/winerror.mc:3513
msgid "RPC comm failure.\n"
@@ -7807,7 +7807,7 @@ msgstr "서비스: [1]"
#: dlls/msi/msi.rc:167 dlls/msi/msi.rc:170 dlls/msi/msi.rc:174
msgid "File: [1], Directory: [9], Size: [6]"
-msgstr "파일: [1], 디렉터리: [9], 크기: [6]"
+msgstr "파일: [1], 디렉터리: [9], 크기: [6]"
#: dlls/msi/msi.rc:168
msgid "Found application: [1]"
@@ -7823,7 +7823,7 @@ msgstr "서비스: [2]"
#: dlls/msi/msi.rc:172
msgid "File: [1], Dependencies: [2]"
-msgstr "파일: [1], 종속성: [2]"
+msgstr "파일: [1], 종속성: [2]"
#: dlls/msi/msi.rc:173
msgid "Application: [1]"
@@ -7835,7 +7835,7 @@ msgstr "프로그램 컨텍스트: [1], 어셈블리 이름 : [2]"
#: dlls/msi/msi.rc:177
msgid "File: [1], Directory: [2], Size: [3]"
-msgstr "파일: [1], 디렉터리: [2], 크기: [3]"
+msgstr "파일: [1], 디렉터리: [2], 크기: [3]"
#: dlls/msi/msi.rc:178 dlls/msi/msi.rc:199
msgid "Component ID: [1], Qualifier: [2]"
@@ -7887,7 +7887,7 @@ msgstr "프로그램: [1], 명령줄: [2]"
#: dlls/msi/msi.rc:192 dlls/msi/msi.rc:209
msgid "File: [1], Section: [2], Key: [3], Value: [4]"
-msgstr "파일: [1], 부분: [2], 키: [3], 값: [4]"
+msgstr "파일: [1], 부분: [2], 키: [3], 값: [4]"
#: dlls/msi/msi.rc:193
msgid "Key: [1], Name: [2]"
@@ -9156,7 +9156,7 @@ msgstr "오른쪽으로 스크롤"
#: dlls/shdoclc/shdoclc.rc:28
msgid "Wine Internet Explorer"
-msgstr "Wine 인터넷 익스폴로어"
+msgstr "Wine 인터넷 익스플로러"
#: dlls/shdoclc/shdoclc.rc:33
msgid "&w&bPage &p"
@@ -11728,7 +11728,7 @@ msgstr "기밀성이 요구됩니다"
#: dlls/wldap32/wldap32.rc:46
msgid "SASL Bind in Progress"
-msgstr "SASL 바인딩 진행 중"
+msgstr "SASL 바인딩 중입니다"
#: dlls/wldap32/wldap32.rc:48
msgid "No Such Attribute"
@@ -11752,7 +11752,7 @@ msgstr "특성 또는 값이 있습니다"
#: dlls/wldap32/wldap32.rc:53
msgid "Invalid Syntax"
-msgstr "잘못된 구문"
+msgstr "잘못된 구문입니다"
#: dlls/wldap32/wldap32.rc:64
msgid "No Such Object"
@@ -11768,7 +11768,7 @@ msgstr "잘못된 DN 구문입니다"
#: dlls/wldap32/wldap32.rc:67
msgid "Is Leaf"
-msgstr "잎 노드임"
+msgstr "잎 노드입니다"
#: dlls/wldap32/wldap32.rc:68
msgid "Alias Dereference Problem"
@@ -11788,11 +11788,11 @@ msgstr "권한이 부족합니다"
#: dlls/wldap32/wldap32.rc:83
msgid "Busy"
-msgstr "바쁨"
+msgstr "사용 중입니다"
#: dlls/wldap32/wldap32.rc:84
msgid "Unavailable"
-msgstr "사용할 수 없음"
+msgstr "사용할 수 없습니다"
#: dlls/wldap32/wldap32.rc:85
msgid "Unwilling To Perform"
@@ -11920,7 +11920,7 @@ msgstr ""
#: programs/attrib/attrib.rc:31 programs/cmd/cmd.rc:376
msgid "%1: File Not Found\n"
-msgstr "%1:파일을 찾을 수 없습니다\n"
+msgstr "%1: 파일을 찾을 수 없습니다\n"
#: programs/attrib/attrib.rc:50
msgid ""
@@ -11943,24 +11943,25 @@ msgid ""
" /S Processes matching files in the current folder and all subfolders.\n"
" /D Processes folders as well.\n"
msgstr ""
-"ATTRIB - 파일 속성을 바꾸거나 표시합니다.\n"
+"ATTRIB - 파일 특성을 화면에 표시하거나 변경합니다.\n"
"\n"
-"문법:\n"
-"ATTRIB [+R | -R] [+A | -A ] [+S | -S] [+H | -H] [drive:][path][filename]\n"
+"구문:\n"
+"ATTRIB [+R | -R] [+A | -A ] [+S | -S] [+H | -H] [드라이브:][경로][파일 이"
+"름]\n"
" [/S [/D]]\n"
"\n"
"옵션:\n"
"\n"
-" + 속성을 설정합니다.\n"
-" - 속성을 제거합니다.\n"
-" R 읽기 전용 속성를 설정합니다.\n"
-" A 압축 파일 속성을 설정합니다.\n"
-" S 시스템 파일 속성을 설정합니다.\n"
-" H 숨은 파일 속성을 설정합니다.\n"
-" [drive:][path][filename]\n"
-" 속성 작업을 할 하나 또는 복수의 파일을 지정합니다.\n"
+" + 특성을 설정합니다.\n"
+" - 특성을 지웁니다.\n"
+" R 읽기 전용 파일 특성을 설정합니다.\n"
+" A 보관 파일 특성을 설정합니다.\n"
+" S 시스템 파일 특성을 설정합니다.\n"
+" H 숨김 파일 특성을 설정합니다.\n"
+" [드라이브:][경로][파일 이름]\n"
+" ATTRIB 명령을 수행할 파일을 지정합니다.\n"
" /S 현재 폴더와 모든 하위 폴더에서 일치하는 파일을 처리합니다.\n"
-" /D 폴더를 함께 처리합니다.\n"
+" /D 폴더를 처리합니다.\n"
#: programs/clock/clock.rc:32
msgid "Ana&log"
@@ -12011,13 +12012,13 @@ msgid ""
"Changes to default directory, environment variables etc made within a\n"
"called procedure are inherited by the caller.\n"
msgstr ""
-"<배치파일 이름>을 호출하는 것은 배치 파일 안에서 다른 배치 파일의\n"
-"명령을 실행하는 것입니다. 배치 파일이 끝나면, 제어권은 배치 파일을\n"
-"호출한 배치 파일로 돌아갑니다.\n"
-"CALL 명령은 매개변수를 지원합니다.\n"
+"CALL <배치파일 이름>은 배치 파일 내에서 다른 배치 파일의 명령을\n"
+"실행하는 데 사용됩니다. 배치 파일이 끝나면 제어권은 배치 파일을\n"
+"호출한 배치 파일로 돌아갑니다. CALL 명령은 호출된 프로시저에\n"
+"매개변수를 제공할 수 있습니다.\n"
"\n"
-"호출된 프로시저 안에서 기본 디렉터리, 환경 변수 등을 바꾸는 것은\n"
-"호출자에게 상속됩니다.\n"
+"호출된 프로시저 내에서 작성된 기본 디렉터리, 환경 변수 등의\n"
+"변경사항은 발신자가 상속합니다.\n"
#: programs/cmd/cmd.rc:44
msgid ""
@@ -12025,15 +12026,15 @@ msgid ""
"default directory.\n"
msgstr ""
"CD <디렉터리> 는 CHDIR의 단축 버전입니다.\n"
-"현재 작업 디렉터리를 바꿉니다.\n"
+"현재 기본 디렉터리를 바꿉니다.\n"
#: programs/cmd/cmd.rc:47
msgid "CHDIR <directory> changes the current default directory.\n"
-msgstr "CHDIR <디렉터리> 는 현재 작업 디렉터리를 바꿉니다.\n"
+msgstr "CHDIR <디렉터리> 는 현재 기본 디렉터리를 바꿉니다.\n"
#: programs/cmd/cmd.rc:50
msgid "CLS clears the console screen.\n"
-msgstr "CLS는 콘솔 화면을 깨끗하게 합니다.\n"
+msgstr "CLS는 콘솔 화면을 지웁니다.\n"
#: programs/cmd/cmd.rc:53
msgid "COPY <filename> copies a file.\n"
@@ -12049,7 +12050,7 @@ msgstr "DATE는 시스템 날짜를 보여주거나 바꿉니다.\n"
#: programs/cmd/cmd.rc:62
msgid "DEL <filename> deletes a file or set of files.\n"
-msgstr "DEL <파일 이름>은 하나의 파일이나 여러 파일을 지웁니다.\n"
+msgstr "DEL <파일 이름>은 하나 또는 여러개의 파일을 지웁니다.\n"
#: programs/cmd/cmd.rc:65
msgid "DIR lists the contents of a directory.\n"
@@ -12068,16 +12069,17 @@ msgid ""
msgstr ""
"ECHO <문자열>은 <문자열>을 현재 터미널 장치에 표시합니다.\n"
"\n"
-"ECHO ON는 배치파일 안의 모든 이후 명령어를 터미널 장치에 실행하기 전에\n"
-"표시합니다.\n"
+"ECHO ON는 배치파일 안의 모든 이후 명령어가 실행 전에 터미널 장치에\n"
+"표시되도록 합니다.\n"
"\n"
"ECHO OFF는 ECHO ON과 반대 효과가 있습니다(기본값은 ECHO OFF입니다).\n"
-"ECHO OFF 명령은 @ 부호처럼 처리 중 명령어가 표시되는 것을 막습니다\n"
-"(@ 부호가 첫번째 문자인 라인은 ECHO OFF인 효과가 있습니다).\n"
+"ECHO OFF 앞에 @ 기호룰 두어서 ECHO OFF 명령어 자체가 화면에\n"
+"표시되는 것을 막을 수 있습니다.\n"
+"\n"
#: programs/cmd/cmd.rc:78
msgid "ERASE <filename> deletes a file or set of files.\n"
-msgstr "ERASE <파일 이름>은 하나의 파일이냐 여러 파일을 지웁니다.\n"
+msgstr "ERASE <파일 이름>은 하나 이상의 파일을 지웁니다.\n"
#: programs/cmd/cmd.rc:85
msgid ""
@@ -12087,11 +12089,11 @@ msgid ""
"\n"
"The % sign must be doubled when using FOR in a batch file.\n"
msgstr ""
-"FOR는 파일 집합에 포함된 각각의 파일에 대해 명령어를 실행할 때 쓰입니다.\n"
+"FOR는 파일 모음에 포함된 각각의 파일에 대해 명령어를 실행할 때 쓰입니다.\n"
"\n"
-"사용법: FOR %변수 IN (set) DO 명령\n"
+"사용법: FOR %변수 IN (파일 모음) DO 명령\n"
"\n"
-"% 부호는 배치 파일 안에서 FOR를 사용할 때는 중첩(%%)되어야 합니다.\n"
+"배치 파일 안에서 FOR를 사용할 때는 '%변수' 대신 '%%변수'를 사용해야 합니다.\n"
#: programs/cmd/cmd.rc:97
msgid ""
@@ -12109,10 +12111,10 @@ msgstr ""
"GOTO 명령은 배치 파일 안에서 다른 구문으로 실행을\n"
"전환합니다.\n"
"\n"
-"GOTO의 타겟인 레이블은 255자까지 가능합니다만, 공백은 포함하지 않을 수도\n"
-"있습니다(운영체제에 따라서 다를 수도 있습니다).\n"
-"만약 배치 파일 안에 2개나 그 이상의 동일한 레이블이 존재할 경우 첫번째\n"
-"것이 실행됩니다. 파일에 없는 레이블로 GOTO를 시도한다면 배치파일 실행은\n"
+"GOTO의 타겟인 레이블은 255자까지 가능합니다. 단, 공백은 포함하지 않을\n"
+"수도 있습니다 (운영 체제에 따라서 다를 수도 있습니다). 만약 배치 파일\n"
+"안에 둘 이상의 동일한 레이블이 존재할 경우 항상 첫 번째 레이블이\n"
+"실행됩니다. GOTO를 시도하려는 레이블이 없다면 배치 파일 실행은\n"
"중단됩니다.\n"
"\n"
"GOTO는 대화식으로 사용할 경우 어떤 효과도 없습니다.\n"
@@ -12122,8 +12124,8 @@ msgid ""
"HELP <command> shows brief help details on a topic.\n"
"HELP without an argument shows all CMD built-in commands.\n"
msgstr ""
-"HELP <명령>은 주제의 간단한 도움말 정보를 보여줍니 다.\n"
-"아무 매개변수가 없는 HELP눈 CMD의 모든 내장 명령을 표시합니다.\n"
+"HELP <명령어>은 해당 명령어에 대한 간단한 도움말을 보여줍니다.\n"
+"매개 변수 없이 HELP를 실행하면 모든 CMD 내장 명령을 표시합니다.\n"
#: programs/cmd/cmd.rc:111
msgid ""
@@ -12136,14 +12138,14 @@ msgid ""
"In the second form of the command, string1 and string2 must be in double\n"
"quotes. The comparison is not case-sensitive.\n"
msgstr ""
-"IF는 명령을 선택적으로 실행 할 때 사용한다.\n"
+"IF는 명령을 조건부로 실행하는 데 사용됩니다.\n"
"\n"
-"문법: IF [NOT] EXIST 파일 이름 명령\n"
-" IF [NOT] string1==string2 명령\n"
-" IF [NOT] ERRORLEVEL 숫자 명령\n"
+"구문: IF [NOT] EXIST 파일_이름 명령어\n"
+" IF [NOT] 문자열1==문자열2 명령어\n"
+" IF [NOT] ERRORLEVEL 숫자 명령어\n"
"\n"
-"명령의 두번째 형식에서, string1과 string2는 반드시 2개의 따옴표로\n"
-"둘려놓아야 합니다.이 비교는 대소문자를 구분하지 않습니다.\n"
+"명령어의 두번째 형식에서, 문자열1과 문자열2는 반드시 2개의 따옴표로\n"
+"둘러싸야 합니다. 대소문자를 구분하지 않고 비교합니다.\n"
#: programs/cmd/cmd.rc:118
msgid ""
@@ -12162,11 +12164,11 @@ msgstr ""
#: programs/cmd/cmd.rc:121
msgid "MD <name> is the short version of MKDIR. It creates a subdirectory.\n"
msgstr ""
-"MD <아름> 운 MKDIR의 단축 버전입니다. 이것은 하위 디렉터리를 만듭니다 .\n"
+"MD <이름>은 MKDIR의 단축 버전입니다. 서브디렉터리를 만듭니다.\n"
#: programs/cmd/cmd.rc:123
msgid "MKDIR <name> creates a subdirectory.\n"
-msgstr "MKDIR <명령> 운 하위 디렉터리를 만듭니다.\n"
+msgstr "MKDIR <이름>은 서브디렉터리를 만듭니다.\n"
#: programs/cmd/cmd.rc:131
msgid ""
@@ -12182,8 +12184,7 @@ msgstr ""
"만약 옮겨지는 항목이 하나의 디렉터리라면 디렉터리 아래 모든 파일과\n"
"서브디렉터리도 이동합니다.\n"
"\n"
-"MOVE는 원본과 대상의 위치가 다른 DOS 드라이브 문자를 가지고 있다면 실패합니"
-"다.\n"
+"MOVE는 원본과 대상이 다른 DOS 드라이브에 위치하면 실패합니다.\n"
#: programs/cmd/cmd.rc:142
msgid ""
@@ -12271,21 +12272,19 @@ msgstr ""
#: programs/cmd/cmd.rc:176
msgid "REN <filename> is the short version of RENAME. It renames a file.\n"
-msgstr ""
-"REN <파일 이름> 은 REANME의 단축 버전입니다.이것은 파일 이름을 바꿉니다.\n"
+msgstr "REN <파일 이름>은 REANME의 단축 버전입니다. 파일 이름을 바꿉니다.\n"
#: programs/cmd/cmd.rc:178
msgid "RENAME <filename> renames a file.\n"
-msgstr "RENAME <파일 이름> 은 파일의 이름을 바꿈.\n"
+msgstr "RENAME <파일 이름>은 파일 이름을 바꿈니다.\n"
#: programs/cmd/cmd.rc:181
msgid "RD <directory> is the short version of RMDIR. It deletes a directory.\n"
-msgstr ""
-"RD <디렉터리> 는 RMDIR의 단축 버전입니다. 이것은 디렉터리를 제거합니다.\n"
+msgstr "RD <디렉터리>는 RMDIR의 단축 버전입니다. 디렉터리를 지웁니다.\n"
#: programs/cmd/cmd.rc:183
msgid "RMDIR <directory> deletes a directory.\n"
-msgstr "RMDIR <디렉터리>는 디렉터리를 제거합니다.\n"
+msgstr "RMDIR <디렉터리>는 디렉터리를 지웁니다.\n"
#: programs/cmd/cmd.rc:229
msgid ""
@@ -12309,7 +12308,7 @@ msgstr ""
"\n"
"매개변수가 없는 SET은 현재 환경변수를 모두 표시합니다.\n"
"\n"
-"환경 변수를 만들거나 수정할 때 사용하는 문법:\n"
+"환경 변수를 만들거나 수정할 때 사용하는 구문:\n"
"\n"
"SET <변수>=<값>\n"
"\n"
@@ -12364,8 +12363,8 @@ msgstr ""
"프로그램을 시작하거나, 파일 확장자와 연관된 프로그램으로\n"
"문서를 엽니다.\n"
"사용법:\n"
-"start [옵션] 프로그램_파일 이름 [...]\n"
-"start [옵션] 문서_파일 이름\n"
+"start [옵션] 프로그램_파일_이름 [...]\n"
+"start [옵션] 문서_파일_이름\n"
"\n"
"옵션:\n"
"\"제목\" 자식 창 표시줄에 나타날 제목을 지정합니다.\n"
@@ -12382,8 +12381,8 @@ msgstr ""
"/belownormal 프로그램을 BELOWNORMAL 우선 순위 클래스에서 시작합니다.\n"
"/node n 지정한 NUMA 노드에서 프로그램을 시작합니다.\n"
"/affinity mask 지정한 프로세서 친화도 마스크에서 프로그램을 시작합니다.\n"
-"/wait 시작한 프로그램이 끝날 때까지 기다립니다.\n"
-" 이 명령의 반환값은 실행했던 프로그램의 반환 코드입니다.\n"
+"/wait 시작한 프로그램이 끝날 때까지 기다립니다. 이 명령의 반환값은\n"
+" 실행했던 프로그램의 반환 코드입니다.\n"
"/unix 유닉스 파일 이름을 사용하고, Windows 탐색기처럼 파일을\n"
" 시작합니다.\n"
"/ProgIDOpen 지정한 progID를 사용해서 문서를 엽니다.\n"
@@ -12391,19 +12390,21 @@ msgstr ""
#: programs/cmd/cmd.rc:237
msgid "TIME sets or shows the current system time.\n"
-msgstr "TIME - 현재 시스템 시간을 보여 줍니다.\n"
+msgstr "TIME - 현재 시스템 시간을 설정하거나 보여줍니다.\n"
#: programs/cmd/cmd.rc:240
msgid "TITLE <string> sets the window title for the cmd window.\n"
-msgstr "TITLE <문자열> - cmd 창의 창 제목을 설정합니다.\n"
+msgstr ""
+"TITLE <문자열>은 CMD 창의 창 제목을 설정합니다.\n"
#: programs/cmd/cmd.rc:244
msgid ""
"TYPE <filename> copies <filename> to the console device (or elsewhere if\n"
"redirected). No check is made that the file is readable text.\n"
msgstr ""
-"TYPE <filename> <filename>을 콘솔 장치로 복사합니다(또는 어디에나\n"
-"다이렉트). 파일이 읽기 가능한 텍스트인지 체크하지 않습니다.\n"
+"TYPE <파일 이름>은 <파일 이름>을 콘솔 장치( 또는 방향 전환된 어딘가)로 복사합니"
+"다.\n"
+"파일 내용이 읽기 가능한 텍스트인지는 체크하지 않습니다.\n"
#: programs/cmd/cmd.rc:253
msgid ""
@@ -12415,14 +12416,13 @@ msgid ""
"\n"
"The verify flag has no function in Wine.\n"
msgstr ""
-"VERIFY는 검증 플래그를 설정하고 제거하거나 테스트하는데 사용됩니다. 올바른 형"
-"식은:\n"
+"VERIFY는 검증 플래그의 설정, 제거 및 테스트 용도로 사용됩니다.\n"
"\n"
"VERIFY ON\t플래그 설정.\n"
"VERIFY OFF\t플래그 제거.\n"
-"VERIFY\t\tON 이나 OFF 같이 적절하게 보여줌.\n"
+"VERIFY\t\t현재 플래그 상태를 표시합니다.\n"
"\n"
-"이 검증 플래그는 Wine에서는 아무 기능을 안함.\n"
+"이 검증 플래그는 Wine에서는 아무 기능도 하지 않습니다.\n"
#: programs/cmd/cmd.rc:256
msgid "VER displays the version of cmd you are running.\n"
@@ -12994,7 +12994,7 @@ msgstr "DirectX 진단 도구"
#: programs/dxdiag/dxdiag.rc:31
msgid "Usage: dxdiag [/whql:off | /whql:on] [/t filename | /x filename]"
-msgstr "사용법: dxdiag [/whql:off | /whql:on] [/t 파일 이름 | /x 파일 이름]"
+msgstr "사용법: dxdiag [/whql:off | /whql:on] [/t 파일_이름 | /x 파일_이름]"
#: programs/explorer/explorer.rc:31
msgid "Wine Explorer"
@@ -13133,13 +13133,13 @@ msgid ""
"\n"
"Where 'command' is one of HELP, START, STOP or USE.\n"
msgstr ""
-"이 명령어의 문법은:\n"
+"구문:\n"
"\n"
"NET 명령어[매개변수]\n"
-" -나-\n"
+"\n"
"NET 명령어 /HELP\n"
"\n"
-"명령어에 들어갈 수 있는 것은 HELP, START, STOP이나 USE중의 하나임.\n"
+"<명령어>는 HELP, START, STOP, USE 중 하나입니다.\n"
#: programs/net/net.rc:31
msgid ""
@@ -13150,12 +13150,12 @@ msgid ""
"Displays the list of running services if 'service' is omitted. Otherwise "
"'service' is the name of the service to start.\n"
msgstr ""
-"명령어의 문법:\n"
+"구문:\n"
"\n"
"NET START [서비스]\n"
"\n"
-"'서비스'가 생략하는 경우 실행 중인 서비스 목록을 표시합니다. 그렇지 않으면 "
-"'서비스'는 시작할 서비스의 이름입니다.\n"
+"<서비스>를 생략하면 실행 중인 서비스 목록을 표시합니다."
+"<서비스>는 시작하려는 서비스 이름입니다.\n"
#: programs/net/net.rc:32
msgid ""
@@ -13165,23 +13165,23 @@ msgid ""
"\n"
"Where 'service' is the name of the service to stop.\n"
msgstr ""
-"명령어의 문법:\n"
+"구문:\n"
"\n"
"NET STOP 서비스\n"
"\n"
-"'서비스'는 정지할 서비스의 이름입니다.\n"
+"<서비스>는 중지하려는 서비스 이름입니다.\n"
#: programs/net/net.rc:33
msgid "Stopping dependent service: %1\n"
-msgstr "종속된 서비스 중지 중: %1\n"
+msgstr "종속 서비스를 중지하고 있습니다: %1\n"
#: programs/net/net.rc:34
msgid "Could not stop service %1\n"
-msgstr "%1 서비스를 중지할 수 없음\n"
+msgstr "%1 서비스를 중지하지 못했습니다\n"
#: programs/net/net.rc:35
msgid "Could not get handle to service control manager.\n"
-msgstr "서비스 제어 관리자를 다룰 수 없습니다.\n"
+msgstr "서비스 제어 관리자 핸들을 얻을 수 없습니다.\n"
#: programs/net/net.rc:36
msgid "Could not get handle to service.\n"
@@ -13189,31 +13189,31 @@ msgstr "서비스 핸들을 얻을 수 없습니다.\n"
#: programs/net/net.rc:37
msgid "The %1 service is starting.\n"
-msgstr "%1 서비스는 시작중입니다.\n"
+msgstr "%1 서비스를 시작하고 있습니다.\n"
#: programs/net/net.rc:38
msgid "The %1 service was started successfully.\n"
-msgstr "%1 서비스 시작 성공했습니다.\n"
+msgstr "%1 서비스를 시작했습니다.\n"
#: programs/net/net.rc:39
msgid "The %1 service failed to start.\n"
-msgstr "%1 서비스 시작 실패했습니다.\n"
+msgstr "%1 서비스를 시작하지 못했습니다.\n"
#: programs/net/net.rc:40
msgid "The %1 service is stopping.\n"
-msgstr "%1 서비스는 정지하는 중입니다.\n"
+msgstr "%1 서비스를 중지하고 있습니다.\n"
#: programs/net/net.rc:41
msgid "The %1 service was stopped successfully.\n"
-msgstr "%1 서비스 정지 성공했습니다.\n"
+msgstr "%1 서비스를 중지했습니다.\n"
#: programs/net/net.rc:42
msgid "The %1 service failed to stop.\n"
-msgstr "%1 서비스 정지 실패했습니다.\n"
+msgstr "%1 서비스를 중지하지 못했습니다.\n"
#: programs/net/net.rc:44
msgid "There are no entries in the list.\n"
-msgstr "리스트가 비어 있습니다.\n"
+msgstr "목록에 항목이 없습니다.\n"
#: programs/net/net.rc:45
msgid ""
@@ -13222,7 +13222,7 @@ msgid ""
"---------------------------------------------------------------\n"
msgstr ""
"\n"
-"상태 로컬 원격\n"
+"상태 로컬 원격\n"
"---------------------------------------------------------------\n"
#: programs/net/net.rc:46
@@ -13231,35 +13231,35 @@ msgstr "%1 %2 %3 열린 리소스: %4!u!\n"
#: programs/net/net.rc:48
msgid "Paused"
-msgstr "정지됨"
+msgstr "일지 중지"
#: programs/net/net.rc:49
msgid "Disconnected"
-msgstr "연결이 끊어짐"
+msgstr "연결 끊김"
#: programs/net/net.rc:50
msgid "A network error occurred"
-msgstr "네트워크 오류가 발생함"
+msgstr "네트워크 오류 발생"
#: programs/net/net.rc:51
msgid "Connection is being made"
-msgstr "연결이 만들어짐"
+msgstr "연결 중"
#: programs/net/net.rc:52
msgid "Reconnecting"
-msgstr "다시 연결중"
+msgstr "다시 연결 중"
#: programs/net/net.rc:43
msgid "The following services are running:\n"
-msgstr "다음 서비스가 실행중임:\n"
+msgstr "실행 중인 서비스:\n"
#: programs/netstat/netstat.rc:30
msgid "Active Connections"
-msgstr "활성화된 연결"
+msgstr "활성 연결"
#: programs/netstat/netstat.rc:31
msgid "Proto"
-msgstr "프로토"
+msgstr "프로토콜"
#: programs/netstat/netstat.rc:32
msgid "Local Address"
@@ -13283,7 +13283,7 @@ msgstr "보냄"
#: programs/netstat/netstat.rc:37
msgid "Received"
-msgstr "응답받음"
+msgstr "받음"
#: programs/netstat/netstat.rc:38
msgid "Bytes"
@@ -13295,11 +13295,11 @@ msgstr "유니캐스트 패킷"
#: programs/netstat/netstat.rc:40
msgid "Non-unicast packets"
-msgstr "유니캐스트가 아닌 패킷"
+msgstr "비유니캐스트 패킷"
#: programs/netstat/netstat.rc:41
msgid "Discards"
-msgstr "폐기"
+msgstr "버림"
#: programs/netstat/netstat.rc:42
msgid "Errors"
@@ -13311,23 +13311,23 @@ msgstr "알 수 없는 프로토콜"
#: programs/netstat/netstat.rc:44
msgid "TCP Statistics for IPv4"
-msgstr "IPv4의 TCP 상태"
+msgstr "IPv4 TCP 통계"
#: programs/netstat/netstat.rc:45
msgid "Active Opens"
-msgstr "활성화된 열림"
+msgstr "활성 열기"
#: programs/netstat/netstat.rc:46
msgid "Passive Opens"
-msgstr "수동적인 열림"
+msgstr "수동 열기"
#: programs/netstat/netstat.rc:47
msgid "Failed Connection Attempts"
-msgstr "연결 시도 실패"
+msgstr "실패한 연결 시도"
#: programs/netstat/netstat.rc:48
msgid "Reset Connections"
-msgstr "연결 재설정"
+msgstr "재설정된 연결"
#: programs/netstat/netstat.rc:49
msgid "Current Connections"
@@ -13335,35 +13335,35 @@ msgstr "현재 연결"
#: programs/netstat/netstat.rc:50
msgid "Segments Received"
-msgstr "세그멘트가 응답함"
+msgstr "받은 세그멘트"
#: programs/netstat/netstat.rc:51
msgid "Segments Sent"
-msgstr "세그멘트가 보내짐"
+msgstr "보낸 세그멘트"
#: programs/netstat/netstat.rc:52
msgid "Segments Retransmitted"
-msgstr "세그멘트가 다시 보내짐"
+msgstr "재전송된 세그멘트"
#: programs/netstat/netstat.rc:53
msgid "UDP Statistics for IPv4"
-msgstr "IPv4의 UDP 상태"
+msgstr "IPv4 UDP 통계"
#: programs/netstat/netstat.rc:54
msgid "Datagrams Received"
-msgstr "데이터그램을 받음"
+msgstr "받은 데이터그램"
#: programs/netstat/netstat.rc:55
msgid "No Ports"
-msgstr "포트가 없음"
+msgstr "포트 없음"
#: programs/netstat/netstat.rc:56
msgid "Receive Errors"
-msgstr "받는 중에 오류 발생"
+msgstr "받기 오류"
#: programs/netstat/netstat.rc:57
msgid "Datagrams Sent"
-msgstr "데이터그램을 보냄"
+msgstr "보낸 데이터그램"
#: programs/notepad/notepad.rc:30
msgid "&New\tCtrl+N"
@@ -14167,7 +14167,7 @@ msgid ""
" REG [operation] /?\n"
"\n"
msgstr ""
-"문법:\n"
+"구문:\n"
" REG [명령] [매개변수]\n"
"\n"
"지원하는 명령:\n"
@@ -15058,11 +15058,11 @@ msgstr "오류: \"%1\" 프로세스를 중단시킬 수 없습니다.\n"
#: programs/taskkill/taskkill.rc:43
msgid "Error: Process self-termination is not permitted.\n"
-msgstr "오류: 프로세스 자가 종료는 허용되지 않습니다.\n"
+msgstr "오류: 프로세스 자체 종료는 허용되지 않습니다.\n"
#: programs/taskmgr/taskmgr.rc:37 programs/taskmgr/taskmgr.rc:108
msgid "&New Task (Run...)"
-msgstr "새 작업(실행...)(&N)"
+msgstr "새 작업 (실행...)(&N)"
#: programs/taskmgr/taskmgr.rc:39
msgid "E&xit Task Manager"
@@ -15295,7 +15295,7 @@ msgstr "프로세서 선호도"
msgid ""
"The Processor Affinity setting controls which CPUs the process will be "
"allowed to execute on."
-msgstr "프로세서 선호도 설정은 어떤 CPU가 프로세스를 실행시킬 지를 제어한다."
+msgstr "프로세서 선호도 설정은 프로세스가 실행될 수 있는 CPU를 지정합니다."
#: programs/taskmgr/taskmgr.rc:446
msgid "CPU 0"
--
2.30.0
1
0