Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Dear monks, I'm setting up a Linux-based home karaoke system to help my flatmates celebrate finishing medical school.

Timidity (a software midi synthesizer for linux) does a great job of playing midi-format karaoke files, but it its lyric display leaves a lot to be desired, and I've not managed to find any gui that can do the job either. So, I'd like to write a Perl program to display them.

Reading the lyrics from the midi file is easy, using MIDI::Event, but how best to display them?

The requirements are simple. I need to:

1. Open a big window
2. Draw a background image on it
3. Draw some text on top of that and update it every so often

I've got no experience at all using graphics with Perl, so can anybody point me in the right direction?

Many thanks,

mj

  • Comment on Which Perl modules to use to display karaoke lyrics?

Replies are listed 'Best First'.
Re: Which Perl modules to use to display karaoke lyrics?
by marto (Cardinal) on Jun 13, 2005 at 10:59 UTC
    Hi,

    Perhaps you could implement this using Perl/TK.
    There is a tutorial here which may be a good starting point.

    Hope this helps,

    Cheers,

    Martin
Re: Which Perl modules to use to display karaoke lyrics?
by dorward (Curate) on Jun 13, 2005 at 11:23 UTC

    This sounds like a great excuse to use X::OSD. You could consider a fullscreen visualisation and then OSD the lyrics on top for an insanely funky display.

Re: Which Perl modules to use to display karaoke lyrics?
by robot_tourist (Hermit) on Jun 13, 2005 at 10:59 UTC

    TK may look scary initially, but it's not. Plus, because there is more than one way to do it, you can use one of the many other windowing systems available.

    Or for a bit more geek l33t, why not try drawing big letters directly to the screen. That might be easier with a bit of C on the side.

    How can you feel when you're made of steel? I am made of steel. I am the Robot Tourist.
    Robot Tourist, by Ten Benson

      Sort of off topic, unless Perl works on iPods: what I would like is karaoke lyrics on my iPod! I have suggested it on Apple's iPod feedback form, but I haven't heard anything about it yet.

      How can you feel when you're made of steel? I am made of steel. I am the Robot Tourist.
      Robot Tourist, by Ten Benson

Re: Which Perl modules to use to display karaoke lyrics?
by zentara (Cardinal) on Jun 13, 2005 at 12:06 UTC
    Post the code you are using for extracting the karoake text, and I'll show you how to put the output onto a gui. It seems the problem is to be able to "synchronize" the output. I have a few ideas, maybe I'll post something later.

    I'm not really a human, but I play one on earth. flash japh
      Taken pretty much from the MIDI:Event documentation:
      use MIDI; # which "use"s MIDI::Event; my @lyrics; MIDI::Opus->new( { "from_file" => $ARGV[0], "exclusive_event_callback" => sub{push @lyrics, $_[2],$_[1]\n"}, "include" => \@MIDI::Event::Text_events } );

      so now @lyrics contains elements looking like this:

      "Happy,300" "Birthday,400" "To,80" "You,500"
      I think the numbers represent the length of time to wait before adding the next bit of text, though I'm not sure what the units are - presumably not absolute times, because the file may get played at different tempos, so maybe they're "midi ticks" or similar.

      I've noticed that when playing a karaoke file in Timidity from the command line, it actually prints the lyric events (presumably to STDOUT) so another idea might be to just capture this and print it, letting Timitidy take care of the syncronisation.

      Thanks for all your suggestions.

      mj

        I usually use the "drvmidi" utlity to play midis and karaoke. It is an old sound blaster awedrv package. It plays kar files pretty good. I tried to capture the output of it, but there is some problem because the apps output actually goes to the soundcard so it is full of binary data. It would be neat if the lyrics were printed to stderr to avoid that complication. I'll try timidity and the MIDI::Event code above and post my results( whether success or not :-) )

        As a last resort, I have been able to run drvmidi in a window in a tk canvas, and I'm sure timidity would work too. So this isn't much better than the command line, but it could be made better by using bigger fonts in the xterm and going full screen and changing the solid color to a photo.

        #!/usr/bin/perl -w use strict; use Tk; my $mw = MainWindow->new(); my $canv = $mw->Canvas(-bg => 'lightsteelblue', -relief => 'sunken', -width => 550, -height => 350)->pack(-expand => 1, -fill => 'both'); my $xtermWidth = 400; my $xtermHeight = 300; ## this Frame is needed for including the xterm in Tk::Canvas my $xtermContainer = $canv->Frame(-container => 1); my $xtid = $xtermContainer->id(); # converting the id from HEX to decimal as xterm requires a decimal Id + my ($xtId) = sprintf hex $xtid; my $dcontitem = $canv->createWindow(275,175, -window => $xtermContainer, -width => $xtermWidth+100, -height => $xtermHeight, -state => 'normal'); my $label = $canv->createText( 275,10, -text => "Hide xterm", ); $canv->Tk::bind("<Button-1>", \&hideShow); my $width = $xtermWidth; my $height = $xtermHeight; $mw->Button(-text => "Exit", -command => [sub{Tk::exit}] )->pack( ); my $tl; #used to mask xterm system("xterm -into $xtId -e timidity z.kar &"); MainLoop(); sub hideShow { if ($canv->itemcget($label, -text) =~ /Hide/) { $canv->itemconfigure($label, -fill => 'white', -text => "Show xterm"); $tl = $mw->Toplevel(-use=>$xtId ); } else { $canv->itemconfigure($label, -fill => 'black', -text => "Hide xterm"); $tl->withdraw; } }

        I'm not really a human, but I play one on earth. flash japh
Re: Which Perl modules to use to display karaoke lyrics?
by mattr (Curate) on Jun 13, 2005 at 15:50 UTC
    If you are looking at Tk you also might be interested in TkZinc. I have not used it, but it might be fun to play around with ways to display animated karaoke lyrics. It does allow opengl but I have not found info about video.
    "If you need alpha-transparency, color gradient, rotating or zooming images and graphics, structuring your graphic Canvas application in hierarchical groups, using affine transformations, displaying multicontour surfaces, complex clipping, or designing a performant radar display, then TkZinc is the widget you need, while being very similar to the Canvas."
    wxperl might also work for you. Incidentally it isn't perl but I believe mplayer can be used to show subtitles from a text subtitle file in nice antialiased fonts, like OSD apparently, though I am not sure if this can be driven live i.e. from stdout of a perl script.

    Hope this helps, tell us how it goes!

Re: Which Perl modules to use to display karaoke lyrics?
by zentara (Cardinal) on Jun 13, 2005 at 19:29 UTC
    Yeah, I tried all the different players and they all have the same problem, it is hard to grab the text output from them. Timidity willl print the midi info out to stdout, and it can be captured and displayed, but as soon as the music starts, the output stops. I'm not sure where they are sending it? It's not in STDERR either. Anyways, here is a pleasant looking hack of my previous "quicky". I just let timidity do it's thing in a window, so there are no synchro problems. I've set it up for 1024x768, and thru in a fun image to show you how to do it. I made a big font in the xterm, and gave it some fun colors for karaoke.
    #!/usr/bin/perl -w use strict; use Tk; use Tk::PNG; #works for a 1024x768 display my $kar = shift || 'z.kar'; my $mw = MainWindow->new(); my $xscr = $mw->screenwidth; my $yscr = $mw->screenheight; $mw->geometry($xscr.'x'.$yscr.'+'.'20'.'+'.'20' ); $mw->fontCreate('big', -family=>'courier', -weight=>'bold', -size=>int(-18*18/14)); my $canv = $mw->Canvas(-bg => 'lightsteelblue', -relief => 'sunken', -width => $xscr - 100, -height =>$yscr - 100, )->pack(-expand => 1, -fill => 'both'); my $bunny = $mw->Photo(-data => 'iVBORw0KGgoAAAANSUhEUgAAAB4AAAAjEAIAAABcJvHFAAAACXBIWXMAAAsSAAALEgHS3 +X78AAAD F0lEQVR42u1YL+yqUBj1vfcLbhY3C44is8BIREYSG9FoNBqNkok2aFhp2BhJDWyadCZN/i +lOGxan jRdOuRsPxl/f+23vJKfX7x6+73znu5dK5RviV9QPDMMwDIPP7/f7/X6XTWU0Go1Go06n0+ +l0PM/z PC91CNu2bduWZVmW5bLpjsfj8XgcBEEQBJPJZDKZZAw0n8/n8zkCGYZhGIYgCIIgFEt3OB +wOh8OA gKZpmqZlDDedTqfTKRnO933f95GVer1er9fz0BVFURRFxCR3QfyMQfv9fr/fDyLgOI7jON +mo419k JUkMBoPBYJCRNBrxdrvdbrco6qvVarVaIWdFpQO/5tIcFBbE4nQ6nU6nJIpHjlGlEklTFE +VRFDIa T32/3+/3+3jqHMdxHBcfB2sK6HFFURRFeb1er9crfksoNUrr0GvUfxGfnA+FmX+QALDItG +LDA6O2 pQyCJFkPqxMDK2p9LodOAhQaLRjfoKRGo2wObl3G8PoDsA0Gb5Q5oonjfSNKTh96AOh+u9 +1ut1uS FuZrONPJ7bJ06tA9TDDsD6QkCnDltEDRkV1Q9AnENyuk8hcyChkkcZKo5uv1er1er3S6cA +PkFXSx MQodPrXFg2zTEsVANhO2JNdEmVo80ub7K/lSDHPyLkNaXrVarVar2W46LMuyLFsKaZ7neZ +4nvwFR NGKeGjYajUajkXz9z+RLn8/n8/ms/ANIQXq5XC6Xy/v9fr/fvw3p9Xq9Xq9VVVVV9fF4PB +6Pokhc r9fr9Vr6s6Lf4dNpbS6/exQA3BHDt/fkPl3wwT85wlcEcrCHZyHO1tmOSl95iGLcQN80Td +M0jTa1 LMuyLF3XdV03TdM0zWaz2Ww2Xdd1XRenDlDHgTbtvj/ykMZpDm/6LpfL5XLBmGi32+12G6 +Th5RAA Pne73W63iwfGYFosFovF4kOZrtVqtVoN16TD4XA4HPAAKDp5yZUkSZIk1GGz2Ww2m91ut9 +vt0Mof lcfxeDwej7PZbDaboRFbrVar1SJfIsLdYZfn8/l8Pue3y1zyiH9VAMFElb5Yp/+PcvAbH/ +25ox5S PYYAAAAASUVORK5CYII='); for my $x (1..15){ $canv->createImage(30, 30 + $x * 40, -image=> $bunny, ); $canv->createImage(930, 30 + $x * 40, -image=> $bunny, ); } my $xtermWidth = 600; my $xtermHeight = 500; ## this Frame is needed for including the xterm in Tk::Canvas my $xtermContainer = $canv->Frame(-container => 1); my $xtid = $xtermContainer->id(); # converting the id from HEX to decimal as xterm requires a decimal Id + my ($xtId) = sprintf hex $xtid; my $dcontitem = $canv->createWindow(475,275, -window => $xtermContainer, -width => $xtermWidth+100, -height => $xtermHeight, -state => 'normal'); my $label = $canv->createText( 475,10, -text => "Click Background To Hide Lyrics", -font => 'big', ); $canv->Tk::bind("<Button-1>", \&hideShow); my $width = $xtermWidth; my $height = $xtermHeight; my $bframe = $mw->Frame(-bg=>'black')->pack(-expand => 1, -fill => 'x' +); $bframe->Button(-text => "Exit", -bg => 'lightsteelblue', -command => [sub{Tk::exit}] )->pack(-side=>'right', -p +adx=>20 ); my $startbut; $startbut = $bframe->Button(-text => "Start", -bg => 'hotpink', -command => sub{ $startbut->configure(-state =>'disabled'); system("xterm -fn 10x20 -bg 'black' -fg 'hotpink' -into $xtId -e +timidity $kar &"); } )->pack(-side=>'left', -padx=>20); my $tl; #used to mask xterm MainLoop(); sub hideShow { if ($canv->itemcget($label, -text) =~ /Hide/) { $canv->itemconfigure($label, -fill => 'white', -text => "Click Background to Show Lyrics"); $tl = $mw->Toplevel(-use=>$xtId ); } else { $canv->itemconfigure($label, -fill => 'black', -text => "Click Background to Hide Lyrics"); $tl->withdraw; } }

    I'm not really a human, but I play one on earth. flash japh
Re: Which Perl modules to use to display karaoke lyrics?
by zentara (Cardinal) on Jun 18, 2005 at 17:00 UTC
    Hi, I finally figured out a way to get the timidity output, onto a scrolling canvas with a background image. See Tk-Karoake Player-w-timidity

    I'm not really a human, but I play one on earth. flash japh
Re: Which Perl modules to use to display karaoke lyrics?
by chanio (Priest) on Jun 15, 2005 at 05:16 UTC
    I'll try all the ideas!

    I would add some primary colors to every sillable of the lyrics and its background.

    I don't like to be a spoiler, but searching for some .kar files I stumbled with a new (+free) JAVA multiplatform option that plays midi, mp3, etc. Before depending completely on your brand new application, you might try installing this java alternative that as it looks, it comes very complete: MIDI JAVA player . It says that it needs the new JAVA JDK 5 (not the JRE) and ANT 1.5 installed. Some Mb consuming, but I guess that it should work fine since the JAVA Midi API was excellent. (besides the Mb consuming I am planning to try it soon, because it is a very promising alternative for LINUX where the system is not able to deal with my Windows midi card).

    Sorry for not promoting perl this time.

    .{\('v')/}   C H E E R   U P !
     _`(___)' ___a_l_b_e_r_t_o_________
    
    Wherever I lay my KNOPPIX disk, a new FREE LINUX nation could be established.