For MIDI ports, use the same open/close logic as for audio devices:

drop clients using it when the port is closed (eg. umidi disconnected)
and try to reopen it whenever a new client connects.
This commit is contained in:
Alexandre Ratchov 2012-11-30 21:51:46 +01:00
parent ccdecf59c4
commit 49190bbba1
4 changed files with 55 additions and 5 deletions

View File

@ -443,7 +443,8 @@ port_exit(void *arg)
if (log_level >= 3) {
port_log(p);
log_puts(": exit\n");
log_puts(": port exit\n");
panic();
}
#endif
}
@ -489,6 +490,37 @@ port_del(struct port *c)
xfree(c);
}
int
port_ref(struct port *c)
{
#ifdef DEBUG
if (log_level >= 3) {
port_log(c);
log_puts(": port requested\n");
}
#endif
if (c->state == PORT_CFG && !port_open(c))
return 0;
return 1;
}
void
port_unref(struct port *c)
{
int i, rxmask;
#ifdef DEBUG
if (log_level >= 3) {
port_log(c);
log_puts(": port released\n");
}
#endif
for (rxmask = 0, i = 0; i < MIDI_NEP; i++)
rxmask |= midi_ep[i].txmask;
if ((rxmask & c->midi->self) == 0 && c->state == PORT_INIT)
port_close(c);
}
struct port *
port_bynum(int num)
{
@ -518,14 +550,24 @@ port_open(struct port *c)
int
port_close(struct port *c)
{
int i;
struct midi *ep;
#ifdef DEBUG
if (c->state == PORT_CFG) {
port_log(c);
log_puts(": can't close port (not opened)\n");
panic();
}
#endif
port_mio_close(c);
c->state = PORT_CFG;
port_mio_close(c);
for (i = 0; i < MIDI_NEP; i++) {
ep = midi_ep + i;
if ((ep->txmask & c->midi->self) ||
(c->midi->txmask & ep->self))
ep->ops->exit(ep->arg);
}
return 1;
}

View File

@ -89,7 +89,6 @@ struct port {
unsigned int state;
char *path;
struct midi *midi;
unsigned int refs;
};
/*
@ -113,6 +112,8 @@ void midi_link(struct midi *, struct midi *);
struct port *port_new(char *, unsigned int);
struct port *port_bynum(int);
void port_del(struct port *);
int port_ref(struct port *);
void port_unref(struct port *);
int port_init(struct port *);
void port_done(struct port *);
int port_close(struct port *);

View File

@ -151,6 +151,10 @@ sock_close(struct sock *f)
midi_del(f->midi);
f->midi = NULL;
}
if (f->port) {
port_unref(f->port);
f->port = NULL;
}
file_del(f->file);
close(f->fd);
xfree(f);
@ -850,6 +854,7 @@ sock_hello(struct sock *f)
}
f->pstate = SOCK_INIT;
if (mode & MODE_MIDIMASK) {
f->port = NULL;
f->slot = NULL;
f->midi = midi_new(&sock_midiops, f, mode);
if (f->midi == NULL)
@ -864,8 +869,9 @@ sock_hello(struct sock *f)
midi_tag(f->midi, p->devnum);
} else if (p->devnum < 48) {
c = port_bynum(p->devnum - 32);
if (c == NULL)
if (c == NULL || !port_ref(c))
return 0;
f->port = c;
midi_link(f->midi, c->midi);
} else
return 0;

View File

@ -58,7 +58,8 @@ struct sock {
int lastvol; /* last volume */
struct opt *opt; /* "subdevice" definition */
struct slot *slot; /* audio device slot number */
struct midi *midi; /* midi endpoint number */
struct midi *midi; /* midi endpoint */
struct port *port; /* midi port */
char who[12]; /* label, mostly for debugging */
};