Akihiro,
However, recent Windows systems don't allow to call MCI commands from another thread.
Could you please elaborate? I understand the Co/UnCo issue, but what about other commands? Wouldn't the thread invoking Co/UnCo remain strictly internal to winmm?
At the MCI string command level, all you see are "device" numbers and aliases, so why shouldn't an app be allowed to send "status x position" from any thread in the app's address space?
Do you know the application which relies on this feature?
I rarely analyzed app's requirements. I usually proceed as follows: read available documentation, perform many tests, then turn a meaningful subset of these into wine test format and write driver code that makes Wine nearly undistinguishable from native.
As native behavior varies, I prefer to target the version that was in use at the time when the driver was mostly used (by commercial apps/games). For the MCI, this means MS-Windows 3.x + 9X/ME and early 2k/XP. When you wade through forums, you'll notice that some VB programmers still use the MCI nowadays, but I saw no complex use cases there. Yet I'm biased, as I hardly investigated mciqtz usage and mostly cared about mciwave+midi+cda so far.
E.g. there may be a need to dispatch REFRESH and PAINT messages?
I didn't check Windows behavior at that point. IMHO, MCI code doesn't assume the Window message queue and shouldn't touch them.
Pumping message queue is pure hypothesis on my side, but it would be valuable to know for sure. I'm not familiar with MS-Windows messaging at all. When I raised the question in wine-devel 2013, IIRC I got no response.
I'm unsure there could be no interaction with the message queue in mciavi and mciqtz. After all, there are MCI_*_HWND command options.
Some other area in need of investigation is timing. When or how fast does a function return? For instance, there are entries in bugzilla related to the time it takes to close and reopen winmm. https://bugs.winehq.org/show_bug.cgi?id=28413
On a related side, at what time are callbacks invoked (or quartz pins)? Fortunately, the MCI knows no callbacks (lesson learned), but they may raise their ugly head again via the MCI-Quartz bridge.
As many (old?) apps are single-threaded, so I was told, the duration of function calls matters, allowing the app to return to its message queue fast. The order of calls through pins matters too, alas.
For instance, I've wondered whether it would be valuable to send PLAY, PAUSE and STOP asynchronously, so as to return to the caller fast. The driver could still have internal logic that would let it accept the next command only after the current one is processed, so it's still strictly serial. IOW there's a pipe of length 1 in between. The difference is that the caller app is free to do other things for as long as it doesn't issue commands to fast in a row. I've observed evidence of some async. behavior with at least one of the MCI drivers (mcicda perhaps, or mcimidi, not sure any more): not all errors that PLAY would meet were returned immediately upon command invocation (IIRC there were a few corner cases along PLAY FROM 100 to 100). From an implementation POV, this requires some processing (error checking, e.g. refuse PLAY FROM 100 TO 50) before sending the async. message, and checking the rest in the async. driver. That's quite different from your current "forward immediately" patch. But that's just an idea.
Regards, Jörg Höhle