mirror of https://github.com/GNOME/gimp.git
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:
parent
5d06777610
commit
078cf7a8e2
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue