#!/usr/bin/perl -w use strict; use CGI; # for escape use Data::Dumper; use HTTP::Response; use POE qw(Component::Server::HTTP Component::MPG123); $| = 1; my $port = 8000; # HTTP server port my $mp3dir = "/home/hossman/mp3/"; # where all your mp3s are my @song_queue = # initial queue of songs to play (if any) ( # $mp3dir . 'a.mp3', # $mp3dir . 'b.mp3', ); ################################################################## # we'll fill this up. my $global_status = { state => 'stoped', total_frames => 0, total_time => 0, last_frame => 0, last_time => 0, }; ## # # The MPG123 Component # # much of this was taken verbatim from the # POE::Component::MPG123 test script # POE::Component::MPG123->spawn( alias => 'song_manager' ); POE::Session->create ( inline_states => { _start => sub { my ($kernel, $heap) = @_[KERNEL, HEAP]; $kernel->alias_set( 'song_manager' ); # Start the first song. &play_next($kernel); }, _stop => sub { }, # Receive status events from mpg123. status => sub { my ( $kernel, $heap, $frames_played, $frames_left, $time_played, $time_left ) = @_[KERNEL, HEAP, ARG0..ARG3]; $global_status->{state} = "playing"; unless ($global_status->{total_frames}) { $global_status->{total_frames} = $frames_left; $global_status->{total_time} = $time_left; } $global_status->{frame_count}++; $global_status->{last_frame} = $frames_played; $global_status->{last_time} = $time_played; # Rather than wait for a specific frame and call # it the end of the song, I'll set a brief delay # here to time out if frames # stop playing. $kernel->delay( song_timeout => 0.25 ); }, song_info => sub { my ($kernel, $heap, $info) = @_[KERNEL, HEAP, ARG0]; $global_status->{song_info} = $info; }, file_info => sub { my ($kernel, $heap, $info) = @_[KERNEL, HEAP, ARG0]; $global_status->{file_info} = $info; }, # The pause succeeded. song_paused => sub { my ($kernel, $heap) = @_[KERNEL, HEAP]; $global_status->{state} = "paused"; }, # The song resumed after we asked it to. song_resumed => sub { my ($kernel, $heap) = @_[KERNEL, HEAP]; $global_status->{state} = "playing"; }, # The song stopped naturally. song_stopped => sub { my ($kernel, $heap) = @_[KERNEL, HEAP]; $global_status->{state} = "stoped"; $global_status->{file_info} = undef; $global_status->{song_info} = undef; $global_status->{total_time} = 0; $global_status->{total_frames} = 0; $global_status->{last_time} = 0; $global_status->{last_frame} = 0; &play_next($kernel); }, # The player has quit. player_quit => sub { my ($kernel, $heap) = @_[KERNEL, HEAP]; $global_status->{state} = "player quit"; }, ### Miscellaneous event handlers. debug => sub { }, _child => sub { }, _signal => sub { 0 }, } ); ## # # The HTTP Component # # The docs for this component are a little lacking ... # but this seems to work # my $httpd = new POE::Component::Server::HTTP ( Port => 8000, Headers => { 'Server' => 'My Server', 'Content-type' => 'text/html', }, ContentHandler => { '/pause/' => \&httpd_pause_handler, '/req/' => \&httpd_req_handler, '/list/' => \&httpd_list_handler, '/next/' => \&httpd_next_handler, '/' => \&httpd_status_handler, }, ); # # HTTPD Handlers # # sub httpd_req_handler { # the really cool one, we unshift a song on to the head # of the list and queue it my ($request, $response) = @_; my $song = CGI::unescape($request->uri->query()); my $res = ""; if (-f $song) { push @song_queue, $song; $res = "REQUEST ACCEPTED: $song\n"; &play_next($poe_kernel); } else { $res = "what are you smoking? (no $song)\n"; } $response->content (&make_html_response($res, &get_status_info)); $response->code(RC_OK); return RC_OK; } sub httpd_list_handler { my ($request, $response) = @_; my @songs = `find $mp3dir -follow -name \*.mp3`; my $links = join ' ', map { chomp; "<a href=\"/req/?" . CGI::escape($_) . "\">$_</a><br>" } @songs; $response->code(RC_OK); $response->content (&make_html_response("Pick a song from the list below", $links)); return RC_OK; } sub httpd_pause_handler { my ($request, $response) = @_; $poe_kernel->post( mpg123 => 'pause' ); $response->code(RC_OK); $response->content (&make_html_response("The current song has been (un)paused", &get_status_info)); return RC_OK; } sub httpd_next_handler { my ($request, $response) = @_; $poe_kernel->post( mpg123 => 'stop'); $response->code(RC_OK); $response->content (&make_html_response("The last song was skipped", &get_status_info)); return RC_OK; } sub httpd_status_handler { my ($request, $response) = @_; $response->code(RC_OK); $response->content (&make_html_response(&get_status_info)); return RC_OK; } sub make_html_response { my ($r) = ('<html><body>' . '[ <a href="/next/">skip song</a> | ' . '<a href="/pause/">(un)pause</a> | ' . '<a href="/list/">Make a Request</a> | ' . '<a href="/">Reload Status</a> ]' . '<hr>' . join('<hr>', @_) . '<p></body></html>'); return $r; } sub play_next { # takes a kernel, # plays if the state is "stoped" and there's a song waiting return unless scalar(@song_queue); return unless 'stoped' eq $global_status->{state}; $_[0]->post( mpg123 => play => shift(@song_queue) ); } sub get_status_info { my $r = "<pre>"; $r .= "\nCurrent State: " . $global_status->{state} . "\n"; $r .= "Total Frames: " . $global_status->{total_frames} . "\n"; $r .= "Total Time: " . $global_status->{total_time} . "\n"; $r .= "Elapsed Frames: " . $global_status->{last_frame} . "\n"; $r .= "Elapsed Time: " . $global_status->{last_time} . "\n"; $r .= "\nSong...\n" . Dumper($global_status->{song_info}); $r .= "\nFile...\n" . Dumper($global_status->{file_info}); $r .= "\nQueue...\n" . join("\n", @song_queue); $r .= "</pre>"; return $r } # Kick the kernel $poe_kernel->run(); exit 0;

In reply to POE MP3/HTTP player by hossman

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.