Table of Contents Introduction GRUB_INIT_TUNE Set using env variable in grub.cfg
91_tunes
grub config fileGRUB play
play.c GRUB source GRUB_INIT_TUNE
Play a tune directly on your pcspeaker right before the grub boot manager loads. See also: https://wiki.archlinux.org/index.php/GRUB/Tips_and_tricks#Play_a_tune
Set using env variable in grub.cfg
GRUB_INIT_TUNE
Play a specific set of frequencies for specific lengths on the machine speaker when GRUB starts. This is particularly useful for cases when you'd like to know when a reboot happens. The value is passed
directly to play .
91_tunes
grub config file
It's easy to play sounds on boot with GRUB. Here is a sample file you can save as /etc/grub.d/91_tunes
, run grub2-mkconfig -o /boot/grub.cfg
and reboot, then select "Tunes Test" to sample the various tunes.
#!/bin/sh
exec tail -n +3 $0
menuentry "Tunes Test" {
background_color "#FF9933"
echo "Close Encounters/5 Tone"
sleep 1
play 480 900 2 1000 2 800 2 400 2 600 3
background_color "#FF9900"
echo "Fur Elise (note long)"
sleep 1
play 480 420 1 400 1 420 1 400 1 420 1 315 1 370 1 335 1 282 3 180 1 215 1 282 1 315 3 213 1 262 1 315 1 335 3 213 1 420 1 400 1 420 1 400 1 420 1 315 1 370 1 335 1 282 3 180 1 215 1 282 1 315 3 213 1 330 1 315 1 282 3
background_color "#FF66FF"
echo "Totentanz"
sleep 1
play 312 262 3 247 3 262 3 220 3 247 3 196 3 220 3 220 3 262 3 262 3 294 3 262 3 247 3 220 3 196 3 247 3 262 3 247 5 220 1 220 5
background_color "#FF66CC"
echo "Oldskool Batman tune"
sleep 1
play 380 120 1 140 1 160 1 200 8 190 4
background_color "#FF6699"
echo "Legend of Zelda tune"
sleep 1
play 12000 440 100 0 1 329 150 440 50 0 1 440 25 493 25 523 25 587 25 659 200
background_color "#FF6666"
echo "Super Mario"
sleep 1
play 1000 334 1 334 1 0 1 334 1 0 1 261 1 334 1 0 1 392 2 0 4 196 2
background_color "#FF6633"
echo "Super Mario Alternate"
sleep 1
play 480 165 2 165 2 165 3 554 1 587 1 554 2 370 1 554 1 523 2 349 1 523 1 494 3 165 2 165 2 165 2
background_color "#FF6600"
echo "Mario Mushroom"
sleep 1
play 1750 523 1 392 1 523 1 659 1 784 1 1047 1 784 1 415 1 523 1 622 1 831 1 622 1 831 1 1046 1 1244 1 1661 1 1244 1 466 1 587 1 698 1 932 1 1175 1 1397 1 1865 1 1397 1
background_color "#FF33FF"
echo "Star Wars Imperial Death March"
sleep 1
play 480 440 4 440 4 440 4 349 3 523 1 440 4 349 3 523 1 440 8 659 4 659 4 659 4 698 3 523 1 415 4 349 3 523 1 440 8
background_color "#FF33CC"
echo "My Little Pony"
sleep 1
play 2400 587 18 554 4 587 8 659 12 587 16 0 10 587 4 659 4 740 8 587 4 784 12 740 8 659 8 587 4 740 20 587 40
background_color "#FF3399"
echo "Wolfenstein 3D"
sleep 1
play 300 131 1 196 1 196 1 196 1 294 1 196 1 294 1 196 1 131 1
background_color "#FF3366"
echo "Mall (Nothing Special)"
sleep 1
play 180 440 1 554 1 659 1
background_color "#FF3333"
echo "Final Countdown"
sleep 1
play 480 554 1 494 1 554 4 370 6 10 3 587 1 554 1 587 2 554 2 494 6
background_color "#FF3300"
echo "Xie-Jelei's Tune"
sleep 1
play 2000 400 4 0 1 500 4 0 1 600 4 0 1 800 6
background_color "#FF00FF"
echo "Random tune"
sleep 1
play 480 220 1 277 1 330 1 440 1 185 1 220 1 277 1 370 1 294 1 370 1 440 1 587 1 330 1 415 1 494 1 659 1
background_color "#FF00CC"
echo "Fleetwood Mac: The Chain Bass Riff (about 5 seconds)"
sleep 1
play 304 55 5 0 1 55 1 62 1 65 2 62 1 55 1 49 1 55 1 62 2 41 8
background_color "#FF0099"
echo "Fleetwood Mac: The Chain Bass Riff Extended Version (WARNING, 25 SECONDS)"
sleep 1
play 9120 55 150 0 30 55 30 62 30 65 60 62 30 55 30 49 30 55 30 62 60 41 360 0 120 55 150 0 30 55 30 62 30 65 60 62 30 55 30 49 30 55 30 62 60 41 360 0 60 41 12 42 3 43 3 44 3 45 3 46 6 47 3 48 3 49 6 50 3 51 3 52 6 53 3 54 3 55 150 0 30 55 30 62 30 65 60 62 30 55 30 49 30 55 30 62 60 41 240 82 20 0 10 82 26 0 4 82 26 0 4 82 26 0 4 82 56 0 4 82 60 55 150 0 30 55 30 62 30 65 60 62 30 55 30 49 30 55 30 62 60 41 360 0 120
background_color "#000000"
}
GRUB play
This is what plays the sounds - note much of this code was borrowed from the GNU/Hurd generic-speaker driver
Command: play file | tempo [pitch1 duration1] [pitch2 duration2] …
Plays a tune
Format is first the tempo as an unsigned 32bit little-endian number, then pairs of unsigned 16bit little-endian numbers for pitch and duration pairs.
The tempo is the base for all note durations. 60 gives a 1-second base, 120 gives a half-second base, etc. Pitches are Hz. Set pitch to 0 to produce a rest.
play.c GRUB source
More on github at play.c
/* play.c - command to play a tune */
GRUB_MOD_LICENSE ("GPLv3+");
#define BASE_TEMPO (60 * 1000)
#define T_REST ((grub_uint16_t) 0)
#define T_FINE ((grub_uint16_t) -1)
struct note
{
grub_uint16_t pitch;
grub_uint16_t duration;
};
/* Returns whether playing should continue. */
static int
play (unsigned tempo, struct note *note)
{
grub_uint64_t to;
if (note->pitch == T_FINE || grub_getkey_noblock () != GRUB_TERM_NO_KEY)
return 1;
grub_dprintf ("play", "pitch = %d, duration = %d\n", note->pitch,
note->duration);
switch (note->pitch)
{
case T_REST:
grub_speaker_beep_off ();
break;
default:
grub_speaker_beep_on (note->pitch);
break;
}
to = grub_get_time_ms () + BASE_TEMPO * note->duration / tempo;
while ((grub_get_time_ms () <= to)
&& (grub_getkey_noblock () == GRUB_TERM_NO_KEY));
return 0;
}
static grub_err_t
grub_cmd_play (grub_command_t cmd __attribute__ ((unused)),
int argc, char **args)
{
if (argc < 1)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
/* TRANSLATORS: It's musical notes, not the notes
you take. Play command expects arguments which can
be either a filename or tempo+notes.
This error happens if none is specified. */
N_("filename or tempo and notes expected"));
if (argc == 1)
{
struct note buf;
grub_uint32_t tempo;
grub_file_t file;
file = grub_file_open (args[0]);
if (! file)
return grub_errno;
if (grub_file_read (file, &tempo, sizeof (tempo)) != sizeof (tempo))
{
grub_file_close (file);
if (!grub_errno)
grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
args[0]);
return grub_errno;
}
if (!tempo)
{
grub_file_close (file);
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid tempo in %s"),
args[0]);
return grub_errno;
}
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;
}
grub_file_close (file);
}
else
{
char *end;
unsigned tempo;
struct note note;
int i;
tempo = grub_strtoul (args[0], &end, 0);
if (!tempo)
{
grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid tempo in %s"),
args[0]);
return grub_errno;
}
if (*end)
/* Was not a number either, assume it was supposed to be a file name. */
return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), args[0]);
grub_dprintf ("play","tempo = %d\n", tempo);
for (i = 1; i + 1 < argc; i += 2)
{
note.pitch = grub_strtoul (args[i], &end, 0);
if (grub_errno)
break;
if (*end)
{
grub_error (GRUB_ERR_BAD_NUMBER, N_("unrecognized number"));
break;
}
note.duration = grub_strtoul (args[i + 1], &end, 0);
if (grub_errno)
break;
if (*end)
{
grub_error (GRUB_ERR_BAD_NUMBER, N_("unrecognized number"));
break;
}
if (play (tempo, ¬e))
break;
}
}
grub_speaker_beep_off ();
return 0;
}
static grub_command_t cmd;
GRUB_MOD_INIT(play)
{
cmd = grub_register_command ("play", grub_cmd_play,
N_("FILE | TEMPO [PITCH1 DURATION1] [PITCH2 DURATION2] ... "),
N_("Play a tune."));
}
GRUB_MOD_FINI(play)
{
grub_unregister_command (cmd);
}
GRUB_INIT_TUNE - Play sound through pcspkr - AskApache