[PATCH v2] winealsa.drv: use separate port for each output device.

Masanori Kakura kakurasan at gmail.com
Thu Dec 23 07:20:59 CST 2021


Hello Andrew.



Now the v2 patch looks good to me (and works).
May I have your opinion?



Masanori

On 2021/12/20 23:42, Andrew Eikum wrote:
> 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