grub_outb (status | SPEAKER_TMR2 | SPEAKER_DATA, SPEAKER);
}
-static grub_err_t
-grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
- int argc, char **args)
+/* Returns whether playing should continue. */
+static int
+play (unsigned tempo, struct note *note)
{
- 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 (note->pitch == T_FINE || grub_checkkey () >= 0)
+ return 1;
- file = grub_file_open (args[0]);
- if (! file)
- return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
+ grub_dprintf ("play", "pitch = %d, duration = %d\n", note->pitch,
+ note->duration);
- if (grub_file_read (file, &tempo, sizeof(tempo)) != sizeof(tempo))
+ switch (note->pitch)
{
- grub_file_close (file);
- return grub_error (GRUB_ERR_FILE_READ_ERROR,
- "file doesn't even contains a full tempo record");
+ case T_REST:
+ beep_off ();
+ break;
+
+ default:
+ beep_on (note->pitch);
+ break;
}
- tempo = grub_le_to_cpu32(tempo);
+ to = grub_get_rtc () + BASE_TEMPO * note->duration / tempo;
+ while (((unsigned int) grub_get_rtc () <= to) && (grub_checkkey () < 0))
+ ;
- grub_dprintf ("play","tempo = %d\n", tempo);
+ return 0;
+}
+
+static grub_err_t
+grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
+ int argc, char **args)
+{
+ grub_file_t file;
- while (grub_file_read (file, &buf,
- sizeof (struct note)) == sizeof (struct note))
+ 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)
{
- buf.pitch = grub_le_to_cpu16(buf.pitch);
- buf.duration = grub_le_to_cpu16(buf.duration);
+ struct note buf;
+ grub_uint32_t tempo;
- if (buf.pitch == T_FINE || grub_checkkey () >= 0)
- break;
+ if (grub_file_read (file, &tempo, sizeof (tempo)) != sizeof (tempo))
+ {
+ grub_file_close (file);
+ return grub_error (GRUB_ERR_FILE_READ_ERROR,
+ "file doesn't even contains a full tempo record");
+ }
- grub_dprintf ("play", "pitch = %d, duration = %d\n", buf.pitch,
- buf.duration);
+ tempo = grub_le_to_cpu32 (tempo);
+ grub_dprintf ("play","tempo = %d\n", tempo);
- switch (buf.pitch)
+ while (grub_file_read (file, &buf,
+ sizeof (struct note)) == sizeof (struct note))
{
- case T_REST:
- beep_off ();
- break;
+ buf.pitch = grub_le_to_cpu16 (buf.pitch);
+ buf.duration = grub_le_to_cpu16 (buf.duration);
- default:
- beep_on (buf.pitch);
+ 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, ¬e))
+ break;
+ }
}
beep_off ();
- grub_file_close (file);
-
while (grub_checkkey () > 0)
grub_getkey ();