[PATCH v2] winealsa.drv: use separate port for each output device.
Andrew Eikum
aeikum at codeweavers.com
Mon Dec 20 08:42:58 CST 2021
Whoops, I missed the ongoing discussion on the bug :) I will wait to
hear back if this revised version is working for you.
Andrew
On Mon, Dec 20, 2021 at 08:41:38AM -0600, Andrew Eikum wrote:
> Kakurasan, can you try out Jacek's patch?
>
> https://source.winehq.org/patches/data/222355
>
> Thanks,
> Andrew
>
> On Sun, Dec 19, 2021 at 03:20:28PM +0100, Jacek Konieczny wrote:
> > This fixes use of multiple MIDI outputs while keeping the flexibility of
> > proper ALSA sequencer port subscriptions.
> >
> > Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52220
> > Signed-off-by: Jacek Konieczny <jajcus at jajcus.net>
> > ---
> > v2: do not fail on port connection errors. Fixes failures to open a
> > device when the port is already connected to the target, either by wine
> > or some external application
> > ---
> > dlls/winealsa.drv/midi.c | 55 +++++++++++++++++++++++++++-------------
> > 1 file changed, 38 insertions(+), 17 deletions(-)
> >
> > diff --git a/dlls/winealsa.drv/midi.c b/dlls/winealsa.drv/midi.c
> > index f2fe6307bb2..ac666b49d79 100644
> > --- a/dlls/winealsa.drv/midi.c
> > +++ b/dlls/winealsa.drv/midi.c
> > @@ -85,6 +85,7 @@ typedef struct {
> > void* lpExtra; /* according to port type (MIDI, FM...), extra data when needed */
> > MIDIOUTCAPSW caps;
> > snd_seq_addr_t addr;
> > + int port_out;
> > } WINE_MIDIOUT;
> >
> > static WINE_MIDIIN MidiInDev [MAX_MIDIINDRV ];
> > @@ -108,7 +109,6 @@ static int numOpenMidiSeq = 0;
> > static int numStartedMidiIn = 0;
> >
> > static int port_in;
> > -static int port_out;
> >
> > static CRITICAL_SECTION crit_sect; /* protects all MidiIn buffer queues */
> > static CRITICAL_SECTION_DEBUG critsect_debug =
> > @@ -247,14 +247,6 @@ static int midiOpenSeq(BOOL create_client)
> > /* Setting the client name is the only init to do */
> > snd_seq_set_client_name(midiSeq, "WINE midi driver");
> >
> > - port_out = snd_seq_create_simple_port(midiSeq, "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");
> > - else
> > - TRACE("Outport port %d created successfully\n", port_out);
> > -
> > 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);
> > @@ -276,7 +268,6 @@ static int midiCloseSeq(void)
> > {
> > EnterCriticalSection(&midiSeqLock);
> > if (--numOpenMidiSeq == 0) {
> > - snd_seq_delete_simple_port(midiSeq, port_out);
> > snd_seq_delete_simple_port(midiSeq, port_in);
> > snd_seq_close(midiSeq);
> > midiSeq = NULL;
> > @@ -738,6 +729,8 @@ static DWORD modGetDevCaps(WORD wDevID, LPMIDIOUTCAPSW lpCaps, DWORD dwSize)
> > static DWORD modOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
> > {
> > int ret;
> > + int port_out;
> > + char port_out_name[32];
> >
> > TRACE("(%04X, %p, %08X);\n", wDevID, lpDesc, dwFlags);
> > if (lpDesc == NULL) {
> > @@ -784,12 +777,37 @@ static DWORD modOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
> > MidiOutDev[wDevID].bufsize = 0x3FFF;
> > MidiOutDev[wDevID].midiDesc = *lpDesc;
> >
> > - /* Connect our app port to the device port */
> > EnterCriticalSection(&midiSeqLock);
> > - ret = snd_seq_connect_to(midiSeq, port_out, MidiOutDev[wDevID].addr.client,
> > - MidiOutDev[wDevID].addr.port);
> > + /* 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(midiSeq, 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("Outport 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(midiSeq, 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));
> > + }
> > LeaveCriticalSection(&midiSeqLock);
> > - if (ret < 0)
> > +
> > + 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);
> > @@ -825,7 +843,9 @@ static DWORD modClose(WORD wDevID)
> > case MOD_MIDIPORT:
> > case MOD_SYNTH:
> > EnterCriticalSection(&midiSeqLock);
> > - snd_seq_disconnect_to(midiSeq, port_out, MidiOutDev[wDevID].addr.client, MidiOutDev[wDevID].addr.port);
> > + 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);
> > + MidiOutDev[wDevID].port_out = -1;
> > LeaveCriticalSection(&midiSeqLock);
> > midiCloseSeq();
> > break;
> > @@ -870,7 +890,7 @@ static DWORD modData(WORD wDevID, DWORD dwParam)
> > snd_seq_event_t event;
> > snd_seq_ev_clear(&event);
> > snd_seq_ev_set_direct(&event);
> > - snd_seq_ev_set_source(&event, port_out);
> > + snd_seq_ev_set_source(&event, MidiOutDev[wDevID].port_out);
> > snd_seq_ev_set_subs(&event);
> >
> > switch (evt & 0xF0) {
> > @@ -1039,7 +1059,7 @@ static DWORD modLongData(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
> > }
> > snd_seq_ev_clear(&event);
> > snd_seq_ev_set_direct(&event);
> > - snd_seq_ev_set_source(&event, port_out);
> > + snd_seq_ev_set_source(&event, MidiOutDev[wDevID].port_out);
> > snd_seq_ev_set_subs(&event);
> > snd_seq_ev_set_sysex(&event, lpMidiHdr->dwBufferLength + len_add, lpNewData ? lpNewData : lpData);
> > EnterCriticalSection(&midiSeqLock);
> > @@ -1201,6 +1221,7 @@ static void ALSA_AddMidiPort(snd_seq_client_info_t* cinfo, snd_seq_port_info_t*
> > 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",
> > --
> > 2.25.1
> >
More information about the wine-devel
mailing list