I do think all the recent changes to winecfg are going into the wrong direction.
First of all, allowing the devices to be opened more than once without having the devices ready for that is a ready bad idea. Basically, windows drivers come in two flavors: - single instance (they can be loaded only once in memory) - multiple instance (they can be loaded several times in memory) For the second type, a specific init string (gotten from the registry, and usually dealing with the HZ resources involved) is passed to the driver. In the wine implementation, we don't get anything from the registry, we just let the device (from the unix interface it uses) return as many audio/midi... ports it finds. This is typically the behavior expected from single instance drivers. Among the issues we'll face here are dual open of the same unix resource (contention) for several instances, overwriting of internal data and structures (they are not prepared for that). Therefore, the multiple open patch has to be reverted.
Secondly, I do think it's a bad idea to reconstruct in winecfg most the driver management. It's not done correctly (the DRV_INIT, DRV_ENABLE and DRV_LOAD messages are not correctly passed). If it works today, it's by chance as the configure message is never handled (we just put out a message box), but it doesn't access the internal structures. To do it, we need the DRV_ messages sent.
Finally, I'm not sure that presenting all the drivers, and the ports available is really meaningful for most users. Some drivers return just potential entries (esound for example). Even with the caps, most users won't tell the difference between alsa and oss entries.
Lately, the available drivers button is not really useful. We shouldn't present non available drivers to the users, and just let him/her choose among the available ones (or just to mark the ones which are not available).
Eric Pouech wrote:
I do think all the recent changes to winecfg are going into the wrong direction.
First of all, allowing the devices to be opened more than once without having the devices ready for that is a ready bad idea. Basically, windows drivers come in two flavors:
- single instance (they can be loaded only once in memory)
- multiple instance (they can be loaded several times in memory)
For the second type, a specific init string (gotten from the registry, and usually dealing with the HZ resources involved) is passed to the driver. In the wine implementation, we don't get anything from the registry, we just let the device (from the unix interface it uses) return as many audio/midi... ports it finds. This is typically the behavior expected from single instance drivers. Among the issues we'll face here are dual open of the same unix resource (contention) for several instances, overwriting of internal data and structures (they are not prepared for that). Therefore, the multiple open patch has to be reverted.
We never "load" a driver more than once. Winecfg calls winmm OpenDriver which will only ever load a single instance of the driver into memory. Subsequent OpenDriver calls will reference the existing in memory driver. Wine models the single instance device driver that supports multiple physical devices. I work with highend multichannel sound cards in windows that show up as a single 8 channel device (with one card or 16 channels with two cards) and as 4 (8) stereo devices.
Secondly, I do think it's a bad idea to reconstruct in winecfg most the driver management. It's not done correctly (the DRV_INIT, DRV_ENABLE and DRV_LOAD messages are not correctly passed). If it works today, it's by chance as the configure message is never handled (we just put out a message box), but it doesn't access the internal structures. To do it, we need the DRV_ messages sent.
It is true that winecfg is not calling each sub system driver (WaveIn, WaveOut, ...) like windows but device probing is done at main driver load in most drivers (and I am fixing the ones that don't) because device configuration is dynamic rather than read from the registry so opening the sub drivers individually to query static data is not a problem. I have a version of the alsa driver that can change registry entries from the configure dialog.
Finally, I'm not sure that presenting all the drivers, and the ports available is really meaningful for most users. Some drivers return just potential entries (esound for example). Even with the caps, most users won't tell the difference between alsa and oss entries.
Jack and esound are fundamentally flawed because they create 10 virtual sound cards that all reference a single physical device. This doesn't take into account multiple devices. The proper way to implement this is to allow multiple opens of the same device (just like windows). That way two or more programs can open one card and other programs can open another card and none of the programs are aware or even care about the others. I have multiple sound cards and headsets in a single computer for music and VoIP and I need a way for individual programs to work with specific devices (just like in windows).
Lately, the available drivers button is not really useful. We shouldn't present non available drivers to the users, and just let him/her choose among the available ones (or just to mark the ones which are not available).
It would be trivial to only show the drivers that opened properly so missing drivers or non-functioning drivers would not be displayed. You can infer that from the device tree now if no physical devices show up under a driver. I could add icons to broken or disabled drivers (just like windows) to show driver/hardware state. I also plan to add device and driver management to the device tree in future versions. This is really just wine's version of the audio portion of windows device manager. Hiding stuff in the registry without giving the user an easy way (GUI rather than reading the source and using regedit) of configuring the sound system is not good.
The direction I am trying to take the winecfg it to allow specific driver configuration through the windows DRV_CONFIGURE mechanism which displays a driver specific dialog box for changing driver specific registry entries. This is the only time there is potential contention problems between programs but only if configuration is performed immediately while the other programs are accessing the driver. This can be avoided by doing the reconfiguration at wine reboot time (winmm.dll unload/load) or by checking for open drivers and using locking to prevent modifications by other programs. You could also move the sound drivers into the server but that won't happen.
We never "load" a driver more than once. Winecfg calls winmm OpenDriver which will only ever load a single instance of the driver into memory. Subsequent OpenDriver calls will reference the existing in memory driver. Wine models the single instance device driver that supports multiple physical devices.
what you end up with is a situation where: - two calls to OpenDriver for the same driver will provide: + a separate HDRVR (one for each call) + the same driver ID at the driver level + an implementation at the driver level with a single data state shared across the two HDRVR instance - most of the drivers are not prepared for that. As a simple example: h1 = OpenDriver("a.drv", ...); h2 = OpenDriver("a.drv", ...); // h1 <> h2, but driver ids are the same // start a play back on one of media stream of a.drv with h1 CloseDriver(h2, 0, 0); // playback will stop, and all data of h1 have been cleared // by closing h2 !
Secondly, I do think it's a bad idea to reconstruct in winecfg most the driver management. It's not done correctly (the DRV_INIT, DRV_ENABLE and DRV_LOAD messages are not correctly passed). If it works today, it's by chance as the configure message is never handled (we just put out a message box), but it doesn't access the internal structures. To do it, we need the DRV_ messages sent.
It is true that winecfg is not calling each sub system driver (WaveIn, WaveOut, ...) like windows but device probing is done at main driver load in most drivers (and I am fixing the ones that don't) because device configuration is dynamic rather than read from the registry so opening the sub drivers individually to query static data is not a problem. I have a version of the alsa driver that can change registry entries from the configure dialog.
yes, but it implies that all drivers configured by winecfg must be single instance drivers.
Finally, I'm not sure that presenting all the drivers, and the ports available is really meaningful for most users. Some drivers return just potential entries (esound for example). Even with the caps, most users won't tell the difference between alsa and oss entries.
Jack and esound are fundamentally flawed because they create 10 virtual sound cards that all reference a single physical device. This doesn't take into account multiple devices. The proper way to implement this is to allow multiple opens of the same device (just like windows). That way two or more programs can open one card and other programs can open another card and none of the programs are aware or even care about the others. I have multiple sound cards and headsets in a single computer for music and VoIP and I need a way for individual programs to work with specific devices (just like in windows).
we do agree here that jack & esound (like any interface with integrated audio mixer) should be multiple instance drivers and not single instance ones.
[snip]
Hiding stuff in the registry without giving the user an easy way (GUI rather than reading the source and using regedit) of configuring the sound system is not good.
that's not what I'm asking for. I request having even for winecfg driver loading/unloading to be handled through winmm, and not by winecfg itself, which forces you in lots of unneeded kludges.
The direction I am trying to take the winecfg it to allow specific driver configuration through the windows DRV_CONFIGURE mechanism which displays a driver specific dialog box for changing driver specific registry entries. This is the only time there is potential contention problems between programs but only if configuration is performed immediately while the other programs are accessing the driver.
that's not true see above
A+
Eric Pouech wrote:
We never "load" a driver more than once. Winecfg calls winmm OpenDriver which will only ever load a single instance of the driver into memory. Subsequent OpenDriver calls will reference the existing in memory driver. Wine models the single instance device driver that supports multiple physical devices.
what you end up with is a situation where:
- two calls to OpenDriver for the same driver will provide:
- a separate HDRVR (one for each call)
- the same driver ID at the driver level
- an implementation at the driver level with a single data state shared across the two HDRVR instance
This is true and is also how windows works with the tests I have done with a user installable driver. The reason this works is because I am only accessing the static driver configuration (GetNumDevs and GetDevCaps). I have no intention of actually using the drivers for anything else because they are not designed for that. I am opening the driver, not the individual devices (WaveIn, WaveOut, ...). I agree that under normal circumstances, bypassing winmm and accessing the driver directly is the wrong thing to do because winmm is responsible for coordinating things, but in this case and only this case (accessing static driver configuration) it is OK. The real way to do this would be to have each driver register itself with the PnP manager and then we could interface with it. I am using winmm (OpenDriver) for loading and configuring the drivers which is perfectly legal to do. Only using LoadLibrary and xxxMessage to get the number of devices and their capabilities is the thing that is really questionable. A PnP manager would fix that in the long term.
Jack and esound are fundamentally flawed because they create 10 virtual sound cards that all reference a single physical device. This doesn't take into account multiple devices. The proper way to implement this is to allow multiple opens of the same device (just like windows). That way two or more programs can open one card and other programs can open another card and none of the programs are aware or even care about the others. I have multiple sound cards and headsets in a single computer for music and VoIP and I need a way for individual programs to work with specific devices (just like in windows).
we do agree here that jack & esound (like any interface with integrated audio mixer) should be multiple instance drivers and not single instance ones.
I guess I have a terminology misunderstanding here and should probably reread my driver documentation. I would like to see this class of driver implemented so that only a single device shows up for a physical device (multi channel cards being the exception). Each wave device could be opened more than once. Each open would dynamically open a connection to the mixing server. In this case with a single physical sound card, waveOutGetNumDevs will always return 1 and a waveOutOpen will always succeed (within mixer server limitations). This is how windows works on versions that have kmixer (98SE up).
Robert Reif wrote:
Eric Pouech wrote:
We never "load" a driver more than once. Winecfg calls winmm OpenDriver which will only ever load a single instance of the driver into memory. Subsequent OpenDriver calls will reference the existing in memory driver. Wine models the single instance device driver that supports multiple physical devices.
what you end up with is a situation where:
- two calls to OpenDriver for the same driver will provide:
- a separate HDRVR (one for each call)
- the same driver ID at the driver level
- an implementation at the driver level with a single data state shared across the two HDRVR instance
This is true and is also how windows works with the tests I have done with a user installable driver. The reason this works is because I am only accessing the static driver configuration (GetNumDevs and GetDevCaps). I have no intention of actually using the drivers for anything else because they are not designed for that.
Here again, I'm not saying you *will* badly use the drivers (and your current code doesn't). But, the way you changed things can let someone do it (or a windows app), and we have no protection for that.
I am opening the driver, not the individual devices (WaveIn, WaveOut, ...). I agree that under normal circumstances, bypassing winmm and accessing the driver directly is the wrong thing to do because winmm is responsible for coordinating things, but in this case and only this case (accessing static driver configuration) it is OK.
The real way to do this would be to have each driver register itself with the PnP manager and then we could interface with it. I am using winmm (OpenDriver) for loading and configuring the drivers which is perfectly legal to do. Only using LoadLibrary and xxxMessage to get the number of devices and their capabilities is the thing that is really questionable. A PnP manager would fix that in the long term.
My concern here is that your changes require a driver to be opened (thru OpenDriver) twice (one time by winecfg, a second time at winmm startup). IMO, the target should be to implement the audio configuration in winecfg without requiring to open twice a driver. It's likely to boil down to let winmm do the core job.
I guess I have a terminology misunderstanding here and should probably reread my driver documentation. I would like to see this class of driver implemented so that only a single device shows up for a physical device (multi channel cards being the exception). Each wave device could be opened more than once. Each open would dynamically open a connection to the mixing server. In this case with a single physical sound card, waveOutGetNumDevs will always return 1 and a waveOutOpen will always succeed (within mixer server limitations). This is how windows works on versions that have kmixer (98SE up).
yup. this is also the way to go for a unified wine audio driver by the way.
A+
Eric Pouech wrote:
Robert Reif wrote:
Eric Pouech wrote:
We never "load" a driver more than once. Winecfg calls winmm OpenDriver which will only ever load a single instance of the driver into memory. Subsequent OpenDriver calls will reference the existing in memory driver. Wine models the single instance device driver that supports multiple physical devices.
what you end up with is a situation where:
- two calls to OpenDriver for the same driver will provide:
- a separate HDRVR (one for each call)
- the same driver ID at the driver level
- an implementation at the driver level with a single data state shared across the two HDRVR instance
This is true and is also how windows works with the tests I have done with a user installable driver. The reason this works is because I am only accessing the static driver configuration (GetNumDevs and GetDevCaps). I have no intention of actually using the drivers for anything else because they are not designed for that.
Here again, I'm not saying you *will* badly use the drivers (and your current code doesn't). But, the way you changed things can let someone do it (or a windows app), and we have no protection for that.
I am opening the
driver, not the individual devices (WaveIn, WaveOut, ...). I agree that under normal circumstances, bypassing winmm and accessing the driver directly is the wrong thing to do because winmm is responsible for coordinating things, but in this case and only this case (accessing static driver configuration) it is OK.
The real way to do this would be to have each driver register itself with the PnP manager and then we could interface with it. I am using winmm (OpenDriver) for loading and configuring the drivers which is perfectly legal to do. Only using LoadLibrary and xxxMessage to get the number of devices and their capabilities is the thing that is really questionable. A PnP manager would fix that in the long term.
My concern here is that your changes require a driver to be opened (thru OpenDriver) twice (one time by winecfg, a second time at winmm startup). IMO, the target should be to implement the audio configuration in winecfg without requiring to open twice a driver. It's likely to boil down to let winmm do the core job.
I guess I have a terminology misunderstanding here and should probably reread my driver documentation. I would like to see this class of driver implemented so that only a single device shows up for a physical device (multi channel cards being the exception). Each wave device could be opened more than once. Each open would dynamically open a connection to the mixing server. In this case with a single physical sound card, waveOutGetNumDevs will always return 1 and a waveOutOpen will always succeed (within mixer server limitations). This is how windows works on versions that have kmixer (98SE up).
yup. this is also the way to go for a unified wine audio driver by the way.
A+
It is not typical for an application to bypass winmm and communicate directly with a driver. Only a control panel or device manager type application would ever even try something like this. Winecfg is one of those unusual programs. Opening a driver more than once will not cause any problems. The open functions in all the drivers are just stubs. Loading a driver is what causes a drivers state to be initialized and there is no way going through winmm to load the same driver more than once. Trying to open a specific driver's device through for example waveOutOpen more than once either through winmm or directly to the driver will only allow the first open to succeed because all attempts after the first will see that the device is already opened and fail.
It is not typical for an application to bypass winmm and communicate directly with a driver. Only a control panel or device manager type application would ever even try something like this. Winecfg is one of those unusual programs. Opening a driver more than once will not cause any problems. The open functions in all the drivers are just stubs. Loading a driver is what causes a drivers state to be initialized and there is no way going through winmm to load the same driver more than once. Trying to open a specific driver's device through for example waveOutOpen more than once either through winmm or directly to the driver will only allow the first open to succeed because all attempts after the first will see that the device is already opened and fail.
this depends on the driver: for example in wineoss, for the wod part, it will work if you specify the same format in the same thread (as we do ref counting on open). Winealsa on the other hand should be ok.
However, since winmm doesn't regenerate its internal status after an OpenDriver, one cannot use waveOut* to access that driver. A+