04-12-2004 18:06
Someone once asked if Linden Lab could make Winamp controllable via Second Life. Well, I haven't gotten Winamp controls built, but I have gerry-rigged a Internet Explorer MP3 player that you can control via Second Life.

Ingredients:
Inside Second Life:
1 LSL script named "player"
1 Notecard named "playlist"
1 Prim

Outside Second Life:
1 Web hosting account
1 POP3 email address
1 Perl script called "player.pl"
1 HTML file called "index.html"

Instructions:

1. Create a prim to put the player and playlist into, and put them in there

2. Create a directory on your computer's harddrive to hold MP3's

3. Go into that directory with a commandline and type: dir/b *.mp3

4. Copy the directory listing, and paste the results into playlist

5. Setup player.pl and index.html on your webhost, change email settings accordingly

6. Bring up the index.html in Internet Explorer -- this uses some crufty Microsoft HTML so it won't work in Mozilla

7. Run your script in-world, and type /play and a number -- your playlist starts counting with 0

8. Enjoy the music!!!

The following bits of code are the three files (player, player.pl, and index.html) you need to get all of this to work...

player - LSL

CODE

// Globals
string EMAIL = "";
string PLIST = "";
key OWNER;

default
{
state_entry()
{
OWNER = llGetOwner();
llListen(0, "", OWNER, "");
}

listen(integer channel, string name, key id, string msg)
{
list words = llParseString2List(msg, [" "], [""]);
string cmd = llList2String(words, 0);
integer mpg = (integer)llList2String(words, 1);

if (cmd == "/play")
{
llGetNotecardLine(PLIST, mpg);
}
}

dataserver(key requested, string data)
{
llWhisper(0, "Sending request for: " + data);
llEmail(EMAIL, "Player", "Play this: " + data);
llWhisper(0, "Request sent...");
}
}


player.pl - Perl

CODE

#!/usr/bin/perl -w
# player.pl
# by: Andrew Burton - [email]tuglyraisin@aol.com[/email]
#####

# modules
use strict;
use Net::POP3;
use CGI;

# globals
my $page = CGI->new();

# mail variables
my $id = '';
my $pw = '';
my $ms = '';

# web variables
my $domain = 'andy.hammerofgod.net/mp3';
my $script = 'player.pl';
my $url = 'http://' . $domain . '/' . $script;

# miscellaneous variables
my $check = 0;
my $messtext = '';
my %entry = ();

# web data
# declared
my $path = '0';
my $dirpath = '';
# defined
if ($page->param('path')) { $path = $page->param('path'); }
if ($page->param('dirpath')) { $dirpath = $page->param('dirpath'); }
else { &error_msg("You didn't choose a path for you MP3's."); }

# where to go
if ($path eq '0')
{
# simple HTML frames
print $page->header() .
'<html><head><title>Player</title></head><frameset rows="50%,50%">' .
'<frame src="' . $script . '?path=top&dirpath=' . $dirpath . '" name="top">' .
'<frame src="' . $script . '?path=bot&dirpath=' . $dirpath . '" name="bot">' .
'</frameset></html>';
}

elsif ($path eq 'top')
{
# local web variables
my $yn = 0;
my $song = '';
my $nsong = '';
# check web data
if ($page->param('song')) { $song = $page->param('song'); }

# check mail
my $pop = Net::POP3->new($ms, Default => 1);
unless ($pop) { &error_msg("Cannot connect to POP3 server."); }

my $logcheck = $pop->login($id, $pw);
unless ($logcheck) { &error_msg("Die could not login."); }

my $msg = $pop->list();
unless ($msg =~ m/0E0/i) {
foreach my $msgid (keys(%$msg)) {
my $msg_sender = $pop->get($msgid);
foreach my $mline (@$msg_sender) {
if ($mline =~ m/Play this\:/) {
my ($dont, $dent) = split(/: /, $mline);
$nsong = $dent;
$nsong =~ s/\n//g;
}
}

# Deletes the message
$pop->delete($msgid);

# Resets some global variables;
$check = 0;
$messtext = '';
}
}

# closes the connection
$pop->quit();

# Check for a different song
if ($song ne $nsong)
{
$yn = 1;
$song = $nsong;
}

print $page->header() .
'<html><head><meta http-equiv=Refresh CONTENT="10; URL=' .
$url . '?path=top&dirpath=' . $dirpath . '">' . "\n" .
'<script type="text/javascript">' . "\n" .
'function newsong()' . "\n" .
'{' . "\n" . 'parent.bot.location.href="' . $url . '?path=bot&dirpath=' . $dirpath .
'&song=' . $song . '"' . "\n" . '}' . "\n" . '</script>' . "\n" .
'</head><body bgcolor="white" text="black">' .
$page->p() . $page->b("Path = " . $dirpath) .
$page->p() . $page->b("Song = " . $song);

if ($yn == 1 && $nsong ne '')
{
print "\n" . '<script type="text/javascript">' . "\n" .
'newsong()' . "\n" .
'</script>' . "\n";
}

print '</body></html>';
}

elsif ($path eq 'bot')
{
# local variables
my $song = '';
if ($page->param('song')) { $song = $page->param('song'); }

print $page->header() .
$page->start_html() .
$page->p('Playing: ' . $dirpath . '/' . $song) .
'<embed src="file://' . $dirpath . '/' . $song . '" autostart>' .
$page->end_html();
}

# exits the program
exit;

#####

# error message
sub error_msg
{
my ($error) = @_;
print $page->header() .
$page->start_html(-title => 'Error!!!') .
$page->h1($error) .
$page->end_html();
exit;
}


index.html - HTML

CODE

<html>
<head><title>SL MP3 Player</title></head>
<body>
<p>Besure to use forward slashes in your path: <b>c:/mp3list</b></p>
<form method="POST" action="player.pl">
<input type="text" name="dirpath" value=""><br>
<input type="Submit"> <input type="Reset">
</form>
</body>
</html>


I know it works, but there is room for improvement... Just don't expect me to improve it. This is a proof of concept work to show that it is very possible to control mundane things via Second Life.
_____________________
"All designers in SL need to be aware of the fact that there are now quite simple methods of complete texture theft in SL that are impossible to stop..." - Cristiano Midnight

Ad aspera per intelligentem prohibitus.