2010-02-14 Samuel Thibault <samuel.thibault@ens-lyon.org>

* commands/i386/pc/play.c (grub_cmd_play): If grub_file_open fails,
	parse arguments as inline tempo and notes.  Move code for playing notes
	to...
	(play): ... new function.
This commit is contained in:
Samuel Thibault 2010-02-14 18:14:16 +01:00
parent 14da0fb7e8
commit 37c8483b97
2 changed files with 92 additions and 40 deletions

View File

@ -1,3 +1,10 @@
2010-02-14 Samuel Thibault <samuel.thibault@ens-lyon.org>
* commands/i386/pc/play.c (grub_cmd_play): If grub_file_open fails,
parse arguments as inline tempo and notes. Move code for playing notes
to...
(play): ... new function.
2010-02-14 Samuel Thibault <samuel.thibault@ens-lyon.org>
* commands/i386/pc/play.c (T_REST, T_FINE, struct note, beep_on): Use

View File

@ -143,66 +143,111 @@ beep_on (grub_uint16_t pitch)
grub_outb (status | SPEAKER_TMR2 | SPEAKER_DATA, SPEAKER);
}
/* Returns whether playing should continue. */
static int
play (unsigned tempo, struct note *note)
{
unsigned int to;
if (note->pitch == T_FINE || grub_checkkey () >= 0)
return 1;
grub_dprintf ("play", "pitch = %d, duration = %d\n", note->pitch,
note->duration);
switch (note->pitch)
{
case T_REST:
beep_off ();
break;
default:
beep_on (note->pitch);
break;
}
to = grub_get_rtc () + BASE_TEMPO * note->duration / tempo;
while (((unsigned int) grub_get_rtc () <= to) && (grub_checkkey () < 0))
;
return 0;
}
static grub_err_t
grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
int argc, char **args)
{
grub_file_t file;
struct note buf;
grub_uint32_t tempo;
unsigned int to;
if (argc != 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required");
if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name or tempo and notes required");
file = grub_file_open (args[0]);
if (! file)
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
if (grub_file_read (file, &tempo, sizeof(tempo)) != sizeof(tempo))
if (file)
{
grub_file_close (file);
return grub_error (GRUB_ERR_FILE_READ_ERROR,
"file doesn't even contains a full tempo record");
}
struct note buf;
grub_uint32_t tempo;
tempo = grub_le_to_cpu32(tempo);
grub_dprintf ("play","tempo = %d\n", tempo);
while (grub_file_read (file, &buf,
sizeof (struct note)) == sizeof (struct note))
{
buf.pitch = grub_le_to_cpu16(buf.pitch);
buf.duration = grub_le_to_cpu16(buf.duration);
if (buf.pitch == T_FINE || grub_checkkey () >= 0)
break;
grub_dprintf ("play", "pitch = %d, duration = %d\n", buf.pitch,
buf.duration);
switch (buf.pitch)
if (grub_file_read (file, &tempo, sizeof (tempo)) != sizeof (tempo))
{
case T_REST:
beep_off ();
break;
grub_file_close (file);
return grub_error (GRUB_ERR_FILE_READ_ERROR,
"file doesn't even contains a full tempo record");
}
default:
beep_on (buf.pitch);
tempo = grub_le_to_cpu32 (tempo);
grub_dprintf ("play","tempo = %d\n", tempo);
while (grub_file_read (file, &buf,
sizeof (struct note)) == sizeof (struct note))
{
buf.pitch = grub_le_to_cpu16 (buf.pitch);
buf.duration = grub_le_to_cpu16 (buf.duration);
if (play (tempo, &buf))
break;
}
to = grub_get_rtc () + BASE_TEMPO * buf.duration / tempo;
while (((unsigned int) grub_get_rtc () <= to) && (grub_checkkey () < 0))
;
grub_file_close (file);
}
else
{
char *end;
unsigned tempo;
struct note note;
int i;
tempo = grub_strtoul (args[0], &end, 0);
if (*end)
/* Was not a number either, assume it was supposed to be a file name. */
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
grub_dprintf ("play","tempo = %d\n", tempo);
for (i = 1; i + 1 < argc; i += 2)
{
note.pitch = grub_strtoul (args[i], &end, 0);
if (*end)
{
grub_error (GRUB_ERR_BAD_NUMBER, "bogus pitch number");
break;
}
note.duration = grub_strtoul (args[i + 1], &end, 0);
if (*end)
{
grub_error (GRUB_ERR_BAD_NUMBER, "bogus duration number");
break;
}
if (play (tempo, &note))
break;
}
}
beep_off ();
grub_file_close (file);
while (grub_checkkey () > 0)
grub_getkey ();