Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

pMusic - an MP3 player for disabled people

by Jouke (Curate)
on Apr 26, 2004 at 11:08 UTC ( [id://348135]=CUFP: print w/replies, xml ) Need Help??

This is the first application that uses the AAC::Pvoice modules after creating those modules for pVoice originally. It's an MP3 player, which was a present for my daughter's birthday last Friday.
It was a rather quick hack, so if you find strange constructs or things that don't work the way it should, please forgive me :)

It also needs the Audio::BASSXS module, which should arrive on a CPAN near you real soon :)

Update: a screenshot
#!/usr/bin/perl #--------------------------------------------------------------------- +-------- # # pMusic 0.1 # # pMusic is an MP3 player for people with disabilities, who are not ab +le to # use a mouse or a keyboard the way healthy people can. It was origina +lly # written for my daughter Krista, who can control a computer by moving + her head # to the left and right, which causes a special headsupport to generat +e events. # # This application makes extensive use of the AAC::Pvoice modules, whi +ch can # be found on CPAN. It also needs the Audio::BASSXS module for playing + the MP3s. # # More of these kinds of applications can be found on http://www.pvoic +e.org # # This application needs a set of icons, which can be downloaded from # http://jouke.pvoice.org/files/pMusic-icons.zip. They are created by # ngMedia (http://www.ngmedia.com). # # Finally, you'll need to have the INPOUT32.DLL, which can be download +ed from # http://jouke.pvoice.org/files/INPOUT32.DLL # # Author: Jouke Visser # Version: 0.1 # Last modification: April 26, 2004 # #--------------------------------------------------------------------- +--------
use strict; use warnings; use Wx; our $VERSION = sprintf("%d.%02d", q$Revision: 0.01 $=~/(\d+)\.(\d+ +)/); # display the splashscreen use Wx::Perl::SplashFast ('img/splash.png', 3000); our $leftpanecolour = Wx::Colour->new(145,211,143); our $rightpanecolour = Wx::Colour->new(215,239,214); our $basepath = $ARGV[0] || 'C:\\mp3\\'; #--------------------------------------------------------------------- +-------- # This is the pMusic package where the frame is called package pMusic; use Wx; use base qw(Wx::App); use Wx::Perl::Carp; #--------------------------------------------------------------------- +-------- sub OnInit { my $self = shift; Wx::InitAllImageHandlers; my $Appname = "pMusic"; my $Appvendor = "pVoice Applications - Jouke Visser"; $self->SetAppName('pMusic'); $self->SetVendorName($Appvendor); my $config = Wx::ConfigBase::Get; my $Device = $config->Read('Device', 'icon' ); $config->Write('Device', $Device ); my $frame = pMusicFrame->new( undef, -1, $self->GetAppName ); $frame->Show(1); return 1; } #--------------------------------------------------------------------- +-------- # This is the pMusicFrame package where the frame created and everythi +ng is # being set up. package pMusicFrame; use strict; use warnings; use Wx qw(:everything); use Wx::Event qw(EVT_TIMER); use Audio::BASSXS; use MP3::M3U::Parser; use MP3::Info; use URI::Escape; use AAC::Pvoice::Panel; use AAC::Pvoice::Input; use AAC::Pvoice::Row; use Wx::Perl::Carp; use base qw(Wx::Frame); #--------------------------------------------------------------------- +-------- sub new { my $class = shift; # Call the Superclass' constructor my $self = $class->SUPER::new(@_); # Set the frame's icon my $icon=Wx::Icon->new( 'pMusic.ico', # name wxBITMAP_TYPE_ICO); # type $self->SetIcon($icon ); my $rv = BASS_Init(1,44100,0,0,0); $self->{backgroundcolour}=$rightpanecolour; $self->SetBackgroundColour($self->{backgroundcolour}); $self->{MAX_X} = 50; $self->{MAX_Y} = 50; $self->{ITEMSPACING} = 3; $self->{itemsperrow} = 4; $self->{maxrows} = 3; $self->{idstart} = 10_000; $self->{splitwindow} = Wx::SplitterWindow->new( $self, -1, wxDefaultPosition, + wxDefaultSize, wxSP_NOBORDER|wxSP +_LIVE_UPDATE ); $self->{splitwindow}->Show(1); $self->Show(1); $self->Maximize(1); $self->{cdinfo} = CDInfoPanel->new( $self->{splitwindow}, -1, wxDefaultPosition, [int((1*$self->GetSize->GetWid +th)/4), ($self->GetSize->GetHeight-20 +)]); $self->{panel} = AAC::Pvoice::Panel->new( $self->{splitwindow}, + # parent -1, # id wxDefaultPosition,# po +sition [int((3*$self->GetSize +->GetWidth)/4), $self->GetSize->GetHe +ight-20], # size wxNO_3D, 1); # style $self->{splitwindow}->SplitVertically( $self->{cdinfo}, $self->{panel}, int((1*$self->GetSize->GetW +idth)/4)); $self->{panel}->Show(1); $self->{cdinfo}->Show(1); $self->{panel}->BackgroundColour($self->{backgroundcolour}); $self->{cdinfo}->SetBackgroundColour($leftpanecolour); $self->{splitwindow}->SetBackgroundColour($self->{backgroundcolour +}); $self->{selectedcd} = 'idx'; $self->{CATIDXBMP} = AAC::Pvoice::Bitmap->new('img/up.png' , $ +self->{MAX_X}, $self->{MAX_Y}); $self->{PREVPAGBMP} = AAC::Pvoice::Bitmap->new('img/prev.png' , $ +self->{MAX_X}, $self->{MAX_Y}); $self->{NEXTPAGBMP} = AAC::Pvoice::Bitmap->new('img/next.png' , $ +self->{MAX_X}, $self->{MAX_Y}); $self->{ROWSELBMP} = AAC::Pvoice::Bitmap->new('img/rowsel.png', $ +self->{MAX_X}, $self->{MAX_Y}); $self->{PLAYBMP} = AAC::Pvoice::Bitmap->new('img/play.png' , $ +self->{MAX_X}, $ +self->{MAX_Y},'',$rightpanecolour); $self->{PAUSEBMP} = AAC::Pvoice::Bitmap->new('img/pause.png' , $ +self->{MAX_X}, $ +self->{MAX_Y},'',$rightpanecolour); $self->{STOPBMP} = AAC::Pvoice::Bitmap->new('img/stop.png' , $ +self->{MAX_X}, $ +self->{MAX_Y},'',$rightpanecolour); $self->{PLAYALLBMP} = AAC::Pvoice::Bitmap->new('img/playall.png',$ +self->{MAX_X}, $ +self->{MAX_Y},'',$rightpanecolour); $self->{PLAYTRACKBMP} = AAC::Pvoice::Bitmap->new('img/playtrack.pn +g',$self->{MAX_X}, $ +self->{MAX_Y},'',$rightpanecolour); # Get information on all playlists in $basedir $self->GetPlayLists; $self->{playall} = 1; # Draw the screen... $self->DrawScreen(); # We're invoking PlayStatus() every second to update the info on t +he CDInfoPanel $self->{timer} = Wx::Timer->new($self,my $tid = Wx::NewId()); $self->{timer}->Start(1000, 0); # 0 is continuous EVT_TIMER($self, $tid, \&PlayStatus); return $self; } #--------------------------------------------------------------------- +-------- sub PlayStatus { my $self = shift; return if not defined $self->{playingcd}; return if not defined $self->{playingindex}; return if $self->{stop} or $self->{pause}; return if not $self->{stream}; $self->UpdateStatus; my $pos = BASS_StreamGetFilePosition($self->{stream},BASS_FILEPOS_ +DECODE); my $len = BASS_StreamGetFilePosition($self->{stream},BASS_FILEPOS_ +END); my $progress=$pos*100.0/$len; # percentage of buffer used if ($progress>100) {$progress=100;} # restrict to 100 (can be high +er) $self->{cdinfo}->UpdateGauge($progress); if ($pos >= $len) { if ($self->{playingindex} < $#{$self->{playlists}->{$self->{pl +ayingcd}}}) { if ($self->{newselection}) { $self->{newselection}=0; $self->{playingindex} = $self->{selectedindex}; $self->{playingcd} = $self->{selectedcd}; } else { $self->{playingindex}++; } $self->{playingfile} = $basepath.$self->{playlists} ->{$self->{playingcd +}} ->[$self->{playingin +dex}]->[2]; $self->{cdinfo}->SetCover(AAC::Pvoice::Bitmap->new( $basep +ath.$self->{playingcd}.'.jpg', $self- +>{cdinfo}->GetSize->GetWidth-50, $self- +>{cdinfo}->GetSize->GetWidth-50, '', $leftp +anecolour)); $self->UpdateSelection; $self->{stream} = BASS_StreamCreateFile(0,$self->{playingf +ile},0,0,0); warn "BASS error: ".BASS_ErrorString(BASS_ErrorGetCode) un +less $self->{stream}; my $rv = BASS_StreamPlay($self->{stream},0,0); warn "BASS error: ".BASS_ErrorString(BASS_ErrorGetCode) un +less $rv == 1; } else { undef $self->{stream}; undef $self->{playingcd}; $self->{playingindex} = 0; $self->{cdinfo}->UpdateStatus("Playing has stopped"); } } } #--------------------------------------------------------------------- +-------- sub DrawScreen { my $self = shift; my $id = $self->{idstart}; #----------------------------------------------------------------- +-------- # This is the closure to select a specific cd my $selectcd = sub{ my $cd = shift; return sub { $self->{selectedcd} = $cd; $self->{selectedindex} = 0; $self->{panel}->{currentpage} += 0; $self->DrawScreen() } }; #----------------------------------------------------------------- +-------- # This is the closure to select a specific item my $selectitem = sub{ my $index = shift; return sub { $self->{stop} = 0; $self->{selectedindex} = $ +index; $self->{newselection}=1; $self->UpdateSelection; } }; #----------------------------------------------------------------- +-------- # This is the closure to go to the previous page my $prevpage = sub{ # not implemented yet }; #----------------------------------------------------------------- +-------- # And the closure to go to the next page my $nextpage = sub{ # not implemented yet }; #----------------------------------------------------------------- +-------- # And the closure to go to play an mp3 file my $play = sub { return sub{ if ($self->{pause}) { BASS_Start; $self->{pause} = 0; $self->UpdateStatus; } else { unless ($self->{stop}) { $self->{playingcd} = $self- +>{selectedcd}; $self->{playingindex} = $self- +>{selectedindex}; } $self->{stop}=0; my $newfile = $basepath.$self->{pl +aylists} ->{$s +elf->{playingcd}} ->[$s +elf->{playingindex}]->[2]; BASS_Stop; $self->{playingfile} = $newfile; $self->{cdinfo}->SetCover(AAC::Pvo +ice::Bitmap->new($basepath.$self->{playingcd}.'.jpg', + $self->{cdinfo}->GetSize->GetWidth-50, + $self->{cdinfo}->GetSize->GetWidth-50, + '', + $leftpanecolour)); $self->UpdateStatus; $self->UpdateSelection; $self->{stream} = BASS_StreamCreat +eFile(0,$self->{playingfile},0,0,0); warn "BASS error: ".BASS_ErrorStri +ng(BASS_ErrorGetCode) unless $self->{stream}; BASS_Start; my $rv = BASS_StreamPlay($self->{s +tream},0,0); warn "BASS error: ".BASS_ErrorStri +ng(BASS_ErrorGetCode) unless $rv == 1; } } }; #----------------------------------------------------------------- +-------- # First we clear the panel $self->{panel}->Clear(); my $title = "pMusic"; $title .= " ( $self->{playlists}->{$self->{selectedcd}}->[0]->[5] +)" if $self->{selectedcd} ne 'idx'; $self->{panel}->AddTitle( $title); #----------------------------------------------------------------- +-------- # create the navigation-row my $items = []; push @$items, [$id++, $self->{ROWSELBMP}, sub{$self->{panel}->ToR +owSelection}]; push @$items, [$id++, $self->{CATIDXBMP}, $selectcd->('idx')] if $self->{selectedcd} ne 'idx'; push @$items, [$id++, $self->{PREVPAGBMP}, $prevpage] if $self->{selectedcd} eq 'idx'; push @$items, [$id++, $self->{NEXTPAGBMP}, $nextpage] if $self->{selectedcd} eq 'idx'; push @$items, [$id++, $self->{PLAYALLBMP}, sub{$self->{playall} = + 1; $self->DrawScreen} + ] if $self->{selectedcd} ne 'idx'; push @$items, [$id++, $self->{PLAYTRACKBMP},sub{$self->{playall} = + 0; $self->DrawScreen} + ] if $self->{selectedcd} ne 'idx'; $self->{panel}->Append(AAC::Pvoice::Row->new($self->{panel}, # p +arent scalar(@$items), # m +ax $items, # i +tems wxDefaultPosition,# p +os wxDefaultSize, $self->{MAX_X}, $self->{MAX_Y}, $self->{ITEMSPACING}, $self->{backgroundcol +our})); if ($self->{selectedcd} eq 'idx') { #------------------------------------------------------------- +------------ # create the rows with selectable cds my $maxY = int( ($self->{panel}->ysize-(3*$self->{MAX_Y})) /($self->{maxrows}) )-$self->{ITEMSPACING}; my $maxX = int($self->{panel}->xsize/($self->{itemsperrow}+1)) +-10; $self->{cdrowsel} = AAC::Pvoice::Bitmap->new( 'img/rowsel.png +', $maxX, $maxY, '', $rightpanecolou +r); $items=[]; my @allitems; @allitems = map { my $pl=$_; [ $id++, AAC::Pvoice::Bitmap->new($base +path.$pl.'.jpg', $maxX +, $maxY +, '', $righ +tpanecolour), $selectcd->($pl) ] } sort keys %{$self->{playlists}}; for (my $ii = 0; $ii < @allitems; $ii+=($self->{itemsperrow}-1 +)) { @$items=@allitems[$ii..($ii+$self->{itemsperrow}-2)]; # add the rowselect button unshift @$items, [$id++, # +id $self->{cdrowsel}, # +bitmap sub{$self->{panel}->ToRowSelection}]; # +action # add the items to the row and the row to the panel $self->{panel}->Append(AAC::Pvoice::Row->new($self->{panel +}, # parent $self->{items +perrow}, # max $items, + # items wxDefaultPosi +tion, # pos wxDefaultSize +, $maxX, $maxY, $self->{ITEMS +PACING}, $self->{backg +roundcolour})); } #------------------------------------------------------------- +------------ # fill up empty rows $self->{panel}->Append(AAC::Pvoice::Row->new($self->{panel}, + # parent $self->{itemsperr +ow}, # max [], + # items wxDefaultPosition +, # pos wxDefaultSize, $maxX, $maxY, $self->{ITEMSPACI +NG}, $self->{backgroun +dcolour}),1) for $self->{panel}->{totalrows}..$self->{maxrows} +; } else { #------------------------------------------------------------- +------------ # create the rows with songs within this cd my $maxY = int( ($self->{panel}->ysize-(3*$self->{MAX_Y})) /(scalar(@{$self->{playlists}->{$self->{select +edcd}}})) )-$self->{ITEMSPACING}; my $maxX = int($self->{panel}->xsize/(2))-10; my $fontsize = 20; $self->UpdateSelection(); for (my $i=0; $i < @{$self->{playlists}->{$self->{selectedcd}} +}; $i++) { my $caption = $self->{playlists}->{ $self->{selectedcd}}-> +[$i]->[4] ." - " .$self->{playlists} ->{$self->{select +edcd}} ->[$i]->[3]; my $newbmp = Wx::Bitmap->new($maxX, $maxY); my $tmpdc = Wx::MemoryDC->new(); $tmpdc->SelectObject($newbmp); $tmpdc->Clear(); my ($cfont, $cpt) = (wxNullFont, 18); my ($cw, $ch); do { $cpt--; $cfont = Wx::Font->new( $cpt, # font siz +e wxSWISS, # font fam +ily wxNORMAL, # style wxNORMAL, # weight 0, 'Comic Sans MS', # face nam +e wxFONTENCODING_SYSTEM); ($cw, $ch, undef, undef) = $tmpdc->GetTextExtent($capt +ion, $cfont); } until ($cw<=$maxX) && ($ch <= $maxY); $fontsize = $cpt if $fontsize > $cpt; } my $cfont = Wx::Font->new( $fontsize, # font size wxSWISS, # font family wxNORMAL, # style wxNORMAL, # weight 0, 'Comic Sans MS', # face name wxFONTENCODING_SYSTEM); for (my $i=0; $i < @{$self->{playlists}->{$self->{selectedcd}} +}; $i++) { my $caption = $self->{playlists} ->{$self->{selectedcd}} ->[$i]->[4] ." - " .$self->{playlists} ->{$self->{selectedcd}} ->[$i]->[3]; my $newbmp = Wx::Bitmap->new($maxX, $maxY); my $tmpdc = Wx::MemoryDC->new(); $tmpdc->SelectObject($newbmp); if ($self->{playall}) { my $br = Wx::Brush->new($leftpanecolour, wxSOLID); $tmpdc->SetBrush($br); $tmpdc->SetBackground($br); $tmpdc->SetTextBackground($leftpanecolour); $tmpdc->SetTextForeground(wxBLACK); } else { $tmpdc->SetTextBackground($leftpanecolour); $tmpdc->SetTextForeground(wxBLACK); } $tmpdc->Clear(); $tmpdc->SetFont($cfont); $tmpdc->DrawText($caption, 0,0); # add the items to the row and the row to the panel $self->{panel}->Append(AAC::Pvoice::Row->new($self->{panel +}, 1, [[$id++, $newbmp, $selectitem +->($i)]], wxDefaultPosi +tion, wxDefaultSize +, $maxX, $maxY, $self->{ITEMS +PACING}, $self->{backg +roundcolour}), $self->{playa +ll}); } } #----------------------------------------------------------------- +-------- # create the control-row $items = []; push @$items, [$id++, $self->{PLAYBMP} , $play->()]; push @$items, [$id++, $self->{PAUSEBMP}, sub{ BASS_Pause(); $self->{pause}=1; $self->UpdateStatus; }]; push @$items, [$id++, $self->{STOPBMP} , sub{ BASS_Stop(); $self->{pause}=0; $self->{stop}=1; $self->{playingindex}=0; $self->{playingcd}=$self->{selectedcd} +; $self->UpdateStatus; $self->UpdateSelection; $self->{cdinfo}->UpdateGauge(0); }]; $self->{panel}->Append(AAC::Pvoice::Row->new($self->{panel}, # p +arent scalar(@$items), # m +ax $items, # i +tems wxDefaultPosition,# p +os wxDefaultSize, $self->{MAX_X}, $self->{MAX_Y}, $self->{ITEMSPACING}, $self->{backgroundcol +our})); #----------------------------------------------------------------- +-------- # finalize the panel $self->{panel}->Finalize(); } #--------------------------------------------------------------------- +-------- sub UpdateStatus { my $self = shift; $self->{cdinfo}->UpdateStatus($self->{playlists} ->{$self->{playingcd}} ->[$self->{playingindex}]->[5], $self->{playlists} ->{$self->{playingcd}} ->[$self->{playingindex}]->[4], $self->{playlists} ->{$self->{playingcd}} ->[$self->{playingindex}]->[3], $self->{playlists} ->{$self->{playingcd}} ->[$self->{playingindex}]->[1], $self->{stop} ? 'stopped' : $self->{pause} ? 'pa +use' : 'pl +aying'); } #--------------------------------------------------------------------- +-------- sub UpdateSelection { my $self = shift; if ($self->{newselection}) { $self->{cdinfo}->UpdateSelection($self->{playlists} ->{$self->{selectedcd}} ->[$self->{selectedindex +}] ->[0]); } elsif (defined $self->{playingcd} && defined $self->{playingindex} +) { $self->{cdinfo}->UpdateSelection($self->{playlists} ->{$self->{playingcd}} ->[$self->{playingindex} ++1] ->[0]); } elsif (not $self->{selectedcd}) { $self->{cdinfo}->UpdateSelection("Geen"); } elsif (not $self->{selectedindex}) { $self->{cdinfo}->UpdateSelection($self->{playlists} ->{$self->{selectedcd}} ->[0]->[0]); } else { $self->{cdinfo}->UpdateSelection($self->{playlists} ->{$self->{selectedcd}} ->[$self->{selectedindex +}] ->[0]); } } #--------------------------------------------------------------------- +-------- sub GetPlayLists { my $self = shift; my $m3u = MP3::M3U::Parser->new( -type => 'dir', -path => $basepath, -seconds => 'format'); $self->{playlists} = $m3u->parse(); foreach my $playlist (keys %{$self->{playlists}}) { foreach my $i (@{$self->{playlists}->{$playlist}}) { $i->[0] =~ s/[\r\n]//g; $i->[2] = uri_unescape($i->[2]); $i->[2] =~ s/[\r\n]//g; my $mp3 = MP3::Info->new($basepath.$i->[2]); $i->[3] = $mp3->artist; $i->[4] = $mp3->title; $i->[5] = $mp3->album; } } } #--------------------------------------------------------------------- +-------- # This is the CDInfoPanel package where we define the left pane of the + frame # which displays status information on what is being played package CDInfoPanel; use strict; use warnings; use Wx qw(:everything); use Wx::Perl::Carp; use base qw (Wx::Panel); #--------------------------------------------------------------------- +-------- sub new { my $class = shift; my $self = $class->SUPER::new(@_); $self->Show(1); my $width = $self->GetSize->GetWidth; $self->Show(0); $self->{tls} = Wx::FlexGridSizer->new(0,1); $self->{coversizer} = Wx::GridSizer->new(0,1); $self->{cover} = Wx::BitmapButton->new( $self, -1, AAC::Pvoice::Bitmap->new( 'img/log +o.png', $width-5 +0, $width-5 +0, '', undef, 1), wxDefaultPosition, [$width-20,$width-20], wxSUNKEN_BORDER); $self->{cover}->SetBackgroundColour($leftpanecolour); $self->{coversizer}->Add($self->{cover},0,wxALL|wxALIGN_CENTRE|wxG +ROW, 0); $self->{coversizer}->SetMinSize($width,$width); $self->{tls}->Add($self->{coversizer},0, wxALL|wxALIGN_CENTRE|wxGR +OW, 0); $self->{gauge} = Wx::Gauge->new( $self, #parent -1, #id 100, #max value wxDefaultPosition, #position [200,30], # size wxGA_PROGRESSBAR|wxGA_SMOOTH); #s +tyle $self->{gauge}->SetBackgroundColour(wxWHITE); $self->{tls}->Add($self->{gauge},0, wxALIGN_CENTRE, 0); $self->{statussizer} = Wx::FlexGridSizer->new(0,1); $self->{font} = Wx::Font->new( 9, # font size wxDECORATIVE, # font family wxNORMAL, # style wxNORMAL, # weight 0, 'Comic Sans MS'); $self->{status1} = Wx::StaticText->new($self, -1, 'Album: ', wxDefaultPositio +n, [$width - 20,50] +, wxALIGN_LEFT); $self->{status1}->SetFont($self->{font}); $self->{status1}->SetBackgroundColour($leftpanecolour); $self->{status2} = Wx::StaticText->new($self, -1, 'Title: ', wxDefaultPositio +n, [$width - 20,50] +, wxALIGN_LEFT); $self->{status2}->SetFont($self->{font}); $self->{status2}->SetBackgroundColour($leftpanecolour); $self->{status3} = Wx::StaticText->new($self, -1, 'Artist: ', wxDefaultPositio +n, [$width - 20,50] +, wxALIGN_LEFT); $self->{status3}->SetFont($self->{font}); $self->{status3}->SetBackgroundColour($leftpanecolour); $self->{status4} = Wx::StaticText->new($self, -1, 'Duration: ', wxDefaultPositio +n, [$width - 20,50] +, wxALIGN_LEFT); $self->{status4}->SetFont($self->{font}); $self->{status4}->SetBackgroundColour($leftpanecolour); $self->{status5} = Wx::StaticText->new($self, -1, 'Action: ', wxDefaultPositio +n, [$width - 20,50] +, wxALIGN_LEFT); $self->{status5}->SetFont($self->{font}); $self->{status5}->SetBackgroundColour($leftpanecolour); $self->{selectionfont} = Wx::Font->new( 11, # font size wxDECORATIVE, # font family wxITALIC, # style wxNORMAL, # weight 0, 'Comic Sans MS'); $self->{selection0} = Wx::StaticText->new($self, -1, 'Next: ', wxDefaultPosi +tion, [$width - 20, +50], wxALIGN_LEFT) +; $self->{selection0}->SetFont($self->{selectionfont}); $self->{selection0}->SetBackgroundColour($leftpanecolour); $self->{statussizer}->Add($self->{status4}, 0, wxGROW|wxALL, 0); $self->{statussizer}->Add($self->{status5}, 0, wxGROW|wxALL, 0); $self->{statussizer}->Add($self->{status1}, 0, wxGROW|wxALL, 0); $self->{statussizer}->Add($self->{status2}, 0, wxGROW|wxALL, 0); $self->{statussizer}->Add($self->{status3}, 0, wxGROW|wxALL, 0); $self->{statussizer}->Add($self->{selection0},0, wxGROW|wxALL, 0); $self->{statussizer}->AddGrowableCol(0); $self->{tls}->Add($self->{statussizer},0, wxGROW|wxALL, 0); $self->{tls}->AddGrowableCol(0); $self->{tls}->AddGrowableRow($_) for (0..3); $self->SetSizer($self->{tls}); $self->{tls}->Fit($self); $self->{tls}->Layout; $self->SetBackgroundColour($leftpanecolour); $self->Refresh; $self->Show(1); $self->UpdateStatus("(None)","(None)","(None)","0:00","(None)"); $self->UpdateSelection("(None)"); return $self; } #--------------------------------------------------------------------- +-------- sub UpdateStatus { my $self = shift; $self->{status1}->SetLabel("Album: ".shift); $self->{status2}->SetLabel("Title: ".shift); $self->{status3}->SetLabel("Artist: ".shift); $self->{status4}->SetLabel("Duration: ".shift); $self->{status5}->SetLabel("Action: ".shift); $self->{tls}->Layout(); } #--------------------------------------------------------------------- +-------- sub UpdateSelection { my $self = shift; my $value = shift; $self->{selection0}->SetLabel("Next: ".$value); $self->{tls}->Layout(); } #--------------------------------------------------------------------- +-------- sub UpdateGauge { my $self = shift; $self->{gauge}->SetValue(shift); } #--------------------------------------------------------------------- +-------- sub SetCover { my $self = shift; $self->{cover}->SetBitmapLabel(shift); $self->Refresh; } #--------------------------------------------------------------------- +-------- # This is the main package where the application itself is started package main; my $obj = pMusic->new(); $obj->MainLoop;


Jouke Visser
Speaking at the 2004 O'Reilly Open Source Convention about pVoice

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: CUFP [id://348135]
Approved by Corion
Front-paged by broquaint
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (3)
As of 2025-03-24 14:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    When you first encountered Perl, which feature amazed you the most?










    Results (64 votes). Check out past polls.

    Notices?
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.