PDA

View Full Version : announcing version v0.92 of Live Music Archive



Dan Aronson
2004-04-14, 23:47
Thanks to the great feedback of Rob, Dean, Dan, Daniel, Peter and
Donald, enclosed is
version 0.92 of the Live Music Archive plugin.

This version includes:
various fixes to UI to make it more consistant with other software,
fixes to make it work on windows (at least win98)
new buttons and new concert browse mode.
various bug fixes.

The Plugin consists of four modes.
Mode 1: Scrolling though the list of bands.
up, down: scroll
right: concerts are indexed by year, get list of years
for displayed artist (mode 2)

Mode 2: Scrolling through list of years
up, down: scroll
right: get list of concerts for given year (mode 3)

Mode 3: Scrolling through list of concerts
up, down: scroll
right: go to concert browse mode (mode 4)
play: replace current playlist with songs from concert
and start playing songs
add:adds all songs from concert to current playlist

Mode 4:Scrolling through songs in a concert
up, down: scroll
play: replace current playlist with selected song
add: add selected song to current playlist

Enjoy and please send more feedback.

--dan aronson
dan at catolabs dot org



# Archive.pm by Dan Aronson (danaronson (AT) yahoo (DOT) com)
#
# This code is derived from code with the following copyright message:
#
# SliMP3 Server Copyright (C) 2001 Sean Adams, Slim Devices Inc.
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License,
# version 2.
use strict;

###########################################
### Section 1. Change these as required ###
###########################################

package Plugins::Archive;

use Slim::Control::Command;
use Slim::Utils::Strings qw (string);
use vars qw($VERSION);

$VERSION = "0.92";

my @bands;
my %band_index;

my $UNKNOWN = 0;
my $FETCH = 1;
my $PARSE = 2;
my $FETCH_SHOW = 3;
my $PLAYING = 4;
my $OK = 5;
my $ERROR = 6;


my %bands;
my %which_concert;
my %current_song;
my %saved_song;
my %song_count;
my %band_url;
my %current_artist;
my %current_year;
my %year_index;
my %year_count;
my %years;
my @years;
my %old_year;
my %show_index_by_artist;
my %old_show_index_by_artist;
my %shows;
my %show_count;
my %show_index;
my %retrieval_error;
my %content; # used for http content (see subroutine 'get')
my %error; # error during call to 'get'
my %get_status;
my %concert_by_id;

sub getDisplayName() {return "Live Music Archive"; };


##################################################
### Section 2. Your variables and code go here ###
##################################################


sub setMode() {
my $client = shift;
if (%retrieval_error && (1 == $retrieval_error{$client})) {
return;
}

$get_status{$client} = $UNKNOWN;
$client->lines(\&lines);
unless (%bands) {
$band_index{$client} = 0;
Slim::Buttons::Block::block($client, "Fetching Archive Band List", "");
get_band_listing($client);
} else {
*bands = $bands{$client};
$current_artist{$client} = $bands[$band_index{$client}];
$client->update();
}


}


my %functions = (
'up' => sub {
my $client = shift;
$band_index{$client} = Slim::Buttons::Common::scroll($client,
-1,
$#bands + 1,
$band_index{$client} || 0);
$current_artist{$client} = $bands[$band_index{$client}];
$client->update();
},
'down' => sub {
my $client = shift;
$band_index{$client} = Slim::Buttons::Common::scroll($client,
1,
$#bands + 1,
$band_index{$client} || 0);
$current_artist{$client} = $bands[$band_index{$client}];
$client->update();
},
'left' => sub {
my $client = shift;
Slim::Buttons::Common::popModeRight($client);
},
'right' => sub {
my $client = shift;
if ($years{$current_artist{$client}}) {
Slim::Buttons::Common::pushModeLeft($client, 'Archive::band_page');
} else {
# if load_band_page is successful, it pushes Archive::band_page mode'
load_band_page($client);
}
},
'numberScroll' => sub {
my $client = shift;
my $button = shift;
my $digit = shift;
my $line1 = "button: ${button}";
my $line2 = "digit: ${digit}";
Slim::Display::Animation::showBriefly($client, $line1, $line2);
}
);

sub lines {
my $client = shift;
my ($line1, $line2);
$line1 = "Live Music Archive";
if (-1 == $#bands) {
$line2 = "couldn't find any bands";
} else {
my $band_index = $band_index{$client};
$line1 .= " (" . ($band_index+1) . ' ' . string('OF') . ' ' . ($#bands + 1) . ")";
$line2 = $bands[$band_index];
}
return ($line1, $line2, undef, Slim::Hardware::VFD::symbol('rightarrow'));
}


# real code

sub URL_decode {
my $the_URL = shift;
$the_URL =~ tr/+/ /;
$the_URL =~ s/%([a-fA-F0-9]{2,2})/chr(hex($1))/eg;
$the_URL =~ s/<!--(.|\n)*-->//g;
return $the_URL;
}


my $tmp_file = "/tmp/osa.$$";
my $etree_listing = "http://www.archive.org/audio/etreelisting-browse.php?mode=mp3";
my $etree_details_db_url = "http://www.archive.org/audio/etree-details-db.php?id=";


sub get_band_listing
{
my $client = shift;
my $ret = get($client, $etree_listing);
if (0 == $ret) {
Slim::Utils::Timers::setTimer($client, Time::HiRes::time() + 1, \&get_band_listing);
} elsif (-1 == $ret) {
$retrieval_error{$client} = 1;
Slim::Buttons::Block::unblock($client);
$::d_plugins && Slim::Utils::Misc::msg("Error when calling get: " . $error{$client});
# abort and pop back to where we were before
Slim::Buttons::Common::popModeRight($client);
$retrieval_error{$client} = 0;

} else {
# get the real data
my $content = $content{$client};
if ($content) {
while ($content =~ s/collection=etree&mode=mp3&cat=([^&]*)&PHPS//)
{
my $band_name = URL_decode($1);
$band_url{$band_name} = $1;
push(@bands, $band_name);
}
}
$bands{$client} = @bands;
if (-1 == $#bands) {
$::d_plugins && Slim::Utils::Misc::msg("Couldn't find any bands, take a look at\n");
$::d_plugins && Slim::Utils::Misc::msg("the result of ${etree_listing}\n");
}
$current_artist{$client} = $bands[0];
Slim::Buttons::Block::unblock($client);
$client->update();
}
}




sub get_band_page_listing
{
my $client = shift;
my $url = shift;
my $ret = get($client, $url);
if (0 == $ret) {
Slim::Utils::Timers::setTimer($client, Time::HiRes::time() + 1, \&get_band_page_listing, $url );
} elsif (-1 == $ret) {
Slim::Buttons::Block::unblock($client);
$::d_plugins && Slim::Utils::Misc::msg("Error when calling get: " . $error{$client});
} else {
my $content = $content{$client};
my $band_url = $band_url{$current_artist{$client}};
my $search_string = "collection=etree&mode=mp3&cat=${band_url}%3A%20(\\d\\d\\d\\d)";
my @years = ();
while ($content =~ s/$search_string//)
{
push(@years, $1);
}
Slim::Buttons::Block::unblock($client);
if (-1 == $#years) {
$::d_plugins && Slim::Utils::Misc::msg("Couldn't find any years, take a look at\n");;
$::d_plugins && Slim::Utils::Misc::msg("the result of ${url}\n");
} else {
$years{$current_artist{$client}} = join(':', reverse(@years));
$year_index{$current_artist{$client}} = 0;
Slim::Buttons::Common::pushModeLeft($client, 'Archive::band_page');
}
}
}


sub load_band_page {
my $client = shift;
my $band_url = $band_url{$current_artist{$client}};
my $url = $etree_listing . "&cat=" . $band_url;
Slim::Buttons::Block::block($client, "Fetching year list", $current_artist{$client});
get_band_page_listing($client, $url);
}

sub band_page_mode_sub {
my $client = shift;
$client->lines(\&band_page_lines);
@years = split(':', $years{$current_artist{$client}});
$year_count{$client} = $#years;
$client->update();
};


my $band_page_mode_sub = *band_page_mode_sub;

sub band_page_lines() {
my $client = shift;
my ($line1, $line2);
$line1 = $current_artist{$client};
if (-1 != $year_index{$current_artist{$client}}) {
$line1 .= " (" . ($year_index{$current_artist{$client}}+1) . ' ' . string('OF') . ' ' . ($#years + 1) . ")";
$line2 = $years[$year_index{$current_artist{$client}}];
} else {
$line2 = "";
}
return ($line1, $line2, undef, Slim::Hardware::VFD::symbol('rightarrow'));
};

my %band_page_functions =
(
'up' => sub {
my $client = shift;
$year_index{$current_artist{$client}} = Slim::Buttons::Common::scroll($client,
-1,
$year_count{$client} + 1,
$year_index{$current_artist{$client}});
$client->update();
},
'down' => sub {
my $client = shift;
$year_index{$current_artist{$client}} = Slim::Buttons::Common::scroll($client,
1,
$year_count{$client} + 1,
$year_index{$current_artist{$client}});
$client->update();
},
'left' => sub {
my $client = shift;
Slim::Buttons::Common::popModeRight($client);
},
'right' => sub {
my $client = shift;
if (exists ($shows{$current_artist{$client}}{$year_index{$cur rent_artist{$client}}})) {
Slim::Buttons::Common::pushModeLeft($client, 'Archive::year_page');
} else {
# if year_page_listing is successful than the mode is pushed
year_page_listing($client);
}
}
);



# Band listing mode
Slim::Buttons::Common::addMode('Archive::band_page ', \%band_page_functions, $band_page_mode_sub);



my $ID_CONCERT_SEPARATOR = "ID_CONCERT_SEPARATOR";
my $CONCERT_LIST_SEPARATOR = "CONCERT_LIST_SEPARATOR";
my $SHOW_LIST_SEPARATOR = "SHOW_LIST_SEPARATOR";

sub trim_whitespace
{
my $string = shift;
$string =~ s/\s*(\S.*?)\s*\z//;
return($1);
}



sub year_page_mode_listing_aux
{
my $client = shift;
my $url = shift;
my $ret = get($client, $url);
if (0 == $ret) {
Slim::Utils::Timers::setTimer($client, Time::HiRes::time() + 1, \&year_page_mode_listing_aux, $url );
} elsif (-1 == $ret) {
Slim::Buttons::Block::unblock($client);
$::d_plugins && Slim::Utils::Misc::msg("Error when calling get: " . $error{$client});
} else {
my $content = $content{$client};
my $search_string_details = "etree-details-db.php\\?id=(\\d+).*<strong>(.*)</strong>";
my $search_string_date = "<b>Date:</b>\\s*(.*?)[,<]";
my $search_string_venue = "<b>Venue:</b>\\s*(.*?)<";
my @concerts = ();
while ($content =~ s/$search_string_details//)
{
my $id = $1;
my $concert = $2;
my $date = "";
my $venue = "";
my $concerts = ();
if (defined($id) && defined($concert)) {
# let's get the following date and venue location
$content =~ s/$search_string_date//;
$date = $1;
$content =~ s/$search_string_venue//;
$venue = $1;
}
push(@concerts, join($ID_CONCERT_SEPARATOR, trim_whitespace($id),
trim_whitespace($concert), trim_whitespace($date),
trim_whitespace($venue)));
}
Slim::Buttons::Block::unblock($client);
if (-1 == $#concerts) {
$::d_plugins && Slim::Utils::Misc::msg("Couldn't find conert list, take a look at\n");;
$::d_plugins && Slim::Utils::Misc::msg("the result of ${url}\n");
} else {
$shows{$current_artist{$client}}{$year_index{$curr ent_artist{$client}}} =
join($CONCERT_LIST_SEPARATOR, @concerts);
$show_index{$current_artist{$client}}{$year_index{ $current_artist{$client}}} = 0;
Slim::Buttons::Common::pushModeLeft($client, 'Archive::year_page');
}
}
}


sub year_page_listing
{
my $client = shift;
my $year_index = $year_index{$current_artist{$client}};
my $year_name = (split(':', $years{$current_artist{$client}}))[$year_index];
my $year_url = $band_url{$current_artist{$client}} . "%3A%20" . $year_name;
my $url = $etree_listing . "&cat=" . $year_url;
# cache the index (so we don't have to keep looking this up)
Slim::Buttons::Block::block($client, "Fetching Concert list from ${year_name}",
$current_artist{$client});
year_page_mode_listing_aux($client, $url);
};

sub year_page_mode_sub {
my $client = shift;
$client->lines(\&year_page_lines);
my @concerts = split($CONCERT_LIST_SEPARATOR, $shows{$current_artist{$client}}
{$year_index{$current_artist{$client}}});
$show_index{$client} = $show_index{$current_artist{$client}}{$year_index{ $current_artist{$client}}};
$show_count{$client} = $#concerts;
$client->update();
};

my $year_page_mode_sub = *year_page_mode_sub;



sub year_page_lines() {
my $client = shift;
my ($line1, $line2);
my @concerts = split($CONCERT_LIST_SEPARATOR, $shows{$current_artist{$client}}
{$year_index{$current_artist{$client}}});
if (-1 != $show_index{$client}) {
my ($id, $concert, $date, $venue)
= split($ID_CONCERT_SEPARATOR,
$concerts[$show_index{$client}]);
$line1 = $current_artist{$client} . '/' .
$years[$year_index{$current_artist{$client}}] . ' (' .
($show_index{$client} + 1) .
' ' . string('OF') . ' ' . ($#concerts + 1) . ")";
$line2 = $date . "/" . $venue;
} else {
$line1 = "Current Artist = " . $current_artist{$client} ."\n";
$line2 = "";
}
return ($line1, $line2, undef,
Slim::Hardware::VFD::symbol('notesymbol') .
Slim::Hardware::VFD::symbol('rightarrow'));
};


sub process_concert_button_press
{
my $client = shift;
my $button = shift;
my @concerts = split($CONCERT_LIST_SEPARATOR,
$shows{$current_artist{$client}}{$year_index{$curr ent_artist{$client}}});
my ($id, $concert) = split($ID_CONCERT_SEPARATOR,
$concerts[$show_index{$client}]);
if (exists $concert_by_id{$id}) {
process_concert_button_press_aux($client, $id, $button);
} else {
my $details_url = $etree_details_db_url . $id;
Slim::Buttons::Block::block($client, "Fetching playlist", $concert);
retrieve_playlist($client, $id, $button);
}
}

my $PLAYLISTITEM = "PLAYLISTITEM";

sub process_concert_button_press_aux
{
my $client = shift;
my $id = shift;
my $button = shift;
if (!exists($concert_by_id{$id})) {
return;
}
my @playlist = split($PLAYLISTITEM, $concert_by_id{$id});
$which_concert{$client} = $id;
$song_count{$id} = $#playlist + 1;
if (('play' eq $button) || ('add' eq $button)) {
my $index = 0;
my $song;
foreach $song (@playlist) {
if ((0 == $index) && ('play' eq $button)) {
Slim::Control::Command::execute($client, ['playlist', 'play', $song]);
} else {
Slim::Control::Command::execute($client, ['playlist', 'add', $song]);
}
$index++;
}
Slim::Control::Command::execute($client, ['play']);
if ('add' eq $button) {
Slim::Display::Animation::showBriefly($client, "Added to current playlist");
}
} else {
Slim::Buttons::Common::pushModeLeft($client, 'Archive::concert_page');
}
}

sub retrieve_playlist
{
my $client = shift;
my $id = shift;
my $button = shift;

my $ret = get($client, $etree_details_db_url . $id);
if (0 == $ret) {
Slim::Utils::Timers::setTimer($client, Time::HiRes::time() + 1, \&retrieve_playlist, $id, $button );
} elsif (-1 == $ret) {
Slim::Buttons::Block::unblock($client);
$::d_plugins && Slim::Utils::Misc::msg("Error when calling get: " . $error{$client});
} else {
Slim::Buttons::Block::unblock($client);
my $content = $content{$client};
if ($content) {
my $song;
my $index = 0;
my @playlist = parse_playlist($content);
if (-1 == $#playlist) {
Slim::Display::Animation::showBriefly($client, "Error, getting show, try another.");
$::d_plugins && Slim::Utils::Misc::msg("Couldn't find playlist, take a look at\n");;
$::d_plugins && Slim::Utils::Misc::msg("the result of " . $etree_details_db_url . $id . "\n");
} else {
$concert_by_id{$id} = join($PLAYLISTITEM, @playlist);
}

} else {
Slim::Display::Animation::showBriefly($client, "Error, getting show, try another.");
}
process_concert_button_press_aux($client, $id, $button);
}
}


my %year_page_functions =

(
'up' => sub {
my $client = shift;
$show_index{$client} = Slim::Buttons::Common::scroll($client,
-1,
$show_count{$client} + 1,
$show_index{$client});
$client->update();
},
'down' => sub {
my $client = shift;
$show_index{$client} = Slim::Buttons::Common::scroll($client,
1,
$show_count{$client} + 1,
$show_index{$client});
$client->update();
},
'left' => sub {
my $client = shift;
# reset cache
$show_index{$current_artist{$client}}{$year_index{ $current_artist{$client}}} = $show_index{$client};
Slim::Buttons::Common::popModeRight($client);
},
'right' => sub {
my $client = shift;
# reset cache
$show_index{$current_artist{$client}}{$year_index{ $current_artist{$client}}} = $show_index{$client};
process_concert_button_press($client, 'right');
},
'add' => sub {
my $client = shift;
process_concert_button_press($client, 'add');
},
'play' => sub {
my $client = shift;
process_concert_button_press($client, 'play');
}
);


my $playlist_search_string = ".*<td class=\"fileTitleHeader\">Audio Files(.*?)</table>";
my $song_search_string = ".*<td class=\"fileTitle\">(.*?)</td>.*\?href=\"(.*?vbr.mp3)\?";
my $archive_prefix = "http://www.archive.org";

sub parse_playlist {
$_ = shift;
my $pls_data = "";
my $count = 1;
my @items;
if ( /$playlist_search_string/s ) {
# found song playlist lines, time to build playlist
# we could do real parsing via HTML::TreeBuilder, but this should be faster and ok
my $song_playlist_lines = $1;
while ( $song_playlist_lines =~ s/$song_search_string// ) {
my $name = $1;
my $url = $2;
# this is the whole list of urls, let's find the last one
my $href_string = "href=\"";

if (!defined($url)) {
return([]);
}
my $href_pos = rindex($url, $href_string);
if (-1 == $href_pos) {
next;
} else {
$url = substr($url, $href_pos + length($href_pos) + 3);
}
$url = $archive_prefix . $url;
push @items, $url;
Slim::Music::Info::setTitle($url, $name);
$count++;
}
}
return @items;
}

# Band listing mode
Slim::Buttons::Common::addMode('Archive::year_page ', \%year_page_functions, $year_page_mode_sub);


sub concert_page_mode_sub
{
my $client = shift;
my $id = $which_concert{$client};
$client->lines(\&concert_page_lines);
$current_song{$client}{$id} = $saved_song{$client}{$id} || 0;
$client->update();
}

my $concert_page_mode_sub = *concert_page_mode_sub;

sub concert_page_lines
{
my $client = shift;
my ($line1, $line2);
my @concerts = split($CONCERT_LIST_SEPARATOR, $shows{$current_artist{$client}}
{$year_index{$current_artist{$client}}});
my @playlist = split($PLAYLISTITEM, $concert_by_id{$which_concert{$client}});
my ($id, $concert, $date, $venue)
= split($ID_CONCERT_SEPARATOR,
$concerts[$show_index{$client}]);
$line1 = $date . "/" . $years[$year_index{$current_artist{$client}}] . "/" . $venue .
"/" . $current_artist{$client};
$line2 = Slim::Music::Info::title($playlist[$current_song{$client}{$id}]);
return($line1, $line2, undef, Slim::Hardware::VFD::symbol('notesymbol'));
}

my %concert_page_functions = (
'up' => sub {
my $client = shift;
my $id = $which_concert{$client};
$current_song{$client}{$id} = Slim::Buttons::Common::scroll($client,
-1,
$song_count{$id},
$current_song{$client}{$id} || 0);
$client->update();
},
'down' => sub {
my $client = shift;
my $id = $which_concert{$client};
$current_song{$client}{$id} = Slim::Buttons::Common::scroll($client,
1,
$song_count{$id},
$current_song{$client}{$id} || 0);
$client->update();
},
'left' => sub {
my $client = shift;
my $id = $which_concert{$client};
$saved_song{$client}{$id} = $current_song{$client}{$id};
Slim::Buttons::Common::popModeRight($client);
},
'right' => sub {
my $client = shift;
Slim::Display::Animation::bumpRight($client);
},
'add' => sub {
my $client = shift;
my $id = $which_concert{$client};
my @playlist = split($PLAYLISTITEM, $concert_by_id{$which_concert{$client}});
Slim::Control::Command::execute($client, ['playlist', 'add',
$playlist[$current_song{$client}{$id}]]);
Slim::Display::Animation::showBriefly($client, "Added to current playlist");
},
'play' => sub {
my $client = shift;
my $id = $which_concert{$client};
my @playlist = split($PLAYLISTITEM, $concert_by_id{$which_concert{$client}});
Slim::Control::Command::execute($client, ['playlist', 'play',
$playlist[$current_song{$client}{$id}]]);
}
);

# Concert Listing Mode
Slim::Buttons::Common::addMode('Archive::concert_p age', \%concert_page_functions, $concert_page_mode_sub);



# HTTP routine
use strict;
use Socket;
use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);


# this version of get implements a non-blocking http request as an FSM. The first argument
# is an index into some hash tables that keep the state. Calling it returns either:
# 1 if the content has been received, in which case it is in the hash table 'content',
# indexed by the first argument
#
# 0 keep calling, not done yet
#
# -1 error, error string returned in hash table 'error' indexed by the first argument

my $OPENING = 1;
my $OPENED = 2;
my $GETTING = 3;
my $READ = 4;
my $READ_RESPONSE = 5;
my %socket;
my %paddr;
my %request;
my %response;

# some code borrowed

# nonblocking get, returns 0 if it should be called again,
# 1 if the data has been recieved and -1 if there is an error

my $CRLF = "\015\012";

# Provide a dummy EINPROGRESS for systems that don't have one. Give
# it a documented value. This code is stolen from
# POE::Wheel::SocketFactory.

# yuck.... code borrowed from:
# http://www.nntp.perl.org/group/perl.perl5.porters/42198


BEGIN {
# http://support.microsoft.com/support/kb/articles/Q150/5/37.asp
# defines EINPROGRESS as 10035. We provide it here because some
# Win32 users report POSIX::EINPROGRESS is not vendor-supported.
if ($^O =~ /Win32/ ) {
use Errno qw(EALREADY EAGAIN EISCONN);
*EINPROGRESS = sub () { 10036 };
*EWOULDBLOCK = sub () { 10035 };
} else {
use Errno qw(EINPROGRESS EWOULDBLOCK EALREADY EAGAIN EISCONN);
}
}

sub get
{
my $client = shift;
my $url = shift;
if ($UNKNOWN == $get_status{$client}) {
$content{$client} = $response{$client} = "";
# parse the request, setup the socket and start the open
if ($url =~ m,^http://([^/:\@]+)(?::(\d+))?(/\S*)?$,) {
my $host = $1;
my $port = $2 || 80;
my $path = $3;
my $iaddr = inet_aton($host);
$path = "/" unless defined($path);
my $paddr = sockaddr_in($port, $iaddr);
# set the socket to non blocking
socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
# yuck.... code borrowed from:
# http://www.nntp.perl.org/group/perl.perl5.porters/42198
if ($^O =~ /Win32/) {
my $set_it = "1";
# 126 is FIONBIO (some docs say 0x7F << 16)
ioctl( SOCK,
0x80000000 | (4 << 16) | (ord('f') << 8) | 126,
$set_it);
} else {
fcntl(SOCK, F_SETFL, fcntl(SOCK, F_GETFL, 0) | O_NONBLOCK);
}
my $ret = connect(SOCK, $paddr);
my $netloc = $host;
$netloc .= ":$port" if $port != 80;
$request{$client} = join($CRLF =>
"GET $path HTTP/1.0",
"Host: $netloc",
"User-Agent: SlimServer/Archive",
"", "");


if ($ret) {
# wow, it connected
$get_status{$client} = $OPENED;
return(get($client));
} else {
my $err = $!;
my $nval = $! + 0;
#ok if in progress
if ((EINPROGRESS == $!) || (EWOULDBLOCK == $!)) {
$get_status{$client} = $OPENING;
$paddr{$client} = $paddr;
return(0);
}
else {
my $rval = $! + 0;
$error{$client} = "Cannot connect to '${url}', $!(" . $rval . ")";
close(SOCK);
$get_status{$client} = $UNKNOWN;
return(-1);
}
}
}
$error{$client} = "Couldn't parse '${url}'";
return(-1);
} elsif ($OPENING == $get_status{$client}) {
my $ret = connect(SOCK, $paddr{$client});
if ($ret || (EISCONN == $!)) {
$get_status{$client} = $OPENED;
return(get($client));
} else {
#ok if in progress
if (EALREADY == $!) {
return(0);
}
else {
my $rval = $! + 0;
$error{$client} = "Cannot connect to '${url}', $!(" . $rval . ")";
close(SOCK);
$get_status{$client} = $UNKNOWN;
return(-1);
}
}
} elsif ($OPENED == $get_status{$client}) {
# connected, now send the request
my $byte_count = syswrite(SOCK,$request{$client});
my $length = length($request{$client});
if ($byte_count) {
if ($length == $byte_count) {
#all bytes are written, can now change to read mode
$get_status{$client} = $READ_RESPONSE;
return(get($client));
} else {
$request{$client} = substring($request{$client}, $byte_count);
return(0);
}
} else {
if (EAGAIN == $!) {
return(0);
} else {
$error{$client} = "Cannot write to socket";
close(SOCK);
$get_status{$client} = $UNKNOWN;
return(-1);
}
}
} elsif ($READ_RESPONSE == $get_status{$client}) {
my $data;
my $byte_count = sysread(SOCK, $data, 100000);
if (defined($byte_count)) {
if (0 == $byte_count) {
# end of file, this is an error when it happens here
$error{$client} = "End of file before any real data read...";
close(SOCK);
$get_status{$client} = $UNKNOWN;
return(-1);
} else {
$response{$client} .= $data;
my $pos = index($response{$client}, $CRLF . $CRLF);
if (-1 != $pos) {
$response{$client} =~ / (\d\d\d)/;
my $response_code = $1;
if (200 != $response_code) {
$error{$client} = "HTTP response wasn't 200, was: ${response_code}";
close(SOCK);
$get_status{$client} = $UNKNOWN;
return(-1);
}
$content{$client} = substr($response{$client}, $pos + length($CRLF . $CRLF));
$get_status{$client} = $READ;
}
return(get($client));
}
} else {
if ((EAGAIN == $!) || (EWOULDBLOCK == $!)) {
return(0);
} else {
my $rval = $! + 0;
$error{$client} = "Error " . $rval . " while trying to read from socket";
close(SOCK);
$get_status{$client} = $UNKNOWN;
return(-1);
}
}
} elsif ($READ = $get_status{$client}) {
# reading data

my $data;
my $byte_count = sysread(SOCK, $data, 100000);
if (defined($byte_count)) {
if (0 == $byte_count) {
# end of file, finally
close(SOCK);
$get_status{$client} = $UNKNOWN;
return(1);
} else {
$content{$client} .= $data;
return(get($client));
}
} else {
if ((EAGAIN == $!) || (EWOULDBLOCK == $!)) {
return(0);
} else {
my $rval = $! + 0;
$error{$client} = "Error " . $rval . " while trying to read from socket";
close(SOCK);
$get_status{$client} = $UNKNOWN;
return(-1);
}
}
} else {
$error{$client} = "Illegal status set, bug in function";
$get_status{$client} = $UNKNOWN;
return(-1);
}
}



################################################
### End of Section 2. ###
################################################

################################
### Ignore from here onwards ###
################################

sub getFunctions() {
return \%functions;
}


1;

kdf
2004-04-15, 00:10
Nice work. This removed the unresponsiveness I had when installing the last
version under Linux.

-kdf

Quoting Dan Aronson <dan (AT) catolabs (DOT) org>:

> Thanks to the great feedback of Rob, Dean, Dan, Daniel, Peter and
> Donald, enclosed is
> version 0.92 of the Live Music Archive plugin.