Wine-Devel
Threads by month
- ----- 2026 -----
- June
- May
- April
- March
- February
- January
- ----- 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
- 4 participants
- 84544 discussions
[PATCH vkd3d v2 1/5] vkd3d: Use device descriptor limits when creating descriptor pools.
by Conor McCarthy March 15, 2022
by Conor McCarthy March 15, 2022
March 15, 2022
Signed-off-by: Conor McCarthy <cmccarthy(a)codeweavers.com>
---
libs/vkd3d/command.c | 13 ++-----------
libs/vkd3d/device.c | 36 ++++++++++++++++++++++++++++++++++++
libs/vkd3d/vkd3d_private.h | 20 ++++++++++++++++++++
3 files changed, 58 insertions(+), 11 deletions(-)
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c
index 61e18105..e7375fb8 100644
--- a/libs/vkd3d/command.c
+++ b/libs/vkd3d/command.c
@@ -1351,15 +1351,6 @@ static bool d3d12_command_allocator_add_transfer_buffer(struct d3d12_command_all
static VkDescriptorPool d3d12_command_allocator_allocate_descriptor_pool(
struct d3d12_command_allocator *allocator)
{
- static const VkDescriptorPoolSize pool_sizes[] =
- {
- {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1024},
- {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1024},
- {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1024},
- {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1024},
- {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1024},
- {VK_DESCRIPTOR_TYPE_SAMPLER, 1024},
- };
struct d3d12_device *device = allocator->device;
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
struct VkDescriptorPoolCreateInfo pool_desc;
@@ -1379,8 +1370,8 @@ static VkDescriptorPool d3d12_command_allocator_allocate_descriptor_pool(
pool_desc.pNext = NULL;
pool_desc.flags = 0;
pool_desc.maxSets = 512;
- pool_desc.poolSizeCount = ARRAY_SIZE(pool_sizes);
- pool_desc.pPoolSizes = pool_sizes;
+ pool_desc.poolSizeCount = ARRAY_SIZE(device->vk_pool_sizes);
+ pool_desc.pPoolSizes = device->vk_pool_sizes;
if ((vr = VK_CALL(vkCreateDescriptorPool(vk_device, &pool_desc, NULL, &vk_pool))) < 0)
{
ERR("Failed to create descriptor pool, vr %d.\n", vr);
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index 3360fd6e..59fa9af9 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -1277,6 +1277,16 @@ static void vkd3d_init_feature_level(struct vkd3d_vulkan_info *vk_info,
TRACE("Max feature level: %#x.\n", vk_info->max_feature_level);
}
+static void vkd3d_device_descriptor_limits_init(struct vkd3d_device_descriptor_limits *limits,
+ const VkPhysicalDeviceLimits *device_limits)
+{
+ limits->uniform_buffer_max_descriptors = device_limits->maxDescriptorSetUniformBuffers;
+ limits->sampled_image_max_descriptors = device_limits->maxDescriptorSetSampledImages;
+ limits->storage_buffer_max_descriptors = device_limits->maxDescriptorSetStorageBuffers;
+ limits->storage_image_max_descriptors = device_limits->maxDescriptorSetStorageImages;
+ limits->sampler_max_descriptors = min(device_limits->maxDescriptorSetSamplers, VKD3D_MAX_DESCRIPTOR_SET_SAMPLERS);
+}
+
static HRESULT vkd3d_init_device_caps(struct d3d12_device *device,
const struct vkd3d_device_create_info *create_info,
struct vkd3d_physical_device_info *physical_device_info,
@@ -1504,6 +1514,9 @@ static HRESULT vkd3d_init_device_caps(struct d3d12_device *device,
features->robustBufferAccess = VK_FALSE;
}
+ vkd3d_device_descriptor_limits_init(&vulkan_info->descriptor_limits,
+ &physical_device_info->properties2.properties.limits);
+
return S_OK;
}
@@ -2419,6 +2432,27 @@ static void vkd3d_time_domains_init(struct d3d12_device *device)
WARN("Found no acceptable host time domain. Calibrated timestamps will not be available.\n");
}
+static void vkd3d_init_descriptor_pool_sizes(VkDescriptorPoolSize *pool_sizes,
+ const struct vkd3d_device_descriptor_limits *limits)
+{
+ pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ pool_sizes[0].descriptorCount = min(limits->uniform_buffer_max_descriptors,
+ VKD3D_MAX_VIRTUAL_HEAP_DESCRIPTORS_PER_TYPE);
+ pool_sizes[1].type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
+ pool_sizes[1].descriptorCount = min(limits->sampled_image_max_descriptors,
+ VKD3D_MAX_VIRTUAL_HEAP_DESCRIPTORS_PER_TYPE);
+ pool_sizes[2].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
+ pool_sizes[2].descriptorCount = pool_sizes[1].descriptorCount;
+ pool_sizes[3].type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
+ pool_sizes[3].descriptorCount = min(limits->storage_image_max_descriptors,
+ VKD3D_MAX_VIRTUAL_HEAP_DESCRIPTORS_PER_TYPE);
+ pool_sizes[4].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
+ pool_sizes[4].descriptorCount = pool_sizes[3].descriptorCount;
+ pool_sizes[5].type = VK_DESCRIPTOR_TYPE_SAMPLER;
+ pool_sizes[5].descriptorCount = min(limits->sampler_max_descriptors,
+ VKD3D_MAX_VIRTUAL_HEAP_DESCRIPTORS_PER_TYPE);
+};
+
/* ID3D12Device */
static inline struct d3d12_device *impl_from_ID3D12Device(ID3D12Device *iface)
{
@@ -3979,6 +4013,8 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
for (i = 0; i < ARRAY_SIZE(device->desc_mutex); ++i)
vkd3d_mutex_init(&device->desc_mutex[i]);
+ vkd3d_init_descriptor_pool_sizes(device->vk_pool_sizes, &device->vk_info.descriptor_limits);
+
if ((device->parent = create_info->parent))
IUnknown_AddRef(device->parent);
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index 67989c11..ca7a3f22 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -62,6 +62,12 @@
#define VKD3D_MAX_SHADER_STAGES 5u
#define VKD3D_MAX_VK_SYNC_OBJECTS 4u
#define VKD3D_MAX_DESCRIPTOR_SETS 64u
+/* D3D12 binding tier 3 has a limit of 2048 samplers. */
+#define VKD3D_MAX_DESCRIPTOR_SET_SAMPLERS 2048u
+/* The main limitation here is the simple descriptor pool recycling scheme
+ * requiring each pool to contain all descriptor types used by vkd3d. Limit
+ * this number to prevent excessive pool memory use. */
+#define VKD3D_MAX_VIRTUAL_HEAP_DESCRIPTORS_PER_TYPE (16 * 1024u)
struct d3d12_command_list;
struct d3d12_device;
@@ -95,6 +101,15 @@ HRESULT hresult_from_errno(int rc);
HRESULT hresult_from_vk_result(VkResult vr);
HRESULT hresult_from_vkd3d_result(int vkd3d_result);
+struct vkd3d_device_descriptor_limits
+{
+ unsigned int uniform_buffer_max_descriptors;
+ unsigned int sampled_image_max_descriptors;
+ unsigned int storage_buffer_max_descriptors;
+ unsigned int storage_image_max_descriptors;
+ unsigned int sampler_max_descriptors;
+};
+
struct vkd3d_vulkan_info
{
/* KHR instance extensions */
@@ -130,6 +145,7 @@ struct vkd3d_vulkan_info
VkPhysicalDeviceLimits device_limits;
VkPhysicalDeviceSparseProperties sparse_properties;
+ struct vkd3d_device_descriptor_limits descriptor_limits;
VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT texel_buffer_alignment_properties;
@@ -1299,6 +1315,8 @@ struct vkd3d_uav_clear_state
HRESULT vkd3d_uav_clear_state_init(struct vkd3d_uav_clear_state *state, struct d3d12_device *device);
void vkd3d_uav_clear_state_cleanup(struct vkd3d_uav_clear_state *state, struct d3d12_device *device);
+#define VKD3D_DESCRIPTOR_POOL_COUNT 6
+
/* ID3D12Device */
struct d3d12_device
{
@@ -1352,6 +1370,8 @@ struct d3d12_device
const struct vkd3d_format_compatibility_list *format_compatibility_lists;
struct vkd3d_null_resources null_resources;
struct vkd3d_uav_clear_state uav_clear_state;
+
+ VkDescriptorPoolSize vk_pool_sizes[VKD3D_DESCRIPTOR_POOL_COUNT];
};
HRESULT d3d12_device_create(struct vkd3d_instance *instance,
--
2.34.1
4
12
March 15, 2022
Dear Sir / Madam,
I hope this email finds you well. My name is Hui Xiang, and I am an Electrical and Electronic Engineering student at the University of Manchester. I would like to participate in Google Summer of Code this summer. After doing research on previous programs, I was impressed by The Wine Project. I am writing this email to ask if Wine will participate in GSoC in 2022.
I love Wine’s idea of running Windows apps on other operating systems while keeping the applications running efficiently with the CPU and memory. On Windows, there are a plethora of fantastic apps, such as Solidworks and AutoCAD. This project enables users to take advantage of both the applications and the operating systems through running these apps on diverse operating systems.
I would appreciate the opportunity to make contributions to this project if Wine will participate GSoC in 2022. Thank you for your time. It would give me great pleasure to hear back from you.
Best Regards,
Hui
4
4
[PATCH vkd3d v6 5/8] vkd3d-shader/hlsl: Properly free parse_variable_def memory.
by Francisco Casas March 15, 2022
by Francisco Casas March 15, 2022
March 15, 2022
Signed-off-by: Francisco Casas <fcasas(a)codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
v6:
- Using 'continue' instead of 'return false' when iterating lists of
variable definitions to correctly free the following fields.
By the way, maybe we should also make hlsl_new_array_type() free the
memory of the basic_type argument on failure.
Also we are assuming that hlsl_new_array_type() can't fail in some
parts of the code that call it.
However, I suggest fixing that in the future, to avoid drowning in a
glass of water now.
Signed-off-by: Francisco Casas <fcasas(a)codeweavers.com>
---
libs/vkd3d-shader/hlsl.y | 42 +++++++++++++++++++++++++++-------------
1 file changed, 29 insertions(+), 13 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y
index 016f1001..477185f3 100644
--- a/libs/vkd3d-shader/hlsl.y
+++ b/libs/vkd3d-shader/hlsl.y
@@ -668,6 +668,15 @@ static struct hlsl_type *apply_type_modifiers(struct hlsl_ctx *ctx, struct hlsl_
return new_type;
}
+static void free_parse_variable_def(struct parse_variable_def *v)
+{
+ free_parse_initializer(&v->initializer);
+ vkd3d_free(v->arrays.sizes);
+ vkd3d_free(v->name);
+ vkd3d_free((void *)v->semantic.name);
+ vkd3d_free(v);
+}
+
static struct list *gen_struct_fields(struct hlsl_ctx *ctx, struct hlsl_type *type, struct list *fields)
{
struct parse_variable_def *v, *v_next;
@@ -685,13 +694,14 @@ static struct list *gen_struct_fields(struct hlsl_ctx *ctx, struct hlsl_type *ty
if (!(field = hlsl_alloc(ctx, sizeof(*field))))
{
- vkd3d_free(v);
- return list;
+ free_parse_variable_def(v);
+ continue;
}
field->type = type;
for (i = 0; i < v->arrays.count; ++i)
field->type = hlsl_new_array_type(ctx, field->type, v->arrays.sizes[i]);
+ vkd3d_free(v->arrays.sizes);
field->loc = v->loc;
field->name = v->name;
field->semantic = v->semantic;
@@ -719,18 +729,29 @@ static bool add_typedef(struct hlsl_ctx *ctx, DWORD modifiers, struct hlsl_type
if (!v->arrays.count)
{
if (!(type = hlsl_type_clone(ctx, orig_type, 0, modifiers)))
- return false;
+ {
+ free_parse_variable_def(v);
+ continue;
+ }
}
else
{
type = orig_type;
}
+ ret = true;
for (i = 0; i < v->arrays.count; ++i)
{
if (!(type = hlsl_new_array_type(ctx, type, v->arrays.sizes[i])))
- return false;
+ {
+ free_parse_variable_def(v);
+ ret = false;
+ break;
+ }
}
+ if (!ret)
+ continue;
+ vkd3d_free(v->arrays.sizes);
vkd3d_free((void *)type->name);
type->name = v->name;
@@ -747,6 +768,7 @@ static bool add_typedef(struct hlsl_ctx *ctx, DWORD modifiers, struct hlsl_type
if (!ret)
hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_REDEFINED,
"Type '%s' is already defined.", v->name);
+ free_parse_initializer(&v->initializer);
vkd3d_free(v);
}
vkd3d_free(list);
@@ -1470,15 +1492,6 @@ static void struct_var_initializer(struct hlsl_ctx *ctx, struct list *list, stru
vkd3d_free(initializer->args);
}
-static void free_parse_variable_def(struct parse_variable_def *v)
-{
- free_parse_initializer(&v->initializer);
- vkd3d_free(v->arrays.sizes);
- vkd3d_free(v->name);
- vkd3d_free((void *)v->semantic.name);
- vkd3d_free(v);
-}
-
static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_type,
DWORD modifiers, struct list *var_list)
{
@@ -1510,6 +1523,7 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t
type = basic_type;
for (i = 0; i < v->arrays.count; ++i)
type = hlsl_new_array_type(ctx, type, v->arrays.sizes[i]);
+ vkd3d_free(v->arrays.sizes);
if (type->type != HLSL_CLASS_MATRIX)
check_invalid_matrix_modifiers(ctx, modifiers, v->loc);
@@ -1569,6 +1583,7 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t
hlsl_error(ctx, &v->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_INITIALIZER,
"Const variable \"%s\" is missing an initializer.", var->name);
hlsl_free_var(var);
+ free_parse_initializer(&v->initializer);
vkd3d_free(v);
continue;
}
@@ -1581,6 +1596,7 @@ static struct list *declare_vars(struct hlsl_ctx *ctx, struct hlsl_type *basic_t
"Variable \"%s\" was already declared in this scope.", var->name);
hlsl_note(ctx, &old->loc, VKD3D_SHADER_LOG_ERROR, "\"%s\" was previously declared here.", old->name);
hlsl_free_var(var);
+ free_parse_initializer(&v->initializer);
vkd3d_free(v);
continue;
}
--
2.25.1
3
2
[PATCH v4 1/3] winegstreamer: Implement WMA decoder Process(Input|Output) error checks.
by Rémi Bernon March 15, 2022
by Rémi Bernon March 15, 2022
March 15, 2022
Checking that WMA decoder ignores any incorrectly sized input sample.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51931
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52391
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
v4: * Rebase to fix the H264 decoder conflict in PATCH 2,
* Kept the signoffs.
dlls/mf/tests/mf.c | 23 +++++++++++++---------
dlls/winegstreamer/wma_decoder.c | 33 ++++++++++++++++++++++++++++++++
2 files changed, 47 insertions(+), 9 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 880fbc9fc3f..de72ad5a6e7 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -6035,6 +6035,7 @@ static void test_wma_decoder(void)
MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8};
MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_Float};
MFT_OUTPUT_STREAM_INFO output_info;
+ MFT_OUTPUT_DATA_BUFFER outputs[2];
MFT_INPUT_STREAM_INFO input_info;
MFT_OUTPUT_DATA_BUFFER output;
const BYTE *wma_encoded_data;
@@ -6212,7 +6213,7 @@ static void test_wma_decoder(void)
ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
ret = IMFSample_Release(sample);
ok(ret == 0, "Release returned %lu\n", ret);
- sample = create_sample(wma_encoded_data + wma_block_size, wma_block_size - wma_block_size / 2);
+ sample = create_sample(wma_encoded_data, wma_block_size + 1);
hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
todo_wine
ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
@@ -6235,16 +6236,13 @@ static void test_wma_decoder(void)
status = 0xdeadbeef;
memset(&output, 0, sizeof(output));
hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
- todo_wine
ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
ok(!output.pSample, "got pSample %p\n", output.pSample);
- todo_wine
ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE ||
broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
"got dwStatus %#lx\n", output.dwStatus);
ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
- todo_wine
ok(status == 0, "got status %#lx\n", status);
sample = create_sample(wma_encoded_data, wma_block_size);
@@ -6257,16 +6255,25 @@ static void test_wma_decoder(void)
status = 0xdeadbeef;
memset(&output, 0, sizeof(output));
hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
- todo_wine
ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
ok(!output.pSample, "got pSample %p\n", output.pSample);
- todo_wine
ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE ||
broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
"got dwStatus %#lx\n", output.dwStatus);
- todo_wine
ok(status == 0, "got status %#lx\n", status);
+ status = 0xdeadbeef;
+ memset(&output, 0, sizeof(output));
+ output_info.cbSize = sizeof(wma_decoded_data);
+ sample = create_sample(NULL, output_info.cbSize);
+ outputs[0].pSample = sample;
+ sample = create_sample(NULL, output_info.cbSize);
+ outputs[1].pSample = sample;
+ hr = IMFTransform_ProcessOutput(transform, 0, 2, outputs, &status);
+ ok(hr == E_INVALIDARG, "ProcessOutput returned %#lx\n", hr);
+ IMFSample_Release(outputs[0].pSample);
+ IMFSample_Release(outputs[1].pSample);
+
i = 1;
status = 0xdeadbeef;
output_info.cbSize = sizeof(wma_decoded_data);
@@ -6337,7 +6344,6 @@ static void test_wma_decoder(void)
ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
ok(output.pSample == sample, "got pSample %p\n", output.pSample);
ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
- todo_wine
ok(status == 0, "got status %#lx\n", status);
ret = IMFSample_Release(sample);
ok(ret == 0, "Release returned %lu\n", ret);
@@ -6353,7 +6359,6 @@ static void test_wma_decoder(void)
ok(output.dwStatus == 0 ||
broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)) /* Win7 */,
"got dwStatus %#lx\n", output.dwStatus);
- todo_wine
ok(status == 0, "got status %#lx\n", status);
check_sample(sample, NULL, 0, NULL);
ret = IMFSample_Release(sample);
diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c
index 6c198706944..a35da1cdc70 100644
--- a/dlls/winegstreamer/wma_decoder.c
+++ b/dlls/winegstreamer/wma_decoder.c
@@ -520,14 +520,47 @@ static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_
static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
{
+ struct wma_decoder *decoder = impl_from_IMFTransform(iface);
+ MFT_INPUT_STREAM_INFO info;
+ HRESULT hr;
+
FIXME("iface %p, id %lu, sample %p, flags %#lx stub!\n", iface, id, sample, flags);
+
+ if (!decoder->wg_transform)
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
+
+ if (FAILED(hr = IMFTransform_GetInputStreamInfo(iface, 0, &info)))
+ return hr;
+
return E_NOTIMPL;
}
static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,
MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status)
{
+ struct wma_decoder *decoder = impl_from_IMFTransform(iface);
+ MFT_OUTPUT_STREAM_INFO info;
+ HRESULT hr;
+
FIXME("iface %p, flags %#lx, count %lu, samples %p, status %p stub!\n", iface, flags, count, samples, status);
+
+ if (count > 1)
+ return E_INVALIDARG;
+
+ if (!decoder->wg_transform)
+ return MF_E_TRANSFORM_TYPE_NOT_SET;
+
+ if (FAILED(hr = IMFTransform_GetOutputStreamInfo(iface, 0, &info)))
+ return hr;
+
+ *status = 0;
+ samples[0].dwStatus = 0;
+ if (!samples[0].pSample)
+ {
+ samples[0].dwStatus = MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE;
+ return MF_E_TRANSFORM_NEED_MORE_INPUT;
+ }
+
return E_NOTIMPL;
}
--
2.35.1
2
3
March 15, 2022
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winealsa.drv/alsa.c | 181 ++++++++++++++++++++++++++++++++++-
dlls/winealsa.drv/mmdevdrv.c | 177 ++++------------------------------
dlls/winealsa.drv/unixlib.h | 13 +++
3 files changed, 213 insertions(+), 158 deletions(-)
diff --git a/dlls/winealsa.drv/alsa.c b/dlls/winealsa.drv/alsa.c
index c199a2e603d..085066622c0 100644
--- a/dlls/winealsa.drv/alsa.c
+++ b/dlls/winealsa.drv/alsa.c
@@ -34,13 +34,13 @@
#include "windef.h"
#include "winbase.h"
#include "winternl.h"
+#include "initguid.h"
#include "mmdeviceapi.h"
#include "wine/debug.h"
#include "wine/list.h"
#include "wine/unixlib.h"
-#include "initguid.h"
#include "unixlib.h"
WINE_DEFAULT_DEBUG_CHANNEL(alsa);
@@ -2241,6 +2241,184 @@ static NTSTATUS is_started(void *args)
return alsa_unlock_result(stream, ¶ms->result, stream->started ? S_OK : S_FALSE);
}
+static unsigned int alsa_probe_num_speakers(char *name)
+{
+ snd_pcm_t *handle;
+ snd_pcm_hw_params_t *params;
+ int err;
+ unsigned int max_channels = 0;
+
+ if ((err = snd_pcm_open(&handle, name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) {
+ WARN("The device \"%s\" failed to open: %d (%s).\n",
+ name, err, snd_strerror(err));
+ return 0;
+ }
+
+ params = malloc(snd_pcm_hw_params_sizeof());
+ if (!params) {
+ WARN("Out of memory.\n");
+ snd_pcm_close(handle);
+ return 0;
+ }
+
+ if ((err = snd_pcm_hw_params_any(handle, params)) < 0) {
+ WARN("snd_pcm_hw_params_any failed for \"%s\": %d (%s).\n",
+ name, err, snd_strerror(err));
+ goto exit;
+ }
+
+ if ((err = snd_pcm_hw_params_get_channels_max(params,
+ &max_channels)) < 0){
+ WARN("Unable to get max channels: %d (%s)\n", err, snd_strerror(err));
+ goto exit;
+ }
+
+exit:
+ free(params);
+ snd_pcm_close(handle);
+
+ return max_channels;
+}
+
+enum AudioDeviceConnectionType {
+ AudioDeviceConnectionType_Unknown = 0,
+ AudioDeviceConnectionType_PCI,
+ AudioDeviceConnectionType_USB
+};
+
+static NTSTATUS get_prop_value(void *args)
+{
+ struct get_prop_value_params *params = args;
+ const char *name = params->alsa_name;
+ EDataFlow flow = params->flow;
+ const GUID *guid = params->guid;
+ const PROPERTYKEY *prop = params->prop;
+ PROPVARIANT *out = params->value;
+ static const PROPERTYKEY devicepath_key = { /* undocumented? - {b3f8fa53-0004-438e-9003-51a46e139bfc},2 */
+ {0xb3f8fa53, 0x0004, 0x438e, {0x90, 0x03, 0x51, 0xa4, 0x6e, 0x13, 0x9b, 0xfc}}, 2
+ };
+
+ if(IsEqualPropertyKey(*prop, devicepath_key))
+ {
+ char uevent[MAX_PATH];
+ FILE *fuevent;
+ int card, device;
+
+ /* only implemented for identifiable devices, i.e. not "default" */
+ if(!sscanf(name, "plughw:%u,%u", &card, &device)){
+ params->result = E_NOTIMPL;
+ return STATUS_SUCCESS;
+ }
+ sprintf(uevent, "/sys/class/sound/card%u/device/uevent", card);
+ fuevent = fopen(uevent, "r");
+
+ if(fuevent){
+ enum AudioDeviceConnectionType connection = AudioDeviceConnectionType_Unknown;
+ USHORT vendor_id = 0, product_id = 0;
+ char line[256];
+
+ while (fgets(line, sizeof(line), fuevent)) {
+ char *val;
+ size_t val_len;
+
+ if((val = strchr(line, '='))) {
+ val[0] = 0;
+ val++;
+
+ val_len = strlen(val);
+ if(val_len > 0 && val[val_len - 1] == '\n') { val[val_len - 1] = 0; }
+
+ if(!strcmp(line, "PCI_ID")){
+ connection = AudioDeviceConnectionType_PCI;
+ if(sscanf(val, "%hX:%hX", &vendor_id, &product_id)<2){
+ WARN("Unexpected input when reading PCI_ID in uevent file.\n");
+ connection = AudioDeviceConnectionType_Unknown;
+ break;
+ }
+ }else if(!strcmp(line, "DEVTYPE") && !strcmp(val,"usb_interface"))
+ connection = AudioDeviceConnectionType_USB;
+ else if(!strcmp(line, "PRODUCT"))
+ if(sscanf(val, "%hx/%hx/", &vendor_id, &product_id)<2){
+ WARN("Unexpected input when reading PRODUCT in uevent file.\n");
+ connection = AudioDeviceConnectionType_Unknown;
+ break;
+ }
+ }
+ }
+
+ fclose(fuevent);
+
+ if(connection == AudioDeviceConnectionType_USB || connection == AudioDeviceConnectionType_PCI){
+ UINT serial_number;
+ char buf[128];
+ int len;
+
+ /* As hardly any audio devices have serial numbers, Windows instead
+ appears to use a persistent random number. We emulate this here
+ by instead using the last 8 hex digits of the GUID. */
+ serial_number = (guid->Data4[4] << 24) | (guid->Data4[5] << 16) | (guid->Data4[6] << 8) | guid->Data4[7];
+
+ if(connection == AudioDeviceConnectionType_USB)
+ sprintf(buf, "{1}.USB\\VID_%04X&PID_%04X\\%u&%08X",
+ vendor_id, product_id, device, serial_number);
+ else /* AudioDeviceConnectionType_PCI */
+ sprintf(buf, "{1}.HDAUDIO\\FUNC_01&VEN_%04X&DEV_%04X\\%u&%08X",
+ vendor_id, product_id, device, serial_number);
+
+ len = strlen(buf) + 1;
+ if(*params->buffer_size < len * sizeof(WCHAR)){
+ params->result = E_NOT_SUFFICIENT_BUFFER;
+ *params->buffer_size = len * sizeof(WCHAR);
+ return STATUS_SUCCESS;
+ }
+ out->vt = VT_LPWSTR;
+ out->pwszVal = params->buffer;
+ ntdll_umbstowcs(buf, len, out->pwszVal, len);
+ params->result = S_OK;
+ return STATUS_SUCCESS;
+ }
+ }else{
+ WARN("Could not open %s for reading\n", uevent);
+ params->result = E_NOTIMPL;
+ return STATUS_SUCCESS;
+ }
+ } else if (flow != eCapture && IsEqualPropertyKey(*prop, PKEY_AudioEndpoint_PhysicalSpeakers)) {
+ unsigned int num_speakers, card, device;
+ char hwname[255];
+
+ if (sscanf(name, "plughw:%u,%u", &card, &device))
+ sprintf(hwname, "hw:%u,%u", card, device); /* must be hw rather than plughw to work */
+ else
+ strcpy(hwname, name);
+
+ num_speakers = alsa_probe_num_speakers(hwname);
+ if (num_speakers == 0){
+ params->result = E_FAIL;
+ return STATUS_SUCCESS;
+ }
+ out->vt = VT_UI4;
+
+ if (num_speakers > 6)
+ out->ulVal = KSAUDIO_SPEAKER_STEREO;
+ else if (num_speakers == 6)
+ out->ulVal = KSAUDIO_SPEAKER_5POINT1;
+ else if (num_speakers >= 4)
+ out->ulVal = KSAUDIO_SPEAKER_QUAD;
+ else if (num_speakers >= 2)
+ out->ulVal = KSAUDIO_SPEAKER_STEREO;
+ else if (num_speakers == 1)
+ out->ulVal = KSAUDIO_SPEAKER_MONO;
+
+ params->result = S_OK;
+ return STATUS_SUCCESS;
+ }
+
+ TRACE("Unimplemented property %s,%u\n", wine_dbgstr_guid(&prop->fmtid), prop->pid);
+
+ params->result = E_NOTIMPL;
+ return STATUS_SUCCESS;
+}
+
unixlib_entry_t __wine_unix_call_funcs[] =
{
get_endpoint_ids,
@@ -2265,4 +2443,5 @@ unixlib_entry_t __wine_unix_call_funcs[] =
set_volumes,
set_event_handle,
is_started,
+ get_prop_value,
};
diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c
index c2ec3dd54af..389c40b47de 100644
--- a/dlls/winealsa.drv/mmdevdrv.c
+++ b/dlls/winealsa.drv/mmdevdrv.c
@@ -49,8 +49,6 @@
#include "audioclient.h"
#include "audiopolicy.h"
-#include <alsa/asoundlib.h>
-
#include "unixlib.h"
WINE_DEFAULT_DEBUG_CHANNEL(alsa);
@@ -2444,58 +2442,12 @@ HRESULT WINAPI AUDDRV_GetAudioSessionManager(IMMDevice *device,
return S_OK;
}
-static unsigned int alsa_probe_num_speakers(char *name) {
- snd_pcm_t *handle;
- snd_pcm_hw_params_t *params;
- int err;
- unsigned int max_channels = 0;
-
- if ((err = snd_pcm_open(&handle, name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) {
- WARN("The device \"%s\" failed to open: %d (%s).\n",
- name, err, snd_strerror(err));
- return 0;
- }
-
- params = HeapAlloc(GetProcessHeap(), 0, snd_pcm_hw_params_sizeof());
- if (!params) {
- WARN("Out of memory.\n");
- snd_pcm_close(handle);
- return 0;
- }
-
- if ((err = snd_pcm_hw_params_any(handle, params)) < 0) {
- WARN("snd_pcm_hw_params_any failed for \"%s\": %d (%s).\n",
- name, err, snd_strerror(err));
- goto exit;
- }
-
- if ((err = snd_pcm_hw_params_get_channels_max(params,
- &max_channels)) < 0){
- WARN("Unable to get max channels: %d (%s)\n", err, snd_strerror(err));
- goto exit;
- }
-
-exit:
- HeapFree(GetProcessHeap(), 0, params);
- snd_pcm_close(handle);
-
- return max_channels;
-}
-
-enum AudioDeviceConnectionType {
- AudioDeviceConnectionType_Unknown = 0,
- AudioDeviceConnectionType_PCI,
- AudioDeviceConnectionType_USB
-};
-
HRESULT WINAPI AUDDRV_GetPropValue(GUID *guid, const PROPERTYKEY *prop, PROPVARIANT *out)
{
+ struct get_prop_value_params params;
char name[256];
EDataFlow flow;
-
- static const PROPERTYKEY devicepath_key = { /* undocumented? - {b3f8fa53-0004-438e-9003-51a46e139bfc},2 */
- {0xb3f8fa53, 0x0004, 0x438e, {0x90, 0x03, 0x51, 0xa4, 0x6e, 0x13, 0x9b, 0xfc}}, 2
- };
+ unsigned int size = 0;
TRACE("%s, (%s,%u), %p\n", wine_dbgstr_guid(guid), wine_dbgstr_guid(&prop->fmtid), prop->pid, out);
@@ -2505,116 +2457,27 @@ HRESULT WINAPI AUDDRV_GetPropValue(GUID *guid, const PROPERTYKEY *prop, PROPVARI
return E_NOINTERFACE;
}
- if(IsEqualPropertyKey(*prop, devicepath_key))
- {
- char uevent[MAX_PATH];
- FILE *fuevent;
- int card, device;
-
- /* only implemented for identifiable devices, i.e. not "default" */
- if(!sscanf(name, "plughw:%u,%u", &card, &device))
- return E_NOTIMPL;
-
- sprintf(uevent, "/sys/class/sound/card%u/device/uevent", card);
- fuevent = fopen(uevent, "r");
-
- if(fuevent){
- enum AudioDeviceConnectionType connection = AudioDeviceConnectionType_Unknown;
- USHORT vendor_id = 0, product_id = 0;
- char line[256];
-
- while (fgets(line, sizeof(line), fuevent)) {
- char *val;
- size_t val_len;
-
- if((val = strchr(line, '='))) {
- val[0] = 0;
- val++;
-
- val_len = strlen(val);
- if(val_len > 0 && val[val_len - 1] == '\n') { val[val_len - 1] = 0; }
-
- if(!strcmp(line, "PCI_ID")){
- connection = AudioDeviceConnectionType_PCI;
- if(sscanf(val, "%hX:%hX", &vendor_id, &product_id)<2){
- WARN("Unexpected input when reading PCI_ID in uevent file.\n");
- connection = AudioDeviceConnectionType_Unknown;
- break;
- }
- }else if(!strcmp(line, "DEVTYPE") && !strcmp(val,"usb_interface"))
- connection = AudioDeviceConnectionType_USB;
- else if(!strcmp(line, "PRODUCT"))
- if(sscanf(val, "%hx/%hx/", &vendor_id, &product_id)<2){
- WARN("Unexpected input when reading PRODUCT in uevent file.\n");
- connection = AudioDeviceConnectionType_Unknown;
- break;
- }
- }
- }
-
- fclose(fuevent);
-
- if(connection == AudioDeviceConnectionType_USB || connection == AudioDeviceConnectionType_PCI){
- static const WCHAR usbformatW[] = { '{','1','}','.','U','S','B','\\','V','I','D','_',
- '%','0','4','X','&','P','I','D','_','%','0','4','X','\\',
- '%','u','&','%','0','8','X',0 }; /* "{1}.USB\VID_%04X&PID_%04X\%u&%08X" */
- static const WCHAR pciformatW[] = { '{','1','}','.','H','D','A','U','D','I','O','\\','F','U','N','C','_','0','1','&',
- 'V','E','N','_','%','0','4','X','&','D','E','V','_',
- '%','0','4','X','\\','%','u','&','%','0','8','X',0 }; /* "{1}.HDAUDIO\FUNC_01&VEN_%04X&DEV_%04X\%u&%08X" */
- UINT serial_number;
-
- /* As hardly any audio devices have serial numbers, Windows instead
- appears to use a persistent random number. We emulate this here
- by instead using the last 8 hex digits of the GUID. */
- serial_number = (guid->Data4[4] << 24) | (guid->Data4[5] << 16) | (guid->Data4[6] << 8) | guid->Data4[7];
-
- out->vt = VT_LPWSTR;
- out->pwszVal = CoTaskMemAlloc(128 * sizeof(WCHAR));
-
- if(!out->pwszVal)
- return E_OUTOFMEMORY;
-
- if(connection == AudioDeviceConnectionType_USB)
- sprintfW( out->pwszVal, usbformatW, vendor_id, product_id, device, serial_number);
- else if(connection == AudioDeviceConnectionType_PCI)
- sprintfW( out->pwszVal, pciformatW, vendor_id, product_id, device, serial_number);
-
- return S_OK;
- }
- }else{
- WARN("Could not open %s for reading\n", uevent);
- return E_NOTIMPL;
- }
- } else if (flow != eCapture && IsEqualPropertyKey(*prop, PKEY_AudioEndpoint_PhysicalSpeakers)) {
- unsigned int num_speakers, card, device;
- char hwname[255];
-
- if (sscanf(name, "plughw:%u,%u", &card, &device))
- sprintf(hwname, "hw:%u,%u", card, device); /* must be hw rather than plughw to work */
- else
- strcpy(hwname, name);
-
- num_speakers = alsa_probe_num_speakers(hwname);
- if (num_speakers == 0)
- return E_FAIL;
+ params.alsa_name = name;
+ params.flow = flow;
+ params.guid = guid;
+ params.prop = prop;
+ params.value = out;
+ params.buffer = NULL;
+ params.buffer_size = &size;
- out->vt = VT_UI4;
+ while(1) {
+ ALSA_CALL(get_prop_value, ¶ms);
- if (num_speakers > 6)
- out->ulVal = KSAUDIO_SPEAKER_STEREO;
- else if (num_speakers == 6)
- out->ulVal = KSAUDIO_SPEAKER_5POINT1;
- else if (num_speakers >= 4)
- out->ulVal = KSAUDIO_SPEAKER_QUAD;
- else if (num_speakers >= 2)
- out->ulVal = KSAUDIO_SPEAKER_STEREO;
- else if (num_speakers == 1)
- out->ulVal = KSAUDIO_SPEAKER_MONO;
+ if(params.result != E_NOT_SUFFICIENT_BUFFER)
+ break;
- return S_OK;
+ CoTaskMemFree(params.buffer);
+ params.buffer = CoTaskMemAlloc(*params.buffer_size);
+ if(!params.buffer)
+ return E_OUTOFMEMORY;
}
+ if(FAILED(params.result))
+ CoTaskMemFree(params.buffer);
- TRACE("Unimplemented property %s,%u\n", wine_dbgstr_guid(&prop->fmtid), prop->pid);
-
- return E_NOTIMPL;
+ return params.result;
}
diff --git a/dlls/winealsa.drv/unixlib.h b/dlls/winealsa.drv/unixlib.h
index 4326f79a50b..c2de48cef65 100644
--- a/dlls/winealsa.drv/unixlib.h
+++ b/dlls/winealsa.drv/unixlib.h
@@ -195,6 +195,18 @@ struct is_started_params
HRESULT result;
};
+struct get_prop_value_params
+{
+ const char *alsa_name;
+ EDataFlow flow;
+ const GUID *guid;
+ const PROPERTYKEY *prop;
+ HRESULT result;
+ PROPVARIANT *value;
+ void *buffer; /* caller allocated buffer to hold value's strings */
+ unsigned int *buffer_size;
+};
+
enum alsa_funcs
{
alsa_get_endpoint_ids,
@@ -219,6 +231,7 @@ enum alsa_funcs
alsa_set_volumes,
alsa_set_event_handle,
alsa_is_started,
+ alsa_get_prop_value,
};
extern unixlib_handle_t alsa_handle;
--
2.25.1
4
6
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winealsa.drv/alsamidi.c | 57 ++++++++++++++++++++++++++++++++++++
dlls/winealsa.drv/midi.c | 47 -----------------------------
2 files changed, 57 insertions(+), 47 deletions(-)
diff --git a/dlls/winealsa.drv/alsamidi.c b/dlls/winealsa.drv/alsamidi.c
index 04d1cb08c09..44b16693d16 100644
--- a/dlls/winealsa.drv/alsamidi.c
+++ b/dlls/winealsa.drv/alsamidi.c
@@ -462,6 +462,60 @@ static UINT midi_out_open(WORD dev_id, MIDIOPENDESC *midi_desc, UINT flags, stru
return MMSYSERR_NOERROR;
}
+static UINT midi_out_close(WORD dev_id, struct notify_context *notify)
+{
+ struct midi_dest *dest;
+
+ TRACE("(%04X);\n", dev_id);
+
+ if (dev_id >= num_dests)
+ {
+ WARN("bad device ID : %d\n", dev_id);
+ return MMSYSERR_BADDEVICEID;
+ }
+
+ dest = dests + dev_id;
+
+ if (dest->midiDesc.hMidi == 0)
+ {
+ WARN("device not opened !\n");
+ return MMSYSERR_ERROR;
+ }
+
+ /* FIXME: should test that no pending buffer is still in the queue for
+ * playing */
+
+ if (dest->seq == NULL)
+ {
+ WARN("can't close !\n");
+ return MMSYSERR_ERROR;
+ }
+
+ switch (dest->caps.wTechnology)
+ {
+ case MOD_FMSYNTH:
+ case MOD_MIDIPORT:
+ case MOD_SYNTH:
+ seq_lock();
+ TRACE("Deleting port :%d, connected to %d:%d\n", dest->port_out, dest->addr.client, dest->addr.port);
+ snd_seq_delete_simple_port(dest->seq, dest->port_out);
+ dest->port_out = -1;
+ seq_unlock();
+ seq_close();
+ dest->seq = NULL;
+ break;
+ default:
+ WARN("Technology not supported (yet) %d !\n", dest->caps.wTechnology);
+ return MMSYSERR_NOTENABLED;
+ }
+
+ set_out_notify(notify, dest, dev_id, MOM_CLOSE, 0, 0);
+
+ dest->midiDesc.hMidi = 0;
+
+ return MMSYSERR_NOERROR;
+}
+
NTSTATUS midi_out_message(void *args)
{
struct midi_out_message_params *params = args;
@@ -479,6 +533,9 @@ NTSTATUS midi_out_message(void *args)
case MODM_OPEN:
*params->err = midi_out_open(params->dev_id, (MIDIOPENDESC *)params->param_1, params->param_2, params->notify);
break;
+ case MODM_CLOSE:
+ *params->err = midi_out_close(params->dev_id, params->notify);
+ break;
default:
TRACE("Unsupported message\n");
*params->err = MMSYSERR_NOTSUPPORTED;
diff --git a/dlls/winealsa.drv/midi.c b/dlls/winealsa.drv/midi.c
index c77d479162b..5f8d855c9fb 100644
--- a/dlls/winealsa.drv/midi.c
+++ b/dlls/winealsa.drv/midi.c
@@ -122,7 +122,6 @@ static void MIDI_NotifyClient(UINT wDevID, WORD wMsg,
wDevID, wMsg, dwParam1, dwParam2);
switch (wMsg) {
- case MOM_CLOSE:
case MOM_DONE:
case MOM_POSITIONCB:
if (wDevID > MODM_NumDevs) return;
@@ -631,50 +630,6 @@ static DWORD modGetDevCaps(WORD wDevID, LPMIDIOUTCAPSW lpCaps, DWORD dwSize)
return MMSYSERR_NOERROR;
}
-/**************************************************************************
- * modClose [internal]
- */
-static DWORD modClose(WORD wDevID)
-{
- int ret = MMSYSERR_NOERROR;
-
- TRACE("(%04X);\n", wDevID);
-
- if (MidiOutDev[wDevID].midiDesc.hMidi == 0) {
- WARN("device not opened !\n");
- return MMSYSERR_ERROR;
- }
- /* FIXME: should test that no pending buffer is still in the queue for
- * playing */
-
- if (MidiOutDev[wDevID].seq == NULL) {
- WARN("can't close !\n");
- return MMSYSERR_ERROR;
- }
-
- switch (MidiOutDev[wDevID].caps.wTechnology) {
- case MOD_FMSYNTH:
- case MOD_MIDIPORT:
- case MOD_SYNTH:
- seq_lock();
- TRACE("Deleting port :%d, connected to %d:%d\n", MidiOutDev[wDevID].port_out, MidiOutDev[wDevID].addr.client, MidiOutDev[wDevID].addr.port);
- snd_seq_delete_simple_port(MidiOutDev[wDevID].seq, MidiOutDev[wDevID].port_out);
- MidiOutDev[wDevID].port_out = -1;
- seq_unlock();
- midiCloseSeq();
- MidiOutDev[wDevID].seq = NULL;
- break;
- default:
- WARN("Technology not supported (yet) %d !\n",
- MidiOutDev[wDevID].caps.wTechnology);
- return MMSYSERR_NOTENABLED;
- }
-
- MIDI_NotifyClient(wDevID, MOM_CLOSE, 0L, 0L);
- MidiOutDev[wDevID].midiDesc.hMidi = 0;
- return ret;
-}
-
/**************************************************************************
* modData [internal]
*/
@@ -1051,8 +1006,6 @@ DWORD WINAPI ALSA_modMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
case DRVM_INIT:
ALSA_MidiInit();
return 0;
- case MODM_CLOSE:
- return modClose(wDevID);
case MODM_DATA:
return modData(wDevID, dwParam1);
case MODM_LONGDATA:
--
2.25.1
1
0
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winealsa.drv/alsa.c | 1 +
dlls/winealsa.drv/alsamidi.c | 133 +++++++++++++++++++++++++++++++++++
dlls/winealsa.drv/midi.c | 127 +++++++--------------------------
dlls/winealsa.drv/unixlib.h | 26 +++++++
4 files changed, 186 insertions(+), 101 deletions(-)
diff --git a/dlls/winealsa.drv/alsa.c b/dlls/winealsa.drv/alsa.c
index 16c0c7c387d..6d307eb84bf 100644
--- a/dlls/winealsa.drv/alsa.c
+++ b/dlls/winealsa.drv/alsa.c
@@ -2445,6 +2445,7 @@ unixlib_entry_t __wine_unix_call_funcs[] =
is_started,
get_prop_value,
midi_init,
+ midi_out_message,
midi_seq_lock, /* temporary */
midi_seq_open,
diff --git a/dlls/winealsa.drv/alsamidi.c b/dlls/winealsa.drv/alsamidi.c
index a90d5b30fcf..04d1cb08c09 100644
--- a/dlls/winealsa.drv/alsamidi.c
+++ b/dlls/winealsa.drv/alsamidi.c
@@ -353,3 +353,136 @@ NTSTATUS midi_init(void *args)
return STATUS_SUCCESS;
}
+
+static void set_out_notify(struct notify_context *notify, struct midi_dest *dest, WORD dev_id, WORD msg,
+ UINT_PTR param_1, UINT_PTR param_2)
+{
+ notify->send_notify = TRUE;
+ notify->dev_id = dev_id;
+ notify->msg = msg;
+ notify->param_1 = param_1;
+ notify->param_2 = param_2;
+ notify->callback = dest->midiDesc.dwCallback;
+ notify->flags = dest->wFlags;
+ notify->device = dest->midiDesc.hMidi;
+ notify->instance = dest->midiDesc.dwInstance;
+}
+
+static UINT midi_out_open(WORD dev_id, MIDIOPENDESC *midi_desc, UINT flags, struct notify_context *notify)
+{
+ int ret;
+ int port_out;
+ char port_out_name[32];
+ snd_seq_t *midi_seq;
+ struct midi_dest *dest;
+
+ TRACE("(%04X, %p, %08X);\n", dev_id, midi_desc, flags);
+
+ if (midi_desc == NULL)
+ {
+ WARN("Invalid Parameter !\n");
+ return MMSYSERR_INVALPARAM;
+ }
+ if (dev_id >= num_dests)
+ {
+ TRACE("MAX_MIDIOUTDRV reached !\n");
+ return MMSYSERR_BADDEVICEID;
+ }
+ dest = dests + dev_id;
+ if (dest->midiDesc.hMidi != 0)
+ {
+ WARN("device already open !\n");
+ return MMSYSERR_ALLOCATED;
+ }
+ if (!dest->bEnabled)
+ {
+ WARN("device disabled !\n");
+ return MIDIERR_NODEVICE;
+ }
+ if ((flags & ~CALLBACK_TYPEMASK) != 0)
+ {
+ WARN("bad dwFlags\n");
+ return MMSYSERR_INVALFLAG;
+ }
+
+ switch (dest->caps.wTechnology)
+ {
+ case MOD_FMSYNTH:
+ case MOD_MIDIPORT:
+ case MOD_SYNTH:
+ if (!(midi_seq = seq_open(NULL)))
+ return MMSYSERR_ALLOCATED;
+ break;
+ default:
+ WARN("Technology not supported (yet) %d !\n", dest->caps.wTechnology);
+ return MMSYSERR_NOTENABLED;
+ }
+
+ dest->wFlags = HIWORD(flags & CALLBACK_TYPEMASK);
+ dest->midiDesc = *midi_desc;
+ dest->seq = midi_seq;
+
+ seq_lock();
+ /* Create a port dedicated to a specific device */
+ /* Keep the old name without a number for the first port */
+ if (dev_id)
+ sprintf(port_out_name, "WINE ALSA Output #%d", dev_id);
+
+ port_out = snd_seq_create_simple_port(midi_seq, dev_id ? port_out_name : "WINE ALSA Output",
+ SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ | SND_SEQ_PORT_CAP_SUBS_WRITE,
+ SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION);
+
+ if (port_out < 0)
+ {
+ TRACE("Unable to create output port\n");
+ dest->port_out = -1;
+ }
+ else
+ {
+ TRACE("Output port %d created successfully\n", port_out);
+ dest->port_out = port_out;
+
+ /* Connect our app port to the device port */
+ ret = snd_seq_connect_to(midi_seq, port_out, dest->addr.client, dest->addr.port);
+
+ /* usually will happen when the port is already connected */
+ /* other errors should not be fatal either */
+ if (ret < 0)
+ WARN("Could not connect port %d to %d:%d: %s\n", dev_id, dest->addr.client,
+ dest->addr.port, snd_strerror(ret));
+ }
+ seq_unlock();
+
+ if (port_out < 0)
+ return MMSYSERR_NOTENABLED;
+
+ TRACE("Output port :%d connected %d:%d\n", port_out, dest->addr.client, dest->addr.port);
+
+ set_out_notify(notify, dest, dev_id, MOM_OPEN, 0, 0);
+ return MMSYSERR_NOERROR;
+}
+
+NTSTATUS midi_out_message(void *args)
+{
+ struct midi_out_message_params *params = args;
+
+ params->notify->send_notify = FALSE;
+
+ switch (params->msg)
+ {
+ case DRVM_EXIT:
+ case DRVM_ENABLE:
+ case DRVM_DISABLE:
+ /* FIXME: Pretend this is supported */
+ *params->err = MMSYSERR_NOERROR;
+ break;
+ case MODM_OPEN:
+ *params->err = midi_out_open(params->dev_id, (MIDIOPENDESC *)params->param_1, params->param_2, params->notify);
+ break;
+ default:
+ TRACE("Unsupported message\n");
+ *params->err = MMSYSERR_NOTSUPPORTED;
+ }
+
+ return STATUS_SUCCESS;
+}
diff --git a/dlls/winealsa.drv/midi.c b/dlls/winealsa.drv/midi.c
index 535f3dbd348..c77d479162b 100644
--- a/dlls/winealsa.drv/midi.c
+++ b/dlls/winealsa.drv/midi.c
@@ -79,6 +79,14 @@ static void seq_unlock(void)
ALSA_CALL(midi_seq_lock, (void *)(UINT_PTR)0);
}
+static void notify_client(struct notify_context *notify)
+{
+ TRACE("dev_id = %d msg = %d param1 = %04lX param2 = %04lX\n", notify->dev_id, notify->msg, notify->param_1, notify->param_2);
+
+ DriverCallback(notify->callback, notify->flags, notify->device, notify->msg,
+ notify->instance, notify->param_1, notify->param_2);
+}
+
/*======================================================================*
* Low level MIDI implementation *
*======================================================================*/
@@ -114,7 +122,6 @@ static void MIDI_NotifyClient(UINT wDevID, WORD wMsg,
wDevID, wMsg, dwParam1, dwParam2);
switch (wMsg) {
- case MOM_OPEN:
case MOM_CLOSE:
case MOM_DONE:
case MOM_POSITIONCB:
@@ -624,96 +631,6 @@ static DWORD modGetDevCaps(WORD wDevID, LPMIDIOUTCAPSW lpCaps, DWORD dwSize)
return MMSYSERR_NOERROR;
}
-/**************************************************************************
- * modOpen [internal]
- */
-static DWORD modOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
-{
- int ret;
- int port_out;
- char port_out_name[32];
- snd_seq_t *midi_seq;
-
- TRACE("(%04X, %p, %08X);\n", wDevID, lpDesc, dwFlags);
- if (lpDesc == NULL) {
- WARN("Invalid Parameter !\n");
- return MMSYSERR_INVALPARAM;
- }
- if (wDevID >= MODM_NumDevs) {
- TRACE("MAX_MIDIOUTDRV reached !\n");
- return MMSYSERR_BADDEVICEID;
- }
- if (MidiOutDev[wDevID].midiDesc.hMidi != 0) {
- WARN("device already open !\n");
- return MMSYSERR_ALLOCATED;
- }
- if (!MidiOutDev[wDevID].bEnabled) {
- WARN("device disabled !\n");
- return MIDIERR_NODEVICE;
- }
- if ((dwFlags & ~CALLBACK_TYPEMASK) != 0) {
- WARN("bad dwFlags\n");
- return MMSYSERR_INVALFLAG;
- }
-
- switch (MidiOutDev[wDevID].caps.wTechnology) {
- case MOD_FMSYNTH:
- case MOD_MIDIPORT:
- case MOD_SYNTH:
- if (!(midi_seq = midiOpenSeq(NULL))) {
- return MMSYSERR_ALLOCATED;
- }
- break;
- default:
- WARN("Technology not supported (yet) %d !\n",
- MidiOutDev[wDevID].caps.wTechnology);
- return MMSYSERR_NOTENABLED;
- }
-
- MidiOutDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
- MidiOutDev[wDevID].midiDesc = *lpDesc;
- MidiOutDev[wDevID].seq = midi_seq;
-
- seq_lock();
- /* Create a port dedicated to a specific device */
- /* Keep the old name without a number for the first port */
- if (wDevID)
- sprintf(port_out_name, "WINE ALSA Output #%d", wDevID);
-
- port_out = snd_seq_create_simple_port(midi_seq, wDevID?port_out_name:"WINE ALSA Output",
- SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ|SND_SEQ_PORT_CAP_SUBS_WRITE,
- SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION);
-
- if (port_out < 0) {
- TRACE("Unable to create output port\n");
- MidiOutDev[wDevID].port_out = -1;
- } else {
- TRACE("Output port %d created successfully\n", port_out);
- MidiOutDev[wDevID].port_out = port_out;
-
- /* Connect our app port to the device port */
- ret = snd_seq_connect_to(midi_seq, port_out, MidiOutDev[wDevID].addr.client,
- MidiOutDev[wDevID].addr.port);
-
- /* usually will happen when the port is already connected */
- /* other errors should not be fatal either */
- if (ret < 0)
- WARN("Could not connect port %d to %d:%d: %s\n",
- wDevID, MidiOutDev[wDevID].addr.client,
- MidiOutDev[wDevID].addr.port, snd_strerror(ret));
- }
- seq_unlock();
-
- if (port_out < 0)
- return MMSYSERR_NOTENABLED;
-
- TRACE("Output port :%d connected %d:%d\n",port_out,MidiOutDev[wDevID].addr.client,MidiOutDev[wDevID].addr.port);
-
- MIDI_NotifyClient(wDevID, MOM_OPEN, 0L, 0L);
- return MMSYSERR_NOERROR;
-}
-
-
/**************************************************************************
* modClose [internal]
*/
@@ -1123,6 +1040,10 @@ DWORD WINAPI ALSA_midMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
DWORD WINAPI ALSA_modMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
+ struct midi_out_message_params params;
+ struct notify_context notify;
+ UINT err;
+
TRACE("(%04X, %04X, %08lX, %08lX, %08lX);\n",
wDevID, wMsg, dwUser, dwParam1, dwParam2);
@@ -1130,13 +1051,6 @@ DWORD WINAPI ALSA_modMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
case DRVM_INIT:
ALSA_MidiInit();
return 0;
- case DRVM_EXIT:
- case DRVM_ENABLE:
- case DRVM_DISABLE:
- /* FIXME: Pretend this is supported */
- return 0;
- case MODM_OPEN:
- return modOpen(wDevID, (LPMIDIOPENDESC)dwParam1, dwParam2);
case MODM_CLOSE:
return modClose(wDevID);
case MODM_DATA:
@@ -1157,10 +1071,21 @@ DWORD WINAPI ALSA_modMessage(UINT wDevID, UINT wMsg, DWORD_PTR dwUser,
return 0;
case MODM_RESET:
return modReset(wDevID);
- default:
- TRACE("Unsupported message\n");
}
- return MMSYSERR_NOTSUPPORTED;
+
+ params.dev_id = wDevID;
+ params.msg = wMsg;
+ params.user = dwUser;
+ params.param_1 = dwParam1;
+ params.param_2 = dwParam2;
+ params.err = &err;
+ params.notify = ¬ify;
+
+ ALSA_CALL(midi_out_message, ¶ms);
+
+ if (!err && notify.send_notify) notify_client(¬ify);
+
+ return err;
}
/**************************************************************************
diff --git a/dlls/winealsa.drv/unixlib.h b/dlls/winealsa.drv/unixlib.h
index d69ab980f42..e3cd7123101 100644
--- a/dlls/winealsa.drv/unixlib.h
+++ b/dlls/winealsa.drv/unixlib.h
@@ -241,6 +241,30 @@ struct midi_init_params
void *dests, *srcs;
};
+struct notify_context
+{
+ BOOL send_notify;
+ WORD dev_id;
+ WORD msg;
+ UINT_PTR param_1;
+ UINT_PTR param_2;
+ UINT_PTR callback;
+ UINT flags;
+ HANDLE device;
+ UINT_PTR instance;
+};
+
+struct midi_out_message_params
+{
+ UINT dev_id;
+ UINT msg;
+ UINT_PTR user;
+ UINT_PTR param_1;
+ UINT_PTR param_2;
+ UINT *err;
+ struct notify_context *notify;
+};
+
struct midi_seq_open_params
{
int close;
@@ -274,12 +298,14 @@ enum alsa_funcs
alsa_is_started,
alsa_get_prop_value,
alsa_midi_init,
+ alsa_midi_out_message,
alsa_midi_seq_lock, /* temporary */
alsa_midi_seq_open,
};
NTSTATUS midi_init(void *args) DECLSPEC_HIDDEN;
+NTSTATUS midi_out_message(void *args) DECLSPEC_HIDDEN;
NTSTATUS midi_seq_lock(void *args) DECLSPEC_HIDDEN;
NTSTATUS midi_seq_open(void *args) DECLSPEC_HIDDEN;
--
2.25.1
1
0
[PATCH 4/6] winealsa: Add a temporary syscall to return the snd_seq handle.
by Huw Davies March 15, 2022
by Huw Davies March 15, 2022
March 15, 2022
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winealsa.drv/alsa.c | 1 +
dlls/winealsa.drv/alsamidi.c | 47 +++++++++++++++++++++++++++++-----
dlls/winealsa.drv/midi.c | 49 ++++++++----------------------------
dlls/winealsa.drv/unixlib.h | 9 +++++++
4 files changed, 62 insertions(+), 44 deletions(-)
diff --git a/dlls/winealsa.drv/alsa.c b/dlls/winealsa.drv/alsa.c
index 76e4b98caaf..16c0c7c387d 100644
--- a/dlls/winealsa.drv/alsa.c
+++ b/dlls/winealsa.drv/alsa.c
@@ -2447,4 +2447,5 @@ unixlib_entry_t __wine_unix_call_funcs[] =
midi_init,
midi_seq_lock, /* temporary */
+ midi_seq_open,
};
diff --git a/dlls/winealsa.drv/alsamidi.c b/dlls/winealsa.drv/alsamidi.c
index 9e7962f46cd..a90d5b30fcf 100644
--- a/dlls/winealsa.drv/alsamidi.c
+++ b/dlls/winealsa.drv/alsamidi.c
@@ -55,6 +55,7 @@ static struct midi_dest dests[MAX_MIDIOUTDRV];
static struct midi_src srcs[MAX_MIDIINDRV];
static snd_seq_t *midi_seq;
static unsigned int seq_refs;
+static int port_in = -1;
static void seq_lock(void)
{
@@ -74,7 +75,7 @@ NTSTATUS midi_seq_lock(void *args)
return STATUS_SUCCESS;
}
-static int seq_open(void)
+static snd_seq_t *seq_open(int *port_in_ret)
{
static int midi_warn;
@@ -87,12 +88,28 @@ static int seq_open(void)
WARN("Error opening ALSA sequencer.\n");
midi_warn = 1;
seq_unlock();
- return -1;
+ return NULL;
}
+ snd_seq_set_client_name(midi_seq, "WINE midi driver");
}
seq_refs++;
+
+ if (port_in_ret)
+ {
+ if (port_in < 0)
+ {
+ port_in = snd_seq_create_simple_port(midi_seq, "WINE ALSA Input",
+ SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_READ | SND_SEQ_PORT_CAP_SUBS_WRITE,
+ SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION);
+ if (port_in < 0)
+ TRACE("Unable to create input port\n");
+ else
+ TRACE("Input port %d created successfully\n", port_in);
+ }
+ *port_in_ret = port_in;
+ }
seq_unlock();
- return 0;
+ return midi_seq;
}
static void seq_close(void)
@@ -100,12 +117,29 @@ static void seq_close(void)
seq_lock();
if (--seq_refs == 0)
{
+ if (port_in >= 0)
+ {
+ snd_seq_delete_simple_port(midi_seq, port_in);
+ port_in = -1;
+ }
snd_seq_close(midi_seq);
midi_seq = NULL;
}
seq_unlock();
}
+NTSTATUS midi_seq_open(void *args)
+{
+ struct midi_seq_open_params *params = args;
+
+ if (!params->close)
+ params->seq = seq_open(params->port_in);
+ else
+ seq_close();
+
+ return STATUS_SUCCESS;
+}
+
static int alsa_to_win_device_type(unsigned int type)
{
/* MOD_MIDIPORT output port
@@ -270,6 +304,7 @@ NTSTATUS midi_init(void *args)
static BOOL init_done;
snd_seq_client_info_t *cinfo;
snd_seq_port_info_t *pinfo;
+ snd_seq_t *seq;
int external;
if (init_done) {
@@ -281,7 +316,7 @@ NTSTATUS midi_init(void *args)
init_done = TRUE;
/* try to open device */
- if (seq_open() == -1) {
+ if (!(seq = seq_open(NULL))) {
*params->err = ERROR_OPEN_FAILED;
return STATUS_SUCCESS;
}
@@ -292,10 +327,10 @@ NTSTATUS midi_init(void *args)
/* Add internal ports first, followed by external */
for (external = 0; external < 2; external++) {
snd_seq_client_info_set_client(cinfo, -1);
- while (snd_seq_query_next_client(midi_seq, cinfo) >= 0) {
+ while (snd_seq_query_next_client(seq, cinfo) >= 0) {
snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
snd_seq_port_info_set_port(pinfo, -1);
- while (snd_seq_query_next_port(midi_seq, pinfo) >= 0) {
+ while (snd_seq_query_next_port(seq, pinfo) >= 0) {
unsigned int cap = snd_seq_port_info_get_capability(pinfo);
unsigned int type = snd_seq_port_info_get_type(pinfo);
if (!external == !(type & SND_SEQ_PORT_TYPE_PORT))
diff --git a/dlls/winealsa.drv/midi.c b/dlls/winealsa.drv/midi.c
index fae6ddf8615..535f3dbd348 100644
--- a/dlls/winealsa.drv/midi.c
+++ b/dlls/winealsa.drv/midi.c
@@ -55,12 +55,8 @@ static int MODM_NumDevs = 0;
/* this is the total number of MIDI out devices found */
static int MIDM_NumDevs = 0;
-static snd_seq_t* midiSeq = NULL;
-static int numOpenMidiSeq = 0;
static int numStartedMidiIn = 0;
-static int port_in;
-
static CRITICAL_SECTION crit_sect; /* protects all MidiIn buffer queues */
static CRITICAL_SECTION_DEBUG critsect_debug =
{
@@ -152,40 +148,18 @@ static void MIDI_NotifyClient(UINT wDevID, WORD wMsg,
DriverCallback(dwCallBack, uFlags, hDev, wMsg, dwInstance, dwParam1, dwParam2);
}
-static BOOL midi_warn = TRUE;
/**************************************************************************
* midiOpenSeq [internal]
*/
static snd_seq_t *midiOpenSeq(int *port_in_ret)
{
- seq_lock();
- if (numOpenMidiSeq == 0) {
- if (snd_seq_open(&midiSeq, "default", SND_SEQ_OPEN_DUPLEX, 0) < 0)
- {
- if (midi_warn)
- {
- WARN("Error opening ALSA sequencer.\n");
- }
- midi_warn = FALSE;
- seq_unlock();
- return NULL;
- }
+ struct midi_seq_open_params params;
- /* Setting the client name is the only init to do */
- snd_seq_set_client_name(midiSeq, "WINE midi driver");
+ params.port_in = port_in_ret;
+ params.close = 0;
+ ALSA_CALL(midi_seq_open, ¶ms);
- port_in = snd_seq_create_simple_port(midiSeq, "WINE ALSA Input",
- SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_READ|SND_SEQ_PORT_CAP_SUBS_WRITE,
- SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION);
- if (port_in < 0)
- TRACE("Unable to create input port\n");
- else
- TRACE("Input port %d created successfully\n", port_in);
- }
- numOpenMidiSeq++;
- seq_unlock();
- if (port_in_ret) *port_in_ret = port_in;
- return midiSeq;
+ return params.seq;
}
/**************************************************************************
@@ -193,13 +167,12 @@ static snd_seq_t *midiOpenSeq(int *port_in_ret)
*/
static int midiCloseSeq(void)
{
- seq_lock();
- if (--numOpenMidiSeq == 0) {
- snd_seq_delete_simple_port(midiSeq, port_in);
- snd_seq_close(midiSeq);
- midiSeq = NULL;
- }
- seq_unlock();
+ struct midi_seq_open_params params;
+
+ params.port_in = NULL;
+ params.close = 1;
+ ALSA_CALL(midi_seq_open, ¶ms);
+
return 0;
}
diff --git a/dlls/winealsa.drv/unixlib.h b/dlls/winealsa.drv/unixlib.h
index e0ae16b97d9..d69ab980f42 100644
--- a/dlls/winealsa.drv/unixlib.h
+++ b/dlls/winealsa.drv/unixlib.h
@@ -241,6 +241,13 @@ struct midi_init_params
void *dests, *srcs;
};
+struct midi_seq_open_params
+{
+ int close;
+ snd_seq_t *seq;
+ int *port_in;
+};
+
enum alsa_funcs
{
alsa_get_endpoint_ids,
@@ -269,11 +276,13 @@ enum alsa_funcs
alsa_midi_init,
alsa_midi_seq_lock, /* temporary */
+ alsa_midi_seq_open,
};
NTSTATUS midi_init(void *args) DECLSPEC_HIDDEN;
NTSTATUS midi_seq_lock(void *args) DECLSPEC_HIDDEN;
+NTSTATUS midi_seq_open(void *args) DECLSPEC_HIDDEN;
extern unixlib_handle_t alsa_handle;
--
2.25.1
1
0
[PATCH 3/6] winealsa: Store the snd_seq handle and the input port in the device data.
by Huw Davies March 15, 2022
by Huw Davies March 15, 2022
March 15, 2022
This is to avoid accessing more global variables and generally
makes things a bit cleaner.
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winealsa.drv/midi.c | 85 ++++++++++++++++++++-----------------
dlls/winealsa.drv/unixlib.h | 3 ++
2 files changed, 49 insertions(+), 39 deletions(-)
diff --git a/dlls/winealsa.drv/midi.c b/dlls/winealsa.drv/midi.c
index 988429ab934..fae6ddf8615 100644
--- a/dlls/winealsa.drv/midi.c
+++ b/dlls/winealsa.drv/midi.c
@@ -156,7 +156,7 @@ static BOOL midi_warn = TRUE;
/**************************************************************************
* midiOpenSeq [internal]
*/
-static int midiOpenSeq(BOOL create_client)
+static snd_seq_t *midiOpenSeq(int *port_in_ret)
{
seq_lock();
if (numOpenMidiSeq == 0) {
@@ -168,25 +168,24 @@ static int midiOpenSeq(BOOL create_client)
}
midi_warn = FALSE;
seq_unlock();
- return -1;
+ return NULL;
}
- if (create_client) {
- /* Setting the client name is the only init to do */
- snd_seq_set_client_name(midiSeq, "WINE midi driver");
-
- port_in = snd_seq_create_simple_port(midiSeq, "WINE ALSA Input",
- SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_READ|SND_SEQ_PORT_CAP_SUBS_WRITE,
- SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION);
- if (port_in < 0)
- TRACE("Unable to create input port\n");
- else
- TRACE("Input port %d created successfully\n", port_in);
- }
+ /* Setting the client name is the only init to do */
+ snd_seq_set_client_name(midiSeq, "WINE midi driver");
+
+ port_in = snd_seq_create_simple_port(midiSeq, "WINE ALSA Input",
+ SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_READ|SND_SEQ_PORT_CAP_SUBS_WRITE,
+ SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION);
+ if (port_in < 0)
+ TRACE("Unable to create input port\n");
+ else
+ TRACE("Input port %d created successfully\n", port_in);
}
numOpenMidiSeq++;
seq_unlock();
- return 0;
+ if (port_in_ret) *port_in_ret = port_in;
+ return midiSeq;
}
/**************************************************************************
@@ -314,8 +313,9 @@ static void handle_midi_event(snd_seq_event_t *ev)
}
}
-static DWORD WINAPI midRecThread(LPVOID arg)
+static DWORD WINAPI midRecThread(void *arg)
{
+ snd_seq_t *midi_seq = arg;
int npfd;
struct pollfd *pfd;
int ret;
@@ -325,9 +325,9 @@ static DWORD WINAPI midRecThread(LPVOID arg)
while(!end_thread) {
TRACE("Thread loop\n");
seq_lock();
- npfd = snd_seq_poll_descriptors_count(midiSeq, POLLIN);
+ npfd = snd_seq_poll_descriptors_count(midi_seq, POLLIN);
pfd = HeapAlloc(GetProcessHeap(), 0, npfd * sizeof(struct pollfd));
- snd_seq_poll_descriptors(midiSeq, pfd, npfd, POLLIN);
+ snd_seq_poll_descriptors(midi_seq, pfd, npfd, POLLIN);
seq_unlock();
/* Check if an event is present */
@@ -337,9 +337,9 @@ static DWORD WINAPI midRecThread(LPVOID arg)
}
/* Note: This definitely does not work.
- * while(snd_seq_event_input_pending(midiSeq, 0) > 0) {
+ * while(snd_seq_event_input_pending(midi_seq, 0) > 0) {
snd_seq_event_t* ev;
- snd_seq_event_input(midiSeq, &ev);
+ snd_seq_event_input(midi_seq, &ev);
....................
snd_seq_free_event(ev);
}*/
@@ -348,7 +348,7 @@ static DWORD WINAPI midRecThread(LPVOID arg)
snd_seq_event_t *ev;
seq_lock();
- snd_seq_event_input(midiSeq, &ev);
+ snd_seq_event_input(midi_seq, &ev);
seq_unlock();
if (ev) {
@@ -357,10 +357,10 @@ static DWORD WINAPI midRecThread(LPVOID arg)
}
seq_lock();
- ret = snd_seq_event_input_pending(midiSeq, 0);
+ ret = snd_seq_event_input_pending(midi_seq, 0);
seq_unlock();
} while(ret > 0);
-
+
HeapFree(GetProcessHeap(), 0, pfd);
}
return 0;
@@ -387,7 +387,8 @@ static DWORD midGetDevCaps(WORD wDevID, LPMIDIINCAPSW lpCaps, DWORD dwSize)
*/
static DWORD midOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
{
- int ret = 0;
+ int ret = 0, port_in;
+ snd_seq_t *midi_seq;
TRACE("(%04X, %p, %08X);\n", wDevID, lpDesc, dwFlags);
@@ -420,7 +421,7 @@ static DWORD midOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
return MMSYSERR_INVALFLAG;
}
- if (midiOpenSeq(TRUE) < 0) {
+ if (!(midi_seq = midiOpenSeq(&port_in))) {
return MMSYSERR_ERROR;
}
@@ -430,10 +431,12 @@ static DWORD midOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
MidiInDev[wDevID].midiDesc = *lpDesc;
MidiInDev[wDevID].state = 0;
MidiInDev[wDevID].startTime = 0;
+ MidiInDev[wDevID].seq = midi_seq;
+ MidiInDev[wDevID].port_in = port_in;
/* Connect our app port to the device port */
seq_lock();
- ret = snd_seq_connect_from(midiSeq, port_in, MidiInDev[wDevID].addr.client,
+ ret = snd_seq_connect_from(midi_seq, port_in, MidiInDev[wDevID].addr.client,
MidiInDev[wDevID].addr.port);
seq_unlock();
if (ret < 0)
@@ -443,7 +446,7 @@ static DWORD midOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
if (numStartedMidiIn++ == 0) {
end_thread = 0;
- hThread = CreateThread(NULL, 0, midRecThread, NULL, 0, NULL);
+ hThread = CreateThread(NULL, 0, midRecThread, midi_seq, 0, NULL);
if (!hThread) {
numStartedMidiIn = 0;
WARN("Couldn't create thread for midi-in\n");
@@ -479,7 +482,7 @@ static DWORD midClose(WORD wDevID)
return MIDIERR_STILLPLAYING;
}
- if (midiSeq == NULL) {
+ if (MidiInDev[wDevID].seq == NULL) {
WARN("ooops !\n");
return MMSYSERR_ERROR;
}
@@ -494,12 +497,13 @@ static DWORD midClose(WORD wDevID)
}
seq_lock();
- snd_seq_disconnect_from(midiSeq, port_in, MidiInDev[wDevID].addr.client, MidiInDev[wDevID].addr.port);
+ snd_seq_disconnect_from(MidiInDev[wDevID].seq, MidiInDev[wDevID].port_in, MidiInDev[wDevID].addr.client, MidiInDev[wDevID].addr.port);
seq_unlock();
midiCloseSeq();
MIDI_NotifyClient(wDevID, MIM_CLOSE, 0L, 0L);
MidiInDev[wDevID].midiDesc.hMidi = 0;
+ MidiInDev[wDevID].seq = NULL;
return ret;
}
@@ -655,6 +659,7 @@ static DWORD modOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
int ret;
int port_out;
char port_out_name[32];
+ snd_seq_t *midi_seq;
TRACE("(%04X, %p, %08X);\n", wDevID, lpDesc, dwFlags);
if (lpDesc == NULL) {
@@ -682,7 +687,7 @@ static DWORD modOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
case MOD_FMSYNTH:
case MOD_MIDIPORT:
case MOD_SYNTH:
- if (midiOpenSeq(TRUE) < 0) {
+ if (!(midi_seq = midiOpenSeq(NULL))) {
return MMSYSERR_ALLOCATED;
}
break;
@@ -694,6 +699,7 @@ static DWORD modOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
MidiOutDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
MidiOutDev[wDevID].midiDesc = *lpDesc;
+ MidiOutDev[wDevID].seq = midi_seq;
seq_lock();
/* Create a port dedicated to a specific device */
@@ -701,7 +707,7 @@ static DWORD modOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
if (wDevID)
sprintf(port_out_name, "WINE ALSA Output #%d", wDevID);
- port_out = snd_seq_create_simple_port(midiSeq, wDevID?port_out_name:"WINE ALSA Output",
+ port_out = snd_seq_create_simple_port(midi_seq, wDevID?port_out_name:"WINE ALSA Output",
SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ|SND_SEQ_PORT_CAP_SUBS_WRITE,
SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION);
@@ -713,7 +719,7 @@ static DWORD modOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
MidiOutDev[wDevID].port_out = port_out;
/* Connect our app port to the device port */
- ret = snd_seq_connect_to(midiSeq, port_out, MidiOutDev[wDevID].addr.client,
+ ret = snd_seq_connect_to(midi_seq, port_out, MidiOutDev[wDevID].addr.client,
MidiOutDev[wDevID].addr.port);
/* usually will happen when the port is already connected */
@@ -751,7 +757,7 @@ static DWORD modClose(WORD wDevID)
/* FIXME: should test that no pending buffer is still in the queue for
* playing */
- if (midiSeq == NULL) {
+ if (MidiOutDev[wDevID].seq == NULL) {
WARN("can't close !\n");
return MMSYSERR_ERROR;
}
@@ -762,10 +768,11 @@ static DWORD modClose(WORD wDevID)
case MOD_SYNTH:
seq_lock();
TRACE("Deleting port :%d, connected to %d:%d\n", MidiOutDev[wDevID].port_out, MidiOutDev[wDevID].addr.client, MidiOutDev[wDevID].addr.port);
- snd_seq_delete_simple_port(midiSeq, MidiOutDev[wDevID].port_out);
+ snd_seq_delete_simple_port(MidiOutDev[wDevID].seq, MidiOutDev[wDevID].port_out);
MidiOutDev[wDevID].port_out = -1;
seq_unlock();
- midiCloseSeq();
+ midiCloseSeq();
+ MidiOutDev[wDevID].seq = NULL;
break;
default:
WARN("Technology not supported (yet) %d !\n",
@@ -792,7 +799,7 @@ static DWORD modData(WORD wDevID, DWORD dwParam)
if (wDevID >= MODM_NumDevs) return MMSYSERR_BADDEVICEID;
if (!MidiOutDev[wDevID].bEnabled) return MIDIERR_NODEVICE;
- if (midiSeq == NULL) {
+ if (MidiOutDev[wDevID].seq == NULL) {
WARN("can't play !\n");
return MIDIERR_NODEVICE;
}
@@ -886,7 +893,7 @@ static DWORD modData(WORD wDevID, DWORD dwParam)
}
if (handled) {
seq_lock();
- snd_seq_event_output_direct(midiSeq, &event);
+ snd_seq_event_output_direct(MidiOutDev[wDevID].seq, &event);
seq_unlock();
}
}
@@ -919,7 +926,7 @@ static DWORD modLongData(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
if (wDevID >= MODM_NumDevs) return MMSYSERR_BADDEVICEID;
if (!MidiOutDev[wDevID].bEnabled) return MIDIERR_NODEVICE;
- if (midiSeq == NULL) {
+ if (MidiOutDev[wDevID].seq == NULL) {
WARN("can't play !\n");
return MIDIERR_NODEVICE;
}
@@ -977,7 +984,7 @@ static DWORD modLongData(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
snd_seq_ev_set_subs(&event);
snd_seq_ev_set_sysex(&event, lpMidiHdr->dwBufferLength + len_add, lpNewData ? lpNewData : lpData);
seq_lock();
- snd_seq_event_output_direct(midiSeq, &event);
+ snd_seq_event_output_direct(MidiOutDev[wDevID].seq, &event);
seq_unlock();
HeapFree(GetProcessHeap(), 0, lpNewData);
break;
diff --git a/dlls/winealsa.drv/unixlib.h b/dlls/winealsa.drv/unixlib.h
index adac72183ee..e0ae16b97d9 100644
--- a/dlls/winealsa.drv/unixlib.h
+++ b/dlls/winealsa.drv/unixlib.h
@@ -218,7 +218,9 @@ typedef struct midi_src
MIDIHDR *lpQueueHdr;
UINT startTime;
MIDIINCAPSW caps;
+ snd_seq_t *seq;
snd_seq_addr_t addr;
+ int port_in;
} WINE_MIDIIN;
typedef struct midi_dest
@@ -227,6 +229,7 @@ typedef struct midi_dest
MIDIOPENDESC midiDesc;
WORD wFlags;
MIDIOUTCAPSW caps;
+ snd_seq_t *seq;
snd_seq_addr_t addr;
int port_out;
} WINE_MIDIOUT;
--
2.25.1
1
0
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/winealsa.drv/alsa.c | 1 +
dlls/winealsa.drv/alsamidi.c | 256 +++++++++++++++++++++++++++++++++++
dlls/winealsa.drv/midi.c | 240 ++------------------------------
dlls/winealsa.drv/unixlib.h | 34 +++++
4 files changed, 305 insertions(+), 226 deletions(-)
diff --git a/dlls/winealsa.drv/alsa.c b/dlls/winealsa.drv/alsa.c
index cdc3d81d8cc..76e4b98caaf 100644
--- a/dlls/winealsa.drv/alsa.c
+++ b/dlls/winealsa.drv/alsa.c
@@ -2444,6 +2444,7 @@ unixlib_entry_t __wine_unix_call_funcs[] =
set_event_handle,
is_started,
get_prop_value,
+ midi_init,
midi_seq_lock, /* temporary */
};
diff --git a/dlls/winealsa.drv/alsamidi.c b/dlls/winealsa.drv/alsamidi.c
index ab4de4f7f9e..9e7962f46cd 100644
--- a/dlls/winealsa.drv/alsamidi.c
+++ b/dlls/winealsa.drv/alsamidi.c
@@ -31,6 +31,7 @@
#include <stdarg.h>
#include <stdio.h>
#include <pthread.h>
+#include <alsa/asoundlib.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
@@ -38,13 +39,23 @@
#include "winbase.h"
#include "winternl.h"
#include "mmdeviceapi.h"
+#include "mmddk.h"
+#include "wine/debug.h"
#include "wine/unixlib.h"
#include "unixlib.h"
+WINE_DEFAULT_DEBUG_CHANNEL(midi);
+
static pthread_mutex_t seq_mutex = PTHREAD_MUTEX_INITIALIZER;
+static unsigned int num_dests, num_srcs;
+static struct midi_dest dests[MAX_MIDIOUTDRV];
+static struct midi_src srcs[MAX_MIDIINDRV];
+static snd_seq_t *midi_seq;
+static unsigned int seq_refs;
+
static void seq_lock(void)
{
pthread_mutex_lock(&seq_mutex);
@@ -62,3 +73,248 @@ NTSTATUS midi_seq_lock(void *args)
return STATUS_SUCCESS;
}
+
+static int seq_open(void)
+{
+ static int midi_warn;
+
+ seq_lock();
+ if (seq_refs == 0)
+ {
+ if (snd_seq_open(&midi_seq, "default", SND_SEQ_OPEN_DUPLEX, 0) < 0)
+ {
+ if (!midi_warn)
+ WARN("Error opening ALSA sequencer.\n");
+ midi_warn = 1;
+ seq_unlock();
+ return -1;
+ }
+ }
+ seq_refs++;
+ seq_unlock();
+ return 0;
+}
+
+static void seq_close(void)
+{
+ seq_lock();
+ if (--seq_refs == 0)
+ {
+ snd_seq_close(midi_seq);
+ midi_seq = NULL;
+ }
+ seq_unlock();
+}
+
+static int alsa_to_win_device_type(unsigned int type)
+{
+ /* MOD_MIDIPORT output port
+ * MOD_SYNTH generic internal synth
+ * MOD_SQSYNTH square wave internal synth
+ * MOD_FMSYNTH FM internal synth
+ * MOD_MAPPER MIDI mapper
+ * MOD_WAVETABLE hardware wavetable internal synth
+ * MOD_SWSYNTH software internal synth
+ */
+
+ /* FIXME Is this really the correct equivalence from ALSA to
+ Windows Sound type? */
+
+ if (type & SND_SEQ_PORT_TYPE_SYNTH)
+ return MOD_FMSYNTH;
+
+ if (type & (SND_SEQ_PORT_TYPE_DIRECT_SAMPLE|SND_SEQ_PORT_TYPE_SAMPLE))
+ return MOD_SYNTH;
+
+ if (type & (SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION))
+ return MOD_MIDIPORT;
+
+ ERR("Cannot determine the type (alsa type is %x) of this midi device. Assuming FM Synth\n", type);
+ return MOD_FMSYNTH;
+}
+
+static void port_add(snd_seq_client_info_t* cinfo, snd_seq_port_info_t* pinfo, unsigned int cap, unsigned int type)
+{
+ char name[MAXPNAMELEN];
+ unsigned int len;
+ struct midi_dest *dest;
+ struct midi_src *src;
+
+ if (cap & SND_SEQ_PORT_CAP_WRITE) {
+ TRACE("OUT (%d:%s:%s:%d:%s:%x)\n",snd_seq_client_info_get_client(cinfo),
+ snd_seq_client_info_get_name(cinfo),
+ snd_seq_client_info_get_type(cinfo) == SND_SEQ_USER_CLIENT ? "user" : "kernel",
+ snd_seq_port_info_get_port(pinfo),
+ snd_seq_port_info_get_name(pinfo),
+ type);
+
+ if (num_dests >= MAX_MIDIOUTDRV)
+ return;
+ if (!type)
+ return;
+
+ dest = dests + num_dests;
+ dest->addr = *snd_seq_port_info_get_addr(pinfo);
+
+ /* Manufac ID. We do not have access to this with soundcard.h
+ * Does not seem to be a problem, because in mmsystem.h only
+ * Microsoft's ID is listed.
+ */
+ dest->caps.wMid = 0x00FF;
+ dest->caps.wPid = 0x0001; /* FIXME Product ID */
+ /* Product Version. We simply say "1" */
+ dest->caps.vDriverVersion = 0x001;
+ /* The following are mandatory for MOD_MIDIPORT */
+ dest->caps.wChannelMask = 0xFFFF;
+ dest->caps.wVoices = 0;
+ dest->caps.wNotes = 0;
+ dest->caps.dwSupport = 0;
+
+ /* Try to use both client and port names, if this is too long take the port name only.
+ In the second case the port name should be explicit enough due to its big size.
+ */
+ len = strlen(snd_seq_port_info_get_name(pinfo));
+ if ( (strlen(snd_seq_client_info_get_name(cinfo)) + len + 3) < sizeof(name) ) {
+ sprintf(name, "%s - %s", snd_seq_client_info_get_name(cinfo), snd_seq_port_info_get_name(pinfo));
+ len = strlen(name);
+ } else {
+ len = min(len, sizeof(name) - 1);
+ memcpy(name, snd_seq_port_info_get_name(pinfo), len);
+ name[len] = '\0';
+ }
+ ntdll_umbstowcs( name, len + 1, dest->caps.szPname, ARRAY_SIZE(dest->caps.szPname));
+
+ dest->caps.wTechnology = alsa_to_win_device_type(type);
+
+ if (MOD_MIDIPORT != dest->caps.wTechnology) {
+ /* FIXME Do we have this information?
+ * Assuming the soundcards can handle
+ * MIDICAPS_VOLUME and MIDICAPS_LRVOLUME but
+ * not MIDICAPS_CACHE.
+ */
+ dest->caps.dwSupport = MIDICAPS_VOLUME|MIDICAPS_LRVOLUME;
+ dest->caps.wVoices = 16;
+
+ /* FIXME Is it possible to know the maximum
+ * number of simultaneous notes of a soundcard ?
+ * I believe we don't have this information, but
+ * it's probably equal or more than wVoices
+ */
+ dest->caps.wNotes = 16;
+ }
+ dest->bEnabled = TRUE;
+ dest->port_out = -1;
+
+ TRACE("MidiOut[%d]\tname='%s' techn=%d voices=%d notes=%d chnMsk=%04x support=%d\n"
+ "\tALSA info: midi dev-type=%x, capa=0\n",
+ num_dests, wine_dbgstr_w(dest->caps.szPname),
+ dest->caps.wTechnology,
+ dest->caps.wVoices, dest->caps.wNotes,
+ dest->caps.wChannelMask, dest->caps.dwSupport,
+ type);
+
+ num_dests++;
+ }
+ if (cap & SND_SEQ_PORT_CAP_READ) {
+ TRACE("IN (%d:%s:%s:%d:%s:%x)\n",snd_seq_client_info_get_client(cinfo),
+ snd_seq_client_info_get_name(cinfo),
+ snd_seq_client_info_get_type(cinfo) == SND_SEQ_USER_CLIENT ? "user" : "kernel",
+ snd_seq_port_info_get_port(pinfo),
+ snd_seq_port_info_get_name(pinfo),
+ type);
+
+ if (num_srcs >= MAX_MIDIINDRV)
+ return;
+ if (!type)
+ return;
+
+ src = srcs + num_srcs;
+ src->addr = *snd_seq_port_info_get_addr(pinfo);
+
+ /* Manufac ID. We do not have access to this with soundcard.h
+ * Does not seem to be a problem, because in mmsystem.h only
+ * Microsoft's ID is listed.
+ */
+ src->caps.wMid = 0x00FF;
+ src->caps.wPid = 0x0001; /* FIXME Product ID */
+ /* Product Version. We simply say "1" */
+ src->caps.vDriverVersion = 0x001;
+ src->caps.dwSupport = 0; /* mandatory with MIDIINCAPS */
+
+ /* Try to use both client and port names, if this is too long take the port name only.
+ In the second case the port name should be explicit enough due to its big size.
+ */
+ len = strlen(snd_seq_port_info_get_name(pinfo));
+ if ( (strlen(snd_seq_client_info_get_name(cinfo)) + len + 3) < sizeof(name) ) {
+ sprintf(name, "%s - %s", snd_seq_client_info_get_name(cinfo), snd_seq_port_info_get_name(pinfo));
+ len = strlen(name);
+ } else {
+ len = min(len, sizeof(name) - 1);
+ memcpy(name, snd_seq_port_info_get_name(pinfo), len);
+ name[len] = '\0';
+ }
+ ntdll_umbstowcs( name, len + 1, src->caps.szPname, ARRAY_SIZE(src->caps.szPname));
+ src->state = 0;
+
+ TRACE("MidiIn [%d]\tname='%s' support=%d\n"
+ "\tALSA info: midi dev-type=%x, capa=0\n",
+ num_srcs, wine_dbgstr_w(src->caps.szPname), src->caps.dwSupport, type);
+
+ num_srcs++;
+ }
+}
+
+NTSTATUS midi_init(void *args)
+{
+ struct midi_init_params *params = args;
+ static BOOL init_done;
+ snd_seq_client_info_t *cinfo;
+ snd_seq_port_info_t *pinfo;
+ int external;
+
+ if (init_done) {
+ *params->err = ERROR_ALREADY_INITIALIZED;
+ return STATUS_SUCCESS;
+ }
+
+ TRACE("Initializing the MIDI variables.\n");
+ init_done = TRUE;
+
+ /* try to open device */
+ if (seq_open() == -1) {
+ *params->err = ERROR_OPEN_FAILED;
+ return STATUS_SUCCESS;
+ }
+
+ cinfo = calloc( 1, snd_seq_client_info_sizeof() );
+ pinfo = calloc( 1, snd_seq_port_info_sizeof() );
+
+ /* Add internal ports first, followed by external */
+ for (external = 0; external < 2; external++) {
+ snd_seq_client_info_set_client(cinfo, -1);
+ while (snd_seq_query_next_client(midi_seq, cinfo) >= 0) {
+ snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
+ snd_seq_port_info_set_port(pinfo, -1);
+ while (snd_seq_query_next_port(midi_seq, pinfo) >= 0) {
+ unsigned int cap = snd_seq_port_info_get_capability(pinfo);
+ unsigned int type = snd_seq_port_info_get_type(pinfo);
+ if (!external == !(type & SND_SEQ_PORT_TYPE_PORT))
+ port_add(cinfo, pinfo, cap, type);
+ }
+ }
+ }
+
+ seq_close();
+ free( cinfo );
+ free( pinfo );
+
+ *params->err = NOERROR;
+ params->num_dests = num_dests;
+ params->num_srcs = num_srcs;
+ params->dests = dests;
+ params->srcs = srcs;
+
+ TRACE("End\n");
+
+ return STATUS_SUCCESS;
+}
diff --git a/dlls/winealsa.drv/midi.c b/dlls/winealsa.drv/midi.c
index c90b061da64..988429ab934 100644
--- a/dlls/winealsa.drv/midi.c
+++ b/dlls/winealsa.drv/midi.c
@@ -43,33 +43,12 @@
#include "wine/debug.h"
#include "wine/unixlib.h"
-#include <alsa/asoundlib.h>
-
#include "unixlib.h"
WINE_DEFAULT_DEBUG_CHANNEL(midi);
-typedef struct {
- int state; /* -1 disabled, 0 is no recording started, 1 in recording, bit 2 set if in sys exclusive recording */
- MIDIOPENDESC midiDesc;
- WORD wFlags;
- LPMIDIHDR lpQueueHdr;
- DWORD startTime;
- MIDIINCAPSW caps;
- snd_seq_addr_t addr;
-} WINE_MIDIIN;
-
-typedef struct {
- BOOL bEnabled;
- MIDIOPENDESC midiDesc;
- WORD wFlags;
- MIDIOUTCAPSW caps;
- snd_seq_addr_t addr;
- int port_out;
-} WINE_MIDIOUT;
-
-static WINE_MIDIIN MidiInDev [MAX_MIDIINDRV ];
-static WINE_MIDIOUT MidiOutDev[MAX_MIDIOUTDRV];
+static WINE_MIDIIN *MidiInDev;
+static WINE_MIDIOUT *MidiOutDev;
/* this is the total number of MIDI out devices found (synth and port) */
static int MODM_NumDevs = 0;
@@ -124,39 +103,6 @@ static void error_handler(const char* file, int line, const char* function, int
}
#endif
-/**************************************************************************
- * MIDI_unixToWindowsDeviceType [internal]
- *
- * return the Windows equivalent to a Unix Device Type
- *
- */
-static int MIDI_AlsaToWindowsDeviceType(unsigned int type)
-{
- /* MOD_MIDIPORT output port
- * MOD_SYNTH generic internal synth
- * MOD_SQSYNTH square wave internal synth
- * MOD_FMSYNTH FM internal synth
- * MOD_MAPPER MIDI mapper
- * MOD_WAVETABLE hardware wavetable internal synth
- * MOD_SWSYNTH software internal synth
- */
-
- /* FIXME Is this really the correct equivalence from ALSA to
- Windows Sound type? */
-
- if (type & SND_SEQ_PORT_TYPE_SYNTH)
- return MOD_FMSYNTH;
-
- if (type & (SND_SEQ_PORT_TYPE_DIRECT_SAMPLE|SND_SEQ_PORT_TYPE_SAMPLE))
- return MOD_SYNTH;
-
- if (type & (SND_SEQ_PORT_TYPE_MIDI_GENERIC|SND_SEQ_PORT_TYPE_APPLICATION))
- return MOD_MIDIPORT;
-
- ERR("Cannot determine the type (alsa type is %x) of this midi device. Assuming FM Synth\n", type);
- return MOD_FMSYNTH;
-}
-
/**************************************************************************
* MIDI_NotifyClient [internal]
*/
@@ -1121,134 +1067,6 @@ static DWORD modReset(WORD wDevID)
}
-/**************************************************************************
- * ALSA_AddMidiPort [internal]
- *
- * Helper for ALSA_MidiInit
- */
-static void ALSA_AddMidiPort(snd_seq_client_info_t* cinfo, snd_seq_port_info_t* pinfo, unsigned int cap, unsigned int type)
-{
- char midiPortName[MAXPNAMELEN];
-
- if (cap & SND_SEQ_PORT_CAP_WRITE) {
- TRACE("OUT (%d:%s:%s:%d:%s:%x)\n",snd_seq_client_info_get_client(cinfo),
- snd_seq_client_info_get_name(cinfo),
- snd_seq_client_info_get_type(cinfo) == SND_SEQ_USER_CLIENT ? "user" : "kernel",
- snd_seq_port_info_get_port(pinfo),
- snd_seq_port_info_get_name(pinfo),
- type);
-
- if (MODM_NumDevs >= MAX_MIDIOUTDRV)
- return;
- if (!type)
- return;
-
- MidiOutDev[MODM_NumDevs].addr = *snd_seq_port_info_get_addr(pinfo);
-
- /* Manufac ID. We do not have access to this with soundcard.h
- * Does not seem to be a problem, because in mmsystem.h only
- * Microsoft's ID is listed.
- */
- MidiOutDev[MODM_NumDevs].caps.wMid = 0x00FF;
- MidiOutDev[MODM_NumDevs].caps.wPid = 0x0001; /* FIXME Product ID */
- /* Product Version. We simply say "1" */
- MidiOutDev[MODM_NumDevs].caps.vDriverVersion = 0x001;
- /* The following are mandatory for MOD_MIDIPORT */
- MidiOutDev[MODM_NumDevs].caps.wChannelMask = 0xFFFF;
- MidiOutDev[MODM_NumDevs].caps.wVoices = 0;
- MidiOutDev[MODM_NumDevs].caps.wNotes = 0;
- MidiOutDev[MODM_NumDevs].caps.dwSupport = 0;
-
- /* Try to use both client and port names, if this is too long take the port name only.
- In the second case the port name should be explicit enough due to its big size.
- */
- if ( (strlen(snd_seq_client_info_get_name(cinfo)) + strlen(snd_seq_port_info_get_name(pinfo)) + 3) < MAXPNAMELEN ) {
- sprintf(midiPortName, "%s - %s", snd_seq_client_info_get_name(cinfo), snd_seq_port_info_get_name(pinfo));
- } else {
- lstrcpynA(midiPortName, snd_seq_port_info_get_name(pinfo), MAXPNAMELEN);
- }
- MultiByteToWideChar(CP_UNIXCP, 0, midiPortName, -1, MidiOutDev[MODM_NumDevs].caps.szPname,
- ARRAY_SIZE(MidiOutDev[MODM_NumDevs].caps.szPname));
-
- MidiOutDev[MODM_NumDevs].caps.wTechnology = MIDI_AlsaToWindowsDeviceType(type);
-
- if (MOD_MIDIPORT != MidiOutDev[MODM_NumDevs].caps.wTechnology) {
- /* FIXME Do we have this information?
- * Assuming the soundcards can handle
- * MIDICAPS_VOLUME and MIDICAPS_LRVOLUME but
- * not MIDICAPS_CACHE.
- */
- MidiOutDev[MODM_NumDevs].caps.dwSupport = MIDICAPS_VOLUME|MIDICAPS_LRVOLUME;
- MidiOutDev[MODM_NumDevs].caps.wVoices = 16;
-
- /* FIXME Is it possible to know the maximum
- * number of simultaneous notes of a soundcard ?
- * I believe we don't have this information, but
- * it's probably equal or more than wVoices
- */
- MidiOutDev[MODM_NumDevs].caps.wNotes = 16;
- }
- MidiOutDev[MODM_NumDevs].bEnabled = TRUE;
- MidiOutDev[MODM_NumDevs].port_out = -1;
-
- TRACE("MidiOut[%d]\tname='%s' techn=%d voices=%d notes=%d chnMsk=%04x support=%d\n"
- "\tALSA info: midi dev-type=%x, capa=0\n",
- MODM_NumDevs, wine_dbgstr_w(MidiOutDev[MODM_NumDevs].caps.szPname),
- MidiOutDev[MODM_NumDevs].caps.wTechnology,
- MidiOutDev[MODM_NumDevs].caps.wVoices, MidiOutDev[MODM_NumDevs].caps.wNotes,
- MidiOutDev[MODM_NumDevs].caps.wChannelMask, MidiOutDev[MODM_NumDevs].caps.dwSupport,
- type);
-
- MODM_NumDevs++;
- }
- if (cap & SND_SEQ_PORT_CAP_READ) {
- TRACE("IN (%d:%s:%s:%d:%s:%x)\n",snd_seq_client_info_get_client(cinfo),
- snd_seq_client_info_get_name(cinfo),
- snd_seq_client_info_get_type(cinfo) == SND_SEQ_USER_CLIENT ? "user" : "kernel",
- snd_seq_port_info_get_port(pinfo),
- snd_seq_port_info_get_name(pinfo),
- type);
-
- if (MIDM_NumDevs >= MAX_MIDIINDRV)
- return;
- if (!type)
- return;
-
- MidiInDev[MIDM_NumDevs].addr = *snd_seq_port_info_get_addr(pinfo);
-
- /* Manufac ID. We do not have access to this with soundcard.h
- * Does not seem to be a problem, because in mmsystem.h only
- * Microsoft's ID is listed.
- */
- MidiInDev[MIDM_NumDevs].caps.wMid = 0x00FF;
- MidiInDev[MIDM_NumDevs].caps.wPid = 0x0001; /* FIXME Product ID */
- /* Product Version. We simply say "1" */
- MidiInDev[MIDM_NumDevs].caps.vDriverVersion = 0x001;
- MidiInDev[MIDM_NumDevs].caps.dwSupport = 0; /* mandatory with MIDIINCAPS */
-
- /* Try to use both client and port names, if this is too long take the port name only.
- In the second case the port name should be explicit enough due to its big size.
- */
- if ( (strlen(snd_seq_client_info_get_name(cinfo)) + strlen(snd_seq_port_info_get_name(pinfo)) + 3) < MAXPNAMELEN ) {
- sprintf(midiPortName, "%s - %s", snd_seq_client_info_get_name(cinfo), snd_seq_port_info_get_name(pinfo));
- } else {
- lstrcpynA(midiPortName, snd_seq_port_info_get_name(pinfo), MAXPNAMELEN);
- }
- MultiByteToWideChar(CP_UNIXCP, 0, midiPortName, -1, MidiInDev[MIDM_NumDevs].caps.szPname,
- ARRAY_SIZE(MidiInDev[MIDM_NumDevs].caps.szPname));
- MidiInDev[MIDM_NumDevs].state = 0;
-
- TRACE("MidiIn [%d]\tname='%s' support=%d\n"
- "\tALSA info: midi dev-type=%x, capa=0\n",
- MIDM_NumDevs, wine_dbgstr_w(MidiInDev[MIDM_NumDevs].caps.szPname),
- MidiInDev[MIDM_NumDevs].caps.dwSupport,
- type);
-
- MIDM_NumDevs++;
- }
-}
-
-
/*======================================================================*
* MIDI entry points *
*======================================================================*/
@@ -1260,49 +1078,19 @@ static void ALSA_AddMidiPort(snd_seq_client_info_t* cinfo, snd_seq_port_info_t*
*/
static BOOL ALSA_MidiInit(void)
{
- static BOOL bInitDone = FALSE;
- snd_seq_client_info_t *cinfo;
- snd_seq_port_info_t *pinfo;
- int external;
-
- if (bInitDone)
- return TRUE;
-
- TRACE("Initializing the MIDI variables.\n");
- bInitDone = TRUE;
-
- /* try to open device */
- if (midiOpenSeq(FALSE) == -1) {
- return TRUE;
+ struct midi_init_params params;
+ UINT err;
+
+ params.err = &err;
+ ALSA_CALL(midi_init, ¶ms);
+
+ if (!err)
+ {
+ MODM_NumDevs = params.num_dests;
+ MIDM_NumDevs = params.num_srcs;
+ MidiOutDev = params.dests;
+ MidiInDev = params.srcs;
}
-
-#if 0 /* Debug purpose */
- snd_lib_error_set_handler(error_handler);
-#endif
- cinfo = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_seq_client_info_sizeof() );
- pinfo = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_seq_port_info_sizeof() );
-
- /* Add internal ports first, followed by external */
- for (external = 0; external < 2; external++) {
- snd_seq_client_info_set_client(cinfo, -1);
- while (snd_seq_query_next_client(midiSeq, cinfo) >= 0) {
- snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
- snd_seq_port_info_set_port(pinfo, -1);
- while (snd_seq_query_next_port(midiSeq, pinfo) >= 0) {
- unsigned int cap = snd_seq_port_info_get_capability(pinfo);
- unsigned int type = snd_seq_port_info_get_type(pinfo);
- if (!external == !(type & SND_SEQ_PORT_TYPE_PORT))
- ALSA_AddMidiPort(cinfo, pinfo, cap, type);
- }
- }
- }
-
- /* close file and exit */
- midiCloseSeq();
- HeapFree( GetProcessHeap(), 0, cinfo );
- HeapFree( GetProcessHeap(), 0, pinfo );
-
- TRACE("End\n");
return TRUE;
}
diff --git a/dlls/winealsa.drv/unixlib.h b/dlls/winealsa.drv/unixlib.h
index 89afcb71bec..adac72183ee 100644
--- a/dlls/winealsa.drv/unixlib.h
+++ b/dlls/winealsa.drv/unixlib.h
@@ -207,6 +207,37 @@ struct get_prop_value_params
unsigned int *buffer_size;
};
+#include <alsa/asoundlib.h>
+#include "mmddk.h"
+
+typedef struct midi_src
+{
+ int state; /* -1 disabled, 0 is no recording started, 1 in recording, bit 2 set if in sys exclusive recording */
+ MIDIOPENDESC midiDesc;
+ WORD wFlags;
+ MIDIHDR *lpQueueHdr;
+ UINT startTime;
+ MIDIINCAPSW caps;
+ snd_seq_addr_t addr;
+} WINE_MIDIIN;
+
+typedef struct midi_dest
+{
+ BOOL bEnabled;
+ MIDIOPENDESC midiDesc;
+ WORD wFlags;
+ MIDIOUTCAPSW caps;
+ snd_seq_addr_t addr;
+ int port_out;
+} WINE_MIDIOUT;
+
+struct midi_init_params
+{
+ UINT *err;
+ unsigned int num_dests, num_srcs;
+ void *dests, *srcs;
+};
+
enum alsa_funcs
{
alsa_get_endpoint_ids,
@@ -232,10 +263,13 @@ enum alsa_funcs
alsa_set_event_handle,
alsa_is_started,
alsa_get_prop_value,
+ alsa_midi_init,
alsa_midi_seq_lock, /* temporary */
};
+NTSTATUS midi_init(void *args) DECLSPEC_HIDDEN;
+
NTSTATUS midi_seq_lock(void *args) DECLSPEC_HIDDEN;
extern unixlib_handle_t alsa_handle;
--
2.25.1
1
0