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) { if (log_level >= 3) {
port_log(p); port_log(p);
log_puts(": exit\n"); log_puts(": port exit\n");
panic();
} }
#endif #endif
} }
@ -489,6 +490,37 @@ port_del(struct port *c)
xfree(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 * struct port *
port_bynum(int num) port_bynum(int num)
{ {
@ -518,14 +550,24 @@ port_open(struct port *c)
int int
port_close(struct port *c) port_close(struct port *c)
{ {
int i;
struct midi *ep;
#ifdef DEBUG #ifdef DEBUG
if (c->state == PORT_CFG) { if (c->state == PORT_CFG) {
port_log(c); port_log(c);
log_puts(": can't close port (not opened)\n"); log_puts(": can't close port (not opened)\n");
panic();
} }
#endif #endif
port_mio_close(c);
c->state = PORT_CFG; 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; return 1;
} }

View File

@ -89,7 +89,6 @@ struct port {
unsigned int state; unsigned int state;
char *path; char *path;
struct midi *midi; 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_new(char *, unsigned int);
struct port *port_bynum(int); struct port *port_bynum(int);
void port_del(struct port *); void port_del(struct port *);
int port_ref(struct port *);
void port_unref(struct port *);
int port_init(struct port *); int port_init(struct port *);
void port_done(struct port *); void port_done(struct port *);
int port_close(struct port *); int port_close(struct port *);

View File

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

View File

@ -58,7 +58,8 @@ struct sock {
int lastvol; /* last volume */ int lastvol; /* last volume */
struct opt *opt; /* "subdevice" definition */ struct opt *opt; /* "subdevice" definition */
struct slot *slot; /* audio device slot number */ 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 */ char who[12]; /* label, mostly for debugging */
}; };