<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="http://opensimulator.org/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>http://opensimulator.org/index.php?action=history&amp;feed=atom&amp;title=Playing_Music_files_in_OpenSim</id>
		<title>Playing Music files in OpenSim - Revision history</title>
		<link rel="self" type="application/atom+xml" href="http://opensimulator.org/index.php?action=history&amp;feed=atom&amp;title=Playing_Music_files_in_OpenSim"/>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/index.php?title=Playing_Music_files_in_OpenSim&amp;action=history"/>
		<updated>2026-05-28T19:05:51Z</updated>
		<subtitle>Revision history for this page on the wiki</subtitle>
		<generator>MediaWiki 1.19.9</generator>

	<entry>
		<id>http://opensimulator.org/index.php?title=Playing_Music_files_in_OpenSim&amp;diff=53539&amp;oldid=prev</id>
		<title>JeffKelley: Created page with &quot;==Introduction==   Web-hosted audio files are the simplest way to play Music in OpenSimulator. Entering the url of an audio file in About Land &gt; Sound &gt; Music instructs the vi...&quot;</title>
		<link rel="alternate" type="text/html" href="http://opensimulator.org/index.php?title=Playing_Music_files_in_OpenSim&amp;diff=53539&amp;oldid=prev"/>
				<updated>2023-06-02T09:58:35Z</updated>
		
		<summary type="html">&lt;p&gt;Created page with &amp;quot;==Introduction==   Web-hosted audio files are the simplest way to play Music in OpenSimulator. Entering the url of an audio file in About Land &amp;gt; Sound &amp;gt; Music instructs the vi...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==Introduction==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Web-hosted audio files are the simplest way to play Music in OpenSimulator. Entering the url of an audio file in About Land &amp;gt; Sound &amp;gt; Music instructs the viewer to play this file. The only software you need is a web server.&lt;br /&gt;
&lt;br /&gt;
Unlike streaming, where the content is choosen by the broadcaster, the songs  to play may be choosen in-world using a script.&lt;br /&gt;
&lt;br /&gt;
==Making a jukebox==&lt;br /&gt;
&lt;br /&gt;
First, prepare a set of music files on a web directory. Make this directory listable (Apache directive Options +Indexes). The result is as follow :&lt;br /&gt;
&lt;br /&gt;
http://www.pescadoo.net/oswiki/apache_directory_list.jpg&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Next, write a script that will read and parse this page to build a list of songs. Finally, present this list to the user (this example use dynamic textures) and provide a selection mechanism (click on the song name). One the selected song name is obtained, call llSetParcelMusicURL &lt;br /&gt;
&lt;br /&gt;
A more sophisticated script can browse multiple web directories, allowing for a unlimited number of songs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;lsl&amp;quot;&amp;gt; &lt;br /&gt;
//&lt;br /&gt;
// Sample jukebox script&lt;br /&gt;
// &lt;br /&gt;
&lt;br /&gt;
string musicDirectoryUrl = &amp;quot;http://my.web.server/music/wildfire/&amp;quot;;&lt;br /&gt;
list Songs;&lt;br /&gt;
&lt;br /&gt;
//&lt;br /&gt;
// Get song list from the HTTP server&lt;br /&gt;
//&lt;br /&gt;
&lt;br /&gt;
QueryMusicDirectory (string url)&lt;br /&gt;
{&lt;br /&gt;
    // Default MAXLENGTH of 2048 probably too small&lt;br /&gt;
    // Extend to max OpenSim default of 16384&lt;br /&gt;
    // This can be further extended in the [Network]&lt;br /&gt;
    // section of OpenSim.ini editing HttpBodyMaxLenMAX&lt;br /&gt;
&lt;br /&gt;
    llHTTPRequest (url, [HTTP_BODY_MAXLENGTH, 16384], &amp;quot;&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
list ParseMusicDirectory (string html)&lt;br /&gt;
{&lt;br /&gt;
    list result;&lt;br /&gt;
    list lines = llParseString2List (html, [&amp;quot;\n&amp;quot;], [ ]);&lt;br /&gt;
    for (integer l=0; l&amp;lt;llGetListLength(lines); l++)&lt;br /&gt;
    {&lt;br /&gt;
        string line = llList2String (lines, l);&lt;br /&gt;
&lt;br /&gt;
        // Crude HTML parsing&lt;br /&gt;
    &lt;br /&gt;
        integer p = llSubStringIndex (line, &amp;quot;&amp;lt;a href=&amp;quot;);&lt;br /&gt;
        if (p != -1) line = llDeleteSubString (line, 0, p+7);&lt;br /&gt;
&lt;br /&gt;
        p = llSubStringIndex (line, &amp;quot;&amp;gt;&amp;quot;);&lt;br /&gt;
        if (p != -1) line = llDeleteSubString (line, p, -1);&lt;br /&gt;
&lt;br /&gt;
        // Remove leading and trailing quotes&lt;br /&gt;
&lt;br /&gt;
        if (llGetSubString (line, 0,0) == &amp;quot;\&amp;quot;&amp;quot;)&lt;br /&gt;
            line = llDeleteSubString (line, 0,0);&lt;br /&gt;
&lt;br /&gt;
        if (llGetSubString (line, -1,-1) == &amp;quot;\&amp;quot;&amp;quot;)&lt;br /&gt;
            line = llDeleteSubString (line, -1,-1);&lt;br /&gt;
            &lt;br /&gt;
        if (llGetSubString (line, -4,-1) == &amp;quot;.mp3&amp;quot;)&lt;br /&gt;
        {&lt;br /&gt;
            line = llDeleteSubString (line, -4,-1);&lt;br /&gt;
            result += [ line ];&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//&lt;br /&gt;
// Matrix drawing stuff&lt;br /&gt;
//&lt;br /&gt;
&lt;br /&gt;
integer DISPLAY_SIDE = 1;   // Active side&lt;br /&gt;
integer TEXTURE_SIZE = 512;&lt;br /&gt;
integer FONT_SIZE = 10;&lt;br /&gt;
integer COLUMNS = 3;    // Holds 3x16 items&lt;br /&gt;
integer ROWS = 16;      // Extend if necessary&lt;br /&gt;
&lt;br /&gt;
string cellBorderColor      = &amp;quot;FFFFFFFF&amp;quot;;&lt;br /&gt;
string backgroundColor      = &amp;quot;FF555555&amp;quot;;&lt;br /&gt;
string cellBackgroundColor  = &amp;quot;FF000055&amp;quot;;&lt;br /&gt;
string cellForegroundColor  = &amp;quot;FFFFFFFF&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
string drawList;&lt;br /&gt;
&lt;br /&gt;
displayBegin() {&lt;br /&gt;
    drawList = &amp;quot;&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
displayEnd() {&lt;br /&gt;
    osSetDynamicTextureDataFace ( &amp;quot;&amp;quot;, &amp;quot;vector&amp;quot;, drawList,&lt;br /&gt;
        &amp;quot;width:&amp;quot;+(string)TEXTURE_SIZE+&amp;quot;,height:&amp;quot;+(string)TEXTURE_SIZE, 0, DISPLAY_SIDE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
drawCell (integer x, integer y, string text) {&lt;br /&gt;
    integer CELL_HEIGHT = TEXTURE_SIZE / ROWS;&lt;br /&gt;
    integer CELL_WIDHT  = TEXTURE_SIZE / COLUMNS;&lt;br /&gt;
    integer xTopLeft    = x*CELL_WIDHT;&lt;br /&gt;
    integer yTopLeft    = y*CELL_HEIGHT;&lt;br /&gt;
&lt;br /&gt;
    // Draw border&lt;br /&gt;
&lt;br /&gt;
    drawList = osSetPenColor   (drawList, cellBorderColor);&lt;br /&gt;
    drawList = osMovePen       (drawList, xTopLeft, yTopLeft);&lt;br /&gt;
    drawList = osDrawRectangle (drawList, CELL_WIDHT, CELL_HEIGHT);&lt;br /&gt;
&lt;br /&gt;
    // Fill background&lt;br /&gt;
&lt;br /&gt;
    drawList = osSetPenColor         (drawList, cellBackgroundColor);&lt;br /&gt;
    drawList = osMovePen             (drawList, xTopLeft+2, yTopLeft+2);&lt;br /&gt;
    drawList = osDrawFilledRectangle (drawList, CELL_WIDHT-3, CELL_HEIGHT-3);&lt;br /&gt;
&lt;br /&gt;
    // Draw text&lt;br /&gt;
&lt;br /&gt;
    xTopLeft += 10;  // Center text in cell&lt;br /&gt;
    yTopLeft += 08;  // Center text in cell&lt;br /&gt;
    drawList = osSetPenColor (drawList, cellForegroundColor);&lt;br /&gt;
    drawList = osMovePen     (drawList, xTopLeft, yTopLeft);&lt;br /&gt;
    drawList = osDrawText    (drawList, text);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
drawTable(list items) {&lt;br /&gt;
    displayBegin();&lt;br /&gt;
&lt;br /&gt;
    drawList = osSetPenSize  (drawList, 1);&lt;br /&gt;
    drawList = osSetFontSize (drawList, FONT_SIZE);&lt;br /&gt;
&lt;br /&gt;
    drawList = osMovePen     (drawList, 0, 0);&lt;br /&gt;
    drawList = osSetPenColor (drawList, backgroundColor);&lt;br /&gt;
    drawList = osDrawFilledRectangle (drawList, TEXTURE_SIZE, TEXTURE_SIZE);&lt;br /&gt;
&lt;br /&gt;
    integer x; integer y;&lt;br /&gt;
    for (x=0; x&amp;lt;COLUMNS; x++)&lt;br /&gt;
        for (y=0; y&amp;lt;ROWS; y++)&lt;br /&gt;
            drawCell (x, y, llList2String (items, y+x*ROWS));&lt;br /&gt;
    displayEnd();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
integer getCellIndex(vector point) {&lt;br /&gt;
    integer y = (ROWS-1) - llFloor(point.y*ROWS); // Top to bottom&lt;br /&gt;
    integer x = llFloor(point.x*COLUMNS);         // Left to right&lt;br /&gt;
    integer index = (y+x*ROWS);&lt;br /&gt;
    return index;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//&lt;br /&gt;
// Click action&lt;br /&gt;
//&lt;br /&gt;
//  To use llSetParcelMusicURL, you need to own the parcel&lt;br /&gt;
//  The object owner must also be the land owner. If the land&lt;br /&gt;
//  is deeded to a group the object will need to be deeded to&lt;br /&gt;
//  the same group for this function to work.&lt;br /&gt;
&lt;br /&gt;
HandleClick (vector point) {&lt;br /&gt;
    integer index = getCellIndex(point);&lt;br /&gt;
    MoveIndex (index);&lt;br /&gt;
&lt;br /&gt;
    string song = llList2String (Songs, index);&lt;br /&gt;
    if (song == &amp;quot;&amp;quot;) return; // Blank cell clicked&lt;br /&gt;
&lt;br /&gt;
    if (song == &amp;quot;STOP&amp;quot;)&lt;br /&gt;
    {&lt;br /&gt;
        llWhisper (0, &amp;quot;Stopping music&amp;quot;);&lt;br /&gt;
        llSetParcelMusicURL (&amp;quot;&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        llWhisper (0, &amp;quot;Now playing &amp;quot;+song);&lt;br /&gt;
        llSetParcelMusicURL (musicDirectoryUrl+song+&amp;quot;.mp3&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
integer INDEX_PRIM = 2; // Optional colored, semi-transparent prim&lt;br /&gt;
                        // to place in front of selection&lt;br /&gt;
&lt;br /&gt;
MoveIndex(integer index)&lt;br /&gt;
{&lt;br /&gt;
    integer x = index / ROWS;&lt;br /&gt;
    integer y = index % ROWS;&lt;br /&gt;
&lt;br /&gt;
    vector size = llGetScale();&lt;br /&gt;
    float xIndex = - (size.x/2) + (x+0.5) * size.x / COLUMNS;&lt;br /&gt;
    float yIndex =   (size.y/2) - (y+0.5) * size.y / ROWS;&lt;br /&gt;
&lt;br /&gt;
    vector indexPos = &amp;lt; xIndex, yIndex, size.z/2 &amp;gt;;&lt;br /&gt;
    llSetLinkPrimitiveParamsFast (INDEX_PRIM, [PRIM_POS_LOCAL, indexPos]);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
default&lt;br /&gt;
{&lt;br /&gt;
    state_entry()&lt;br /&gt;
    {&lt;br /&gt;
        QueryMusicDirectory (musicDirectoryUrl);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    http_response (key request_id, integer status, list metadata, string body)&lt;br /&gt;
    {&lt;br /&gt;
        if (status == 200)&lt;br /&gt;
        {&lt;br /&gt;
            Songs = ParseMusicDirectory (body);&lt;br /&gt;
            Songs += [ &amp;quot;STOP&amp;quot; ];&lt;br /&gt;
            drawTable (Songs);&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
            llOwnerSay (&amp;quot;HTTP error &amp;quot;+(string)status);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    touch_start (integer n) {&lt;br /&gt;
        vector point = llDetectedTouchST(0);&lt;br /&gt;
        integer face = llDetectedTouchFace(0);&lt;br /&gt;
        integer link = llDetectedLinkNumber(0);&lt;br /&gt;
&lt;br /&gt;
        if (face != DISPLAY_SIDE) return;&lt;br /&gt;
        if (point == TOUCH_INVALID_TEXCOORD) return;&lt;br /&gt;
&lt;br /&gt;
        HandleClick (point);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
[[Streaming_Media_in_OpenSim]]&lt;/div&gt;</summary>
		<author><name>JeffKelley</name></author>	</entry>

	</feed>