Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

Parcel Media Commands

DrDoug Pennell
e-mail is for old people
Join date: 13 Mar 2007
Posts: 112
09-08-2008 12:25
Hello,

I am trying to build a narrated tour in SL. As the tourist progresses along the path, I want he/she/it to hear audio of me describing what they are seeing.

I have tried using llPlaySound to play sound snippets and that solution does not seem to work reliably, regardless of how I try to preload sounds.

It has been suggested that I should use llParcelMediaCommandList to play the sounds. I have played with this some but have some questions:

Does the PARCEL_MEDIA_COMMAND_TIME flag work with mp3s? I cannot seem to get this to start the audio at any place except the beginning.

Would it be better to use this function to play individual sound snippets as the tour progresses or should I make one long mp3 (say 5 minutes or so) and then try to play the appropriate bits using PARCEL_MEDIA_COMMAND_PAUSE and some combination of llSLeep or llSetTimerEvent?

Thanks,

Doug
Haruki Watanabe
llSLCrash(void);
Join date: 28 Mar 2007
Posts: 434
09-08-2008 13:49
I would suggest, that you have some sensor in an object that senses the Agents which are standing in front of your house/landmark (whatever is there to have the audio played to).

Then use the llParcelMediaCommand to play the specific mp3 for the detected agent only.

Use llSensorRepeat() to repeatedly scan for agents near the object.

Have a list of agents in the objects, which tracks to which agents the mp3 is currently played. If there's a new agent, which isn't in the list, start the mp3 for this agent. If there's an agent in the list, which isn't found in the sensor, stop the playing for this agent using PARCEL_MEDIA_COMMAND_STOP (he/she/it might still be nearby and still have the sound going on).

This way, if there's already an agent listening to the current soundbit and another agent shows up, the new one will hear the soundbit from the beginning, without having the first agent hearing the sound from the beginning, too.

With this approach, you can make an individual mp3 for every stop at your tour, which makes it easier to maintain them and makes the mp3 smaller.

The following is untested (and I'm sure one of our super-coders has a much more brilliant way to do it :)

CODE


list gCurrentAgents;

default{

state_entry(){

// Scan every 1 second for agents within range of 5 meters

llSensor("",NULL_KEY,AGENT,5,PI, 1);
}

sensor(integer num){

integer i;
list presentAgents = []; // Used to check whether we have an agent in the playing list who's not here anymore'

// check whether all the detected Agents are already hearing the sound

for(i=0;i<num;i++){

presentAgents = (presentAgents = []) + presentAgents + llDetectedKey(i);

if(llListFindList(gCurrentAgents) == -1){
// This agent isn't in the list yet, so add it and start the sound
gCurrentAgents = (gCurrentAgents = []) + gCurrentAgents + [llDetectedKey(i)];
llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_AGENT, llDetectedKey(i), PARCEL_MEDIA_COMMAND_URL, "http://www.myserver.com/mySound.mp3", PARCEL_MEDIA_COMMAND_PLAY]);
}
}

// now check if we have an agent in the list, who's not been detected

integer l = llGetListLength(gCurrentAgents);

for(i=0;i<l;i++){
if(llListFindList(presentAgents, [llList2Key(gCurrentAgents, i)] == -1){
// This agent is gone - stop the Stream for her/him/it

llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_AGENT, llDetectedKey(i), PARCEL_MEDIA_COMMAND_URL, "http://www.myserver.com/mySound.mp3", PARCEL_MEDIA_COMMAND_STOP]);
}
}
}
}



HTH
DrDoug Pennell
e-mail is for old people
Join date: 13 Mar 2007
Posts: 112
09-08-2008 14:41
From: Haruki Watanabe
I would suggest, that you have some sensor in an object that senses the Agents which are standing in front of your house/landmark (whatever is there to have the audio played to).

Then use the llParcelMediaCommand to play the specific mp3 for the detected agent only.

Use llSensorRepeat() to repeatedly scan for agents near the object.



Thanks Haruki!

I haven't been able to get this script to compile yet but I'll work on it some more later.

Any advantage of using a sensor to trigger this as opposed to a collision event? I was thinking I would just trigger the sounds when the avatar ran into the (phantom) box. Would that be less laggy than a sensor?

Thanks again,

Doug
Haruki Watanabe
llSLCrash(void);
Join date: 28 Mar 2007
Posts: 434
09-09-2008 00:39
Hi Doug

Yes - a collision would work as well - but you won't have the chance to determine when the agent left the spot and thus, you couldn't stop the sound playing for her/him/it... :)
DrDoug Pennell
e-mail is for old people
Join date: 13 Mar 2007
Posts: 112
09-09-2008 12:30
From: Haruki Watanabe
Hi Doug

Yes - a collision would work as well - but you won't have the chance to determine when the agent left the spot and thus, you couldn't stop the sound playing for her/him/it... :)


Hi Haruki,

That makes sense. Better than a collision event.

Unfortunately I cannot get your script to compile. I apologize - I am not a very skilled coder. I found some small errors (eg needing llSensorRepeat instead of llSensor), but I can't seem to debug the following part:

for(i=0;i<l;i++)
{
if(llListFindList(presentAgents, [llList2Key(gCurrentAgents, i)] == -1)
llParcelMediaCommandList(
[PARCEL_MEDIA_COMMAND_AGENT, llDetectedKey(i),
PARCEL_MEDIA_COMMAND_URL, "http://www.myserver.com/mySound.mp3", PARCEL_MEDIA_COMMAND_STOP]);
}


The llListFindList function gives me a type mismatch - perhaps the list "presentAgents" and the key of the current agent when the llListFindList function requires two lists?

I dunno. Sorry for being so obtuse.

Doug
Very Keynes
LSL is a Virus
Join date: 6 May 2006
Posts: 484
09-09-2008 13:28
Hi Doc,

You are missing a closing bracket, try this:

CODE


for(i=0;i<l;i++)
{
if(llListFindList(presentAgents, [llList2Key(gCurrentAgents, i)]) == -1)
llParcelMediaCommandList(
[PARCEL_MEDIA_COMMAND_AGENT, llDetectedKey(i),
PARCEL_MEDIA_COMMAND_URL, "http://www.myserver.com/mySound.mp3", PARCEL_MEDIA_COMMAND_STOP]);
}



That should compile but I have not tested or read the rest of the code :)
Haruki Watanabe
llSLCrash(void);
Join date: 28 Mar 2007
Posts: 434
09-09-2008 16:36
Thanks Very... :)

Dr - didn't have time yet to try this inworld - hope Very's solution fixed it... :)
DrDoug Pennell
e-mail is for old people
Join date: 13 Mar 2007
Posts: 112
09-10-2008 09:59
From: Haruki Watanabe
Thanks Very... :)

Dr - didn't have time yet to try this inworld - hope Very's solution fixed it... :)


Hi Very and Haruki,

Thanks for all your help. I really appreciate it.

The script now compiles correctly, but I'm not sure it is actually doing what was intended.

The first part seems OK in that as far as I can tell, it will only play the mp3 once for each avatar. At least it only plays once for me. If I want to hear it again I need to reset the script.

So far so good.

However the second (problematic) part does not seem to work. Once the sensor detects me, the mp3 plays through to completion, regardless of whether or not I leave sensor range. This is not really a big deal since this will be part of a tour and the tour vehicle will follow the correct path at the correct pace. I'll put in a script reset so that my students can take the tour more than once and hear the audio again - some of them will need it :).

I would be interested to figure out the second part though, just for my own scripting education.

Thanks again,

Doug
Haruki Watanabe
llSLCrash(void);
Join date: 28 Mar 2007
Posts: 434
09-10-2008 16:03
Hi Doug

Ok - I finally had the time to test this inworld... It was far from being perfect... sorry for that :)

Here it goes:

CODE


list gCurrentAgents;

default{

state_entry(){

// Scan every 2 seconds for agents within range of 5 meters

llSensorRepeat("",NULL_KEY,AGENT,5.0,PI, 2.0);
}

sensor(integer num){

integer i;
list presentAgents = []; // Used to check whether we have an agent in the playing list who's not here anymore'

// check whether all the detected Agents are already hearing the sound

for(i=0;i<num;i++){

presentAgents = (presentAgents = []) + presentAgents + llDetectedKey(i);

if(llListFindList(presentAgents, [llList2Key(gCurrentAgents, i)]) == -1){

llOwnerSay("adding " + llKey2Name(llDetectedKey(i)) + " to the list");

// This agent isn't in the list yet, so add it and start the sound
gCurrentAgents = (gCurrentAgents = []) + gCurrentAgents + [llDetectedKey(i)];
llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_TEXTURE, (key) llGetTexture(0),
PARCEL_MEDIA_COMMAND_AGENT, llDetectedKey(i),
PARCEL_MEDIA_COMMAND_URL, "http://212.112.241.88:8000/listen.pls",
PARCEL_MEDIA_COMMAND_PLAY]);
}
}

// now check if we have an agent in the list, who's not been detected

integer l = llGetListLength(gCurrentAgents);

for(i=0;i<l;i++){

integer pos = llListFindList(presentAgents, [llList2Key(gCurrentAgents, i)]);

if(pos == -1){
// This agent is gone - stop the Stream for her/him/it
llOwnerSay("removing " + llKey2Name(llList2Key(gCurrentAgents, i)) + " from the list");
llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_AGENT, llList2Key(gCurrentAgents, i), PARCEL_MEDIA_COMMAND_STOP]);
// Remove the Agent from the present list
gCurrentAgents = llDeleteSubList(gCurrentAgents, pos, pos);
}
}
}

no_sensor(){
// There are no more Agents present. Try to stop all streams for the Agents in the list

integer l = llGetListLength(gCurrentAgents);
integer i;

for(i=0;i<l;i++){

// This agent is gone - stop the Stream for her/him/it
llOwnerSay("removing " + llKey2Name(llList2Key(gCurrentAgents, i)) + " from the list");
llParcelMediaCommandList([PARCEL_MEDIA_COMMAND_AGENT, llList2Key(gCurrentAgents, i), PARCEL_MEDIA_COMMAND_STOP]);
}

// Remove all agents from the list

gCurrentAgents = [];

}
}



The problem was, that when only one agent was detected, this agent never got deleted from the list, since I forgot to put in a no_sensor-event.

There were some other bugs as well, one, that I didn't mention the texture in the parcel-media-command-list.
The «trick»*that is used here is, that we use the video-channel to play mp3-files (which works pretty well). There's one quirk with that. You have to edit your land-info, go to the media-tab and check the box «Media -> Auto-Scale». If you don't do this, it might not work...

I added some «llOwnerSay»-commands to the code so you can see whether the agent is added or deleted from the list. Once everything is working, you can delete those lines. If you are on group-owned land and have to deed the object to make it work, change those llOwnerSay into «llSay(0, ...)», because you won't hear llOwnerSay-messages from a deeded object...

Hope it works... :)

Cheers

H

P.S. no - pun intended - but the name «Doug» always remembers me of Gary Larson's Farside (beware of Doug) :) http://farm1.static.flickr.com/27/58683157_cf923d8f56.jpg?v=0
DrDoug Pennell
e-mail is for old people
Join date: 13 Mar 2007
Posts: 112
09-12-2008 06:33
From: Haruki Watanabe
Hi Doug

The «trick»*that is used here is, that we use the video-channel to play mp3-files (which works pretty well). There's one quirk with that. You have to edit your land-info, go to the media-tab and check the box «Media -> Auto-Scale». If you don't do this, it might not work...


P.S. no - pun intended - but the name «Doug» always remembers me of Gary Larson's Farside (beware of Doug) :) http://farm1.static.flickr.com/27/58683157_cf923d8f56.jpg?v=0


Hi Haruki,

Thanks so much for this! It works like a charm.

I have a question though - why do you use the video channel to play mp3 files? Why not just use:

PARCEL_MEDIA_COMMAND_TYPE, "audio/mpeg" ?

Anyway - thanks again for all your help with this. It is a huge help to me and my students will appreciate it.

BTW, I have that picture on my bulletin board above my desk at work, along with these two.

http://obgyn.osu.edu/images/Doug-1.jpg
http://obgyn.osu.edu/images/Doug-2.jpg

Take Care,

Doug
Haruki Watanabe
llSLCrash(void);
Join date: 28 Mar 2007
Posts: 434
09-12-2008 08:35
Hi Doug

Now that I read the manual of the Parcel-media-command again, I'm asking myself the same question... Seems like you pointed me to something here... Ah well... I should read manuals more thouroughly...

Glad' it's working now, though :)

Happy Farside!