modules/controller_linux_input.c don't enter an infinite blocking loop

2004-10-26  Michael Natterer  <mitch@gimp.org>

	* modules/controller_linux_input.c
	* modules/controller_midi.c: don't enter an infinite blocking loop
	when the user selects an input file that can be opened, but not
	read (like a directory).
This commit is contained in:
Michael Natterer 2004-10-26 15:56:32 +00:00 committed by Michael Natterer
parent 5d06777610
commit 078cf7a8e2
3 changed files with 272 additions and 194 deletions

View File

@ -1,3 +1,10 @@
2004-10-26 Michael Natterer <mitch@gimp.org>
* modules/controller_linux_input.c
* modules/controller_midi.c: don't enter an infinite blocking loop
when the user selects an input file that can be opened, but not
read (like a directory).
2004-10-26 Michael Natterer <mitch@gimp.org> 2004-10-26 Michael Natterer <mitch@gimp.org>
* app/widgets/gimpactionview.[ch] (gimp_action_view_new): added * app/widgets/gimpactionview.[ch] (gimp_action_view_new): added

View File

@ -400,15 +400,52 @@ linux_input_read_event (GIOChannel *io,
GIOCondition cond, GIOCondition cond,
gpointer data) gpointer data)
{ {
struct input_event ev; ControllerLinuxInput *input = CONTROLLER_LINUX_INPUT (data);
gsize n_bytes; GIOStatus status;
gint i; GError *error = NULL;
struct input_event ev;
gsize n_bytes;
gint i;
if (g_io_channel_read_chars (io, status = g_io_channel_read_chars (io,
(gchar *) &ev, (gchar *) &ev,
sizeof (struct input_event), &n_bytes, sizeof (struct input_event), &n_bytes,
NULL) == G_IO_STATUS_NORMAL && &error);
n_bytes == sizeof (struct input_event))
switch (status)
{
case G_IO_STATUS_ERROR:
case G_IO_STATUS_EOF:
g_source_remove (input->io_id);
input->io_id = 0;
g_io_channel_unref (input->io);
input->io = NULL;
if (error)
{
gchar *name = g_strdup_printf (_("Device not available: %s"),
error->message);
g_object_set (input, "name", name, NULL);
g_free (name);
g_free (error);
}
else
{
g_object_set (input, "name", _("End of file"), NULL);
}
return FALSE;
break;
case G_IO_STATUS_AGAIN:
return TRUE;
default:
break;
}
if (n_bytes == sizeof (struct input_event))
{ {
switch (ev.type) switch (ev.type)
{ {

View File

@ -391,7 +391,8 @@ midi_set_device (ControllerMidi *midi,
g_io_channel_set_encoding (midi->io, NULL, NULL); g_io_channel_set_encoding (midi->io, NULL, NULL);
midi->io_id = g_io_add_watch (midi->io, midi->io_id = g_io_add_watch (midi->io,
G_IO_IN, G_IO_IN | G_IO_ERR |
G_IO_HUP | G_IO_NVAL,
midi_read_event, midi_read_event,
midi); midi);
return TRUE; return TRUE;
@ -446,223 +447,256 @@ midi_read_event (GIOChannel *io,
gpointer data) gpointer data)
{ {
ControllerMidi *midi = CONTROLLER_MIDI (data); ControllerMidi *midi = CONTROLLER_MIDI (data);
GIOStatus status;
GError *error = NULL;
guchar buf[0xf]; guchar buf[0xf];
gsize size; gsize size;
gint pos = 0;
if (g_io_channel_read_chars (io, status = g_io_channel_read_chars (io,
(gchar *) buf, (gchar *) buf,
sizeof (buf), &size, sizeof (buf), &size,
NULL) == G_IO_STATUS_NORMAL) &error);
switch (status)
{ {
gint pos = 0; case G_IO_STATUS_ERROR:
case G_IO_STATUS_EOF:
g_source_remove (midi->io_id);
midi->io_id = 0;
while (pos < size) g_io_channel_unref (midi->io);
midi->io = NULL;
if (error)
{ {
gchar *name = g_strdup_printf (_("Device not available: %s"),
error->message);
g_object_set (midi, "name", name, NULL);
g_free (name);
g_free (error);
}
else
{
g_object_set (midi, "name", _("End of file"), NULL);
}
return FALSE;
break;
case G_IO_STATUS_AGAIN:
return TRUE;
default:
break;
}
while (pos < size)
{
#if 0 #if 0
gint i; gint i;
g_print ("MIDI IN (%d bytes), command 0x%02x: ", size, midi->command); g_print ("MIDI IN (%d bytes), command 0x%02x: ", size, midi->command);
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
g_print ("%02x ", buf[i]); g_print ("%02x ", buf[i]);
g_print ("\n"); g_print ("\n");
#endif #endif
if (buf[pos] & 0x80) /* status byte */ if (buf[pos] & 0x80) /* status byte */
{
if (buf[pos] >= 0xf8) /* realtime messages */
{ {
if (buf[pos] >= 0xf8) /* realtime messages */ switch (buf[pos])
{
case 0xf8: /* timing clock */
case 0xf9: /* (undefined) */
case 0xfa: /* start */
case 0xfb: /* continue */
case 0xfc: /* stop */
case 0xfd: /* (undefined) */
case 0xfe: /* active sensing */
case 0xff: /* system reset */
/* nop */
#if 0
g_print ("MIDI: realtime message (%02x)\n", buf[pos]);
#endif
break;
}
}
else
{
midi->swallow = FALSE; /* any status bytes ends swallowing */
if (buf[pos] >= 0xf0) /* system messages */
{ {
switch (buf[pos]) switch (buf[pos])
{ {
case 0xf8: /* timing clock */ case 0xf0: /* sysex start */
case 0xf9: /* (undefined) */ midi->swallow = TRUE;
case 0xfa: /* start */
case 0xfb: /* continue */ D (g_print ("MIDI: sysex start\n"));
case 0xfc: /* stop */ break;
case 0xfd: /* (undefined) */
case 0xfe: /* active sensing */ case 0xf1: /* time code */
case 0xff: /* system reset */ midi->swallow = TRUE; /* type + data */
/* nop */
#if 0 D (g_print ("MIDI: time code\n"));
g_print ("MIDI: realtime message (%02x)\n", buf[pos]); break;
#endif
case 0xf2: /* song position */
midi->swallow = TRUE; /* lsb + msb */
D (g_print ("MIDI: song position\n"));
break;
case 0xf3: /* song select */
midi->swallow = TRUE; /* song number */
D (g_print ("MIDI: song select\n"));
break;
case 0xf4: /* (undefined) */
case 0xf5: /* (undefined) */
D (g_print ("MIDI: undefined system message\n"));
break;
case 0xf6: /* tune request */
D (g_print ("MIDI: tune request\n"));
break;
case 0xf7: /* sysex end */
D (g_print ("MIDI: sysex end\n"));
break; break;
} }
} }
else else /* channel messages */
{ {
midi->swallow = FALSE; /* any status bytes ends swallowing */ midi->command = buf[pos] >> 4;
midi->channel = buf[pos] & 0xf;
if (buf[pos] >= 0xf0) /* system messages */ /* reset running status */
{ midi->key = -1;
switch (buf[pos]) midi->velocity = -1;
{ midi->msb = -1;
case 0xf0: /* sysex start */ midi->lsb = -1;
midi->swallow = TRUE;
D (g_print ("MIDI: sysex start\n"));
break;
case 0xf1: /* time code */
midi->swallow = TRUE; /* type + data */
D (g_print ("MIDI: time code\n"));
break;
case 0xf2: /* song position */
midi->swallow = TRUE; /* lsb + msb */
D (g_print ("MIDI: song position\n"));
break;
case 0xf3: /* song select */
midi->swallow = TRUE; /* song number */
D (g_print ("MIDI: song select\n"));
break;
case 0xf4: /* (undefined) */
case 0xf5: /* (undefined) */
D (g_print ("MIDI: undefined system message\n"));
break;
case 0xf6: /* tune request */
D (g_print ("MIDI: tune request\n"));
break;
case 0xf7: /* sysex end */
D (g_print ("MIDI: sysex end\n"));
break;
}
}
else /* channel messages */
{
midi->command = buf[pos] >> 4;
midi->channel = buf[pos] & 0xf;
/* reset running status */
midi->key = -1;
midi->velocity = -1;
midi->msb = -1;
midi->lsb = -1;
}
} }
}
pos++; /* status byte consumed */ pos++; /* status byte consumed */
continue;
}
if (midi->swallow)
{
pos++; /* consume any data byte */
continue;
}
switch (midi->command)
{
case 0x8: /* note off */
case 0x9: /* note on */
case 0xa: /* aftertouch */
if (midi->key == -1)
{
midi->key = buf[pos++]; /* key byte consumed */
continue; continue;
} }
if (midi->swallow) if (midi->velocity == -1)
midi->velocity = buf[pos++]; /* velocity byte consumed */
/* note on with velocity = 0 means note off */
if (midi->command == 0x9 && midi->velocity == 0x0)
midi->command = 0x8;
if (midi->command == 0x9)
{ {
pos++; /* consume any data byte */ D (g_print ("MIDI (ch %02d): note on (%02x vel %02x)\n",
continue; midi->channel,
midi->key, midi->velocity));
midi_event (midi, midi->channel, midi->key,
(gdouble) midi->velocity / 127.0);
} }
else if (midi->command == 0x8)
switch (midi->command)
{ {
case 0x8: /* note off */ D (g_print ("MIDI (ch %02d): note off (%02x vel %02x)\n",
case 0x9: /* note on */
case 0xa: /* aftertouch */
if (midi->key == -1)
{
midi->key = buf[pos++]; /* key byte consumed */
continue;
}
if (midi->velocity == -1)
midi->velocity = buf[pos++]; /* velocity byte consumed */
/* note on with velocity = 0 means note off */
if (midi->command == 0x9 && midi->velocity == 0x0)
midi->command = 0x8;
if (midi->command == 0x9)
{
D (g_print ("MIDI (ch %02d): note on (%02x vel %02x)\n",
midi->channel,
midi->key, midi->velocity));
midi_event (midi, midi->channel, midi->key,
(gdouble) midi->velocity / 127.0);
}
else if (midi->command == 0x8)
{
D (g_print ("MIDI (ch %02d): note off (%02x vel %02x)\n",
midi->channel, midi->key, midi->velocity));
midi_event (midi, midi->channel, midi->key + 128,
(gdouble) midi->velocity / 127.0);
}
else
{
D (g_print ("MIDI (ch %02d): polyphonic aftertouch (%02x pressure %02x)\n",
midi->channel, midi->key, midi->velocity));
}
midi->key = -1;
midi->velocity = -1;
break;
case 0xb: /* controllers, sustain */
if (midi->key == -1)
{
midi->key = buf[pos++];
continue;
}
if (midi->velocity == -1)
midi->velocity = buf[pos++];
D (g_print ("MIDI (ch %02d): controller %d (value %d)\n",
midi->channel, midi->key, midi->velocity)); midi->channel, midi->key, midi->velocity));
midi_event (midi, midi->channel, midi->key + 128 + 128, midi_event (midi, midi->channel, midi->key + 128,
(gdouble) midi->velocity / 127.0); (gdouble) midi->velocity / 127.0);
midi->key = -1;
midi->velocity = -1;
break;
case 0xc: /* program change */
midi->key = buf[pos++];
D (g_print ("MIDI (ch %02d): program change (%d)\n",
midi->channel, midi->key));
midi->key = -1;
break;
case 0xd: /* channel key pressure */
midi->velocity = buf[pos++];
D (g_print ("MIDI (ch %02d): channel aftertouch (%d)\n",
midi->channel, midi->velocity));
midi->velocity = -1;
break;
case 0xe: /* pitch bend */
if (midi->lsb == -1)
{
midi->lsb = buf[pos++];
continue;
}
if (midi->msb == -1)
midi->msb = buf[pos++];
midi->velocity = midi->lsb | (midi->msb << 7);
D (g_print ("MIDI (ch %02d): pitch (%d)\n",
midi->channel, midi->velocity));
midi->msb = -1;
midi->lsb = -1;
midi->velocity = -1;
break;
} }
else
{
D (g_print ("MIDI (ch %02d): polyphonic aftertouch (%02x pressure %02x)\n",
midi->channel, midi->key, midi->velocity));
}
midi->key = -1;
midi->velocity = -1;
break;
case 0xb: /* controllers, sustain */
if (midi->key == -1)
{
midi->key = buf[pos++];
continue;
}
if (midi->velocity == -1)
midi->velocity = buf[pos++];
D (g_print ("MIDI (ch %02d): controller %d (value %d)\n",
midi->channel, midi->key, midi->velocity));
midi_event (midi, midi->channel, midi->key + 128 + 128,
(gdouble) midi->velocity / 127.0);
midi->key = -1;
midi->velocity = -1;
break;
case 0xc: /* program change */
midi->key = buf[pos++];
D (g_print ("MIDI (ch %02d): program change (%d)\n",
midi->channel, midi->key));
midi->key = -1;
break;
case 0xd: /* channel key pressure */
midi->velocity = buf[pos++];
D (g_print ("MIDI (ch %02d): channel aftertouch (%d)\n",
midi->channel, midi->velocity));
midi->velocity = -1;
break;
case 0xe: /* pitch bend */
if (midi->lsb == -1)
{
midi->lsb = buf[pos++];
continue;
}
if (midi->msb == -1)
midi->msb = buf[pos++];
midi->velocity = midi->lsb | (midi->msb << 7);
D (g_print ("MIDI (ch %02d): pitch (%d)\n",
midi->channel, midi->velocity));
midi->msb = -1;
midi->lsb = -1;
midi->velocity = -1;
break;
} }
} }