From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/wm_asyncreader.c | 77 ++++++++++++++++++++++------- 1 file changed, 60 insertions(+), 17 deletions(-)
diff --git a/dlls/winegstreamer/wm_asyncreader.c b/dlls/winegstreamer/wm_asyncreader.c index 11f225a759f..a7d26aa131c 100644 --- a/dlls/winegstreamer/wm_asyncreader.c +++ b/dlls/winegstreamer/wm_asyncreader.c @@ -30,12 +30,22 @@ union async_op_data QWORD duration; void *context; } start; + struct + { + WCHAR *filename; + } open_file; + struct + { + IStream *stream; + } open_stream; };
struct async_op { enum async_op_type { + ASYNC_OP_OPEN_STREAM, + ASYNC_OP_OPEN_FILE, ASYNC_OP_START, ASYNC_OP_STOP, ASYNC_OP_CLOSE, @@ -77,7 +87,7 @@ struct async_reader CRITICAL_SECTION callback_cs; CONDITION_VARIABLE callback_cv;
- bool running; + bool opened, running; struct list async_ops;
bool user_clock; @@ -219,10 +229,7 @@ static DWORD WINAPI async_reader_callback_thread(void *arg) struct async_reader *reader = arg; static const DWORD zero; struct list *entry; - HRESULT hr = S_OK; - - IWMReaderCallback_OnStatus(reader->callback, WMT_OPENED, S_OK, - WMT_TYPE_DWORD, (BYTE *)&zero, reader->context); + HRESULT hr;
EnterCriticalSection(&reader->callback_cs);
@@ -236,6 +243,26 @@ static DWORD WINAPI async_reader_callback_thread(void *arg) hr = list_empty(&reader->async_ops) ? S_OK : E_ABORT; switch (op->type) { + case ASYNC_OP_OPEN_FILE: + if (SUCCEEDED(hr) && FAILED(hr = wm_reader_open_file(&reader->reader, op->u.open_file.filename))) + reader->running = false; + free(op->u.open_file.filename); + goto case_ASYNC_OP_OPEN; + + case ASYNC_OP_OPEN_STREAM: + if (SUCCEEDED(hr) && FAILED(hr = wm_reader_open_stream(&reader->reader, op->u.open_stream.stream))) + reader->running = false; + IStream_Release(op->u.open_stream.stream); + goto case_ASYNC_OP_OPEN; + + case_ASYNC_OP_OPEN: + reader->opened = SUCCEEDED(hr); + LeaveCriticalSection(&reader->callback_cs); + IWMReaderCallback_OnStatus(reader->callback, WMT_OPENED, hr, + WMT_TYPE_DWORD, (BYTE *)&zero, reader->context); + EnterCriticalSection(&reader->callback_cs); + break; + case ASYNC_OP_START: { reader->context = op->u.start.context; @@ -282,6 +309,10 @@ static DWORD WINAPI async_reader_callback_thread(void *arg)
LeaveCriticalSection(&reader->callback_cs);
+ if (reader->opened) + wm_reader_close(&reader->reader); + reader->opened = false; + TRACE("Reader is stopping; exiting.\n"); return 0; } @@ -386,18 +417,26 @@ static HRESULT WINAPI WMReader_Open(IWMReader *iface, const WCHAR *url, IWMReaderCallback *callback, void *context) { struct async_reader *reader = impl_from_IWMReader(iface); + union async_op_data data; HRESULT hr;
TRACE("reader %p, url %s, callback %p, context %p.\n", reader, debugstr_w(url), callback, context);
+ if (!(data.open_file.filename = wcsdup(url))) + return E_OUTOFMEMORY; + EnterCriticalSection(&reader->cs);
- if (SUCCEEDED(hr = wm_reader_open_file(&reader->reader, url)) - && FAILED(hr = async_reader_open(reader, callback, context))) - wm_reader_close(&reader->reader); + if (reader->opened) + hr = E_UNEXPECTED; + else if (SUCCEEDED(hr = async_reader_queue_op(reader, ASYNC_OP_OPEN_FILE, &data))) + hr = async_reader_open(reader, callback, context);
LeaveCriticalSection(&reader->cs); + + if (FAILED(hr)) + free(data.open_file.filename); return hr; }
@@ -410,11 +449,10 @@ static HRESULT WINAPI WMReader_Close(IWMReader *iface)
EnterCriticalSection(&reader->cs);
- if (SUCCEEDED(hr = async_reader_queue_op(reader, ASYNC_OP_CLOSE, NULL))) - { + if (!reader->callback_thread) + hr = NS_E_INVALID_REQUEST; + else if (SUCCEEDED(hr = async_reader_queue_op(reader, ASYNC_OP_CLOSE, NULL))) async_reader_close(reader); - hr = wm_reader_close(&reader->reader); - }
LeaveCriticalSection(&reader->cs);
@@ -857,17 +895,24 @@ static HRESULT WINAPI WMReaderAdvanced2_OpenStream(IWMReaderAdvanced6 *iface, IStream *stream, IWMReaderCallback *callback, void *context) { struct async_reader *reader = impl_from_IWMReaderAdvanced6(iface); + union async_op_data data; HRESULT hr;
TRACE("reader %p, stream %p, callback %p, context %p.\n", reader, stream, callback, context);
+ IStream_AddRef((data.open_stream.stream = stream)); + EnterCriticalSection(&reader->cs);
- if (SUCCEEDED(hr = wm_reader_open_stream(&reader->reader, stream)) - && FAILED(hr = async_reader_open(reader, callback, context))) - wm_reader_close(&reader->reader); + if (reader->opened) + hr = E_UNEXPECTED; + else if (SUCCEEDED(hr = async_reader_queue_op(reader, ASYNC_OP_OPEN_STREAM, &data))) + hr = async_reader_open(reader, callback, context);
LeaveCriticalSection(&reader->cs); + + if (FAILED(hr)) + IStream_Release(data.open_stream.stream); return hr; }
@@ -1732,8 +1777,6 @@ static void async_reader_destroy(struct wm_reader *iface) reader->cs.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&reader->cs);
- wm_reader_close(&reader->reader); - wm_reader_cleanup(&reader->reader); free(reader); }