Commit a23e658a authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

mfplat: Add support for scheduled items.

parent 1a53a655
...@@ -35,6 +35,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(mfplat); ...@@ -35,6 +35,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
#define MAX_USER_QUEUE_HANDLES 124 #define MAX_USER_QUEUE_HANDLES 124
#define WAIT_ITEM_KEY_MASK (0x82000000) #define WAIT_ITEM_KEY_MASK (0x82000000)
#define SCHEDULED_ITEM_KEY_MASK (0x80000000)
static LONG next_item_key; static LONG next_item_key;
...@@ -53,6 +54,7 @@ struct work_item ...@@ -53,6 +54,7 @@ struct work_item
union union
{ {
TP_WAIT *wait_object; TP_WAIT *wait_object;
TP_TIMER *timer_object;
} u; } u;
}; };
...@@ -414,6 +416,30 @@ static void CALLBACK waiting_item_cancelable_callback(TP_CALLBACK_INSTANCE *inst ...@@ -414,6 +416,30 @@ static void CALLBACK waiting_item_cancelable_callback(TP_CALLBACK_INSTANCE *inst
release_work_item(item); release_work_item(item);
} }
static void CALLBACK scheduled_item_callback(TP_CALLBACK_INSTANCE *instance, void *context, TP_TIMER *timer)
{
struct work_item *item = context;
TRACE("result object %p.\n", item->result);
invoke_async_callback(item->result);
release_work_item(item);
}
static void CALLBACK scheduled_item_cancelable_callback(TP_CALLBACK_INSTANCE *instance, void *context, TP_TIMER *timer)
{
struct work_item *item = context;
TRACE("result object %p.\n", item->result);
queue_release_pending_item(item);
invoke_async_callback(item->result);
release_work_item(item);
}
static void queue_mark_item_pending(DWORD mask, struct work_item *item, MFWORKITEM_KEY *key) static void queue_mark_item_pending(DWORD mask, struct work_item *item, MFWORKITEM_KEY *key)
{ {
*key = generate_item_key(mask); *key = generate_item_key(mask);
...@@ -450,6 +476,36 @@ static HRESULT queue_submit_wait(struct queue *queue, HANDLE event, LONG priorit ...@@ -450,6 +476,36 @@ static HRESULT queue_submit_wait(struct queue *queue, HANDLE event, LONG priorit
return S_OK; return S_OK;
} }
static HRESULT queue_submit_timer(struct queue *queue, IMFAsyncResult *result, INT64 timeout, MFWORKITEM_KEY *key)
{
PTP_TIMER_CALLBACK callback;
struct work_item *item;
FILETIME filetime;
LARGE_INTEGER t;
if (!(item = alloc_work_item(queue, result)))
return E_OUTOFMEMORY;
if (key)
{
queue_mark_item_pending(SCHEDULED_ITEM_KEY_MASK, item, key);
callback = scheduled_item_cancelable_callback;
}
else
callback = scheduled_item_callback;
t.QuadPart = timeout * 1000 * 10;
filetime.dwLowDateTime = t.u.LowPart;
filetime.dwHighDateTime = t.u.HighPart;
item->u.timer_object = CreateThreadpoolTimer(callback, item, &queue->env);
SetThreadpoolTimer(item->u.timer_object, &filetime, 0, 0);
TRACE("dispatched %p.\n", result);
return S_OK;
}
static HRESULT queue_cancel_item(struct queue *queue, MFWORKITEM_KEY key) static HRESULT queue_cancel_item(struct queue *queue, MFWORKITEM_KEY key)
{ {
HRESULT hr = MF_E_NOT_FOUND; HRESULT hr = MF_E_NOT_FOUND;
...@@ -463,6 +519,8 @@ static HRESULT queue_cancel_item(struct queue *queue, MFWORKITEM_KEY key) ...@@ -463,6 +519,8 @@ static HRESULT queue_cancel_item(struct queue *queue, MFWORKITEM_KEY key)
key >>= 32; key >>= 32;
if ((key & WAIT_ITEM_KEY_MASK) == WAIT_ITEM_KEY_MASK) if ((key & WAIT_ITEM_KEY_MASK) == WAIT_ITEM_KEY_MASK)
CloseThreadpoolWait(item->u.wait_object); CloseThreadpoolWait(item->u.wait_object);
else if ((key & SCHEDULED_ITEM_KEY_MASK) == SCHEDULED_ITEM_KEY_MASK)
CloseThreadpoolTimer(item->u.timer_object);
else else
WARN("Unknown item key mask %#x.\n", (DWORD)key); WARN("Unknown item key mask %#x.\n", (DWORD)key);
queue_release_pending_item(item); queue_release_pending_item(item);
...@@ -771,9 +829,17 @@ HRESULT WINAPI MFInvokeCallback(IMFAsyncResult *result) ...@@ -771,9 +829,17 @@ HRESULT WINAPI MFInvokeCallback(IMFAsyncResult *result)
static HRESULT schedule_work_item(IMFAsyncResult *result, INT64 timeout, MFWORKITEM_KEY *key) static HRESULT schedule_work_item(IMFAsyncResult *result, INT64 timeout, MFWORKITEM_KEY *key)
{ {
FIXME("%p, %s, %p.\n", result, wine_dbgstr_longlong(timeout), key); struct queue *queue;
HRESULT hr;
if (FAILED(hr = grab_queue(MFASYNC_CALLBACK_QUEUE_TIMER, &queue)))
return hr;
TRACE("%p, %s, %p.\n", result, wine_dbgstr_longlong(timeout), key);
hr = queue_submit_timer(queue, result, timeout, key);
return E_NOTIMPL; return hr;
} }
/*********************************************************************** /***********************************************************************
......
...@@ -1050,11 +1050,9 @@ static void test_scheduled_items(void) ...@@ -1050,11 +1050,9 @@ static void test_scheduled_items(void)
ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr); ok(hr == S_OK, "Failed to start up, hr %#x.\n", hr);
hr = MFScheduleWorkItem(&callback, NULL, -5000, &key); hr = MFScheduleWorkItem(&callback, NULL, -5000, &key);
todo_wine
ok(hr == S_OK, "Failed to schedule item, hr %#x.\n", hr); ok(hr == S_OK, "Failed to schedule item, hr %#x.\n", hr);
hr = MFCancelWorkItem(key); hr = MFCancelWorkItem(key);
todo_wine
ok(hr == S_OK, "Failed to cancel item, hr %#x.\n", hr); ok(hr == S_OK, "Failed to cancel item, hr %#x.\n", hr);
hr = MFCancelWorkItem(key); hr = MFCancelWorkItem(key);
...@@ -1084,15 +1082,13 @@ todo_wine ...@@ -1084,15 +1082,13 @@ todo_wine
IMFAsyncResult_Release(result); IMFAsyncResult_Release(result);
hr = MFScheduleWorkItem(&callback, NULL, -5000, &key); hr = MFScheduleWorkItem(&callback, NULL, -5000, &key);
todo_wine
ok(hr == S_OK, "Failed to schedule item, hr %#x.\n", hr); ok(hr == S_OK, "Failed to schedule item, hr %#x.\n", hr);
hr = MFCancelWorkItem(key); hr = MFCancelWorkItem(key);
todo_wine
ok(hr == S_OK, "Failed to cancel item, hr %#x.\n", hr); ok(hr == S_OK, "Failed to cancel item, hr %#x.\n", hr);
hr = MFShutdown(); hr = MFShutdown();
ok(hr == S_OK, "Failed to shutdown, hr %#x.\n", hr); ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
} }
static void test_serial_queue(void) static void test_serial_queue(void)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment