Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

GetNotecardLine help

Ploy Vogel
Registered User
Join date: 27 Aug 2004
Posts: 133
06-02-2005 17:33
I am trying to have a sound play off a list on a notecard when I touch the object. This is the code I am trying. Can anyone tell me what is wrong? Thanks




string gName = "Sounds"; // name of a notecard in the object's inventory
integer gLine = 0; // current line number


default {
state_entry() {
llGetNotecardLine(gName, gLine); // request first line
gLine++;
// increase line count
}

touch_start(integer total_number)
{
llPlaySound(llGetNotecardLine(gName, gLine), 1.0);
}

dataserver(key query_id, string data) {
if (data != EOF) { // not at the end of the notecard
llSay(0, data); // output the line
llGetNotecardLine(gName, gLine); // request next line
gLine++; // increase line count

}
}
}
Vortex Saito
Quintzee Creator
Join date: 10 Sep 2004
Posts: 73
06-02-2005 17:56
The way you are doing it now won't work, because you have in the state_entry a call to the dataserver event. In the dataserver event you read the entire notecard. So if you touch the prim for the soundevent. All the lines in the notecard are already read, so dataserver event returns an end of file (EOF)
Ploy Vogel
Registered User
Join date: 27 Aug 2004
Posts: 133
06-02-2005 18:25
Originally I tried this but I couldn't get it to work either.



string gName = "Sounds"; // name of a notecard in the object's inventory
integer gLine = 0; // current line number


default {

state_entry() {

}

touch_start(integer total_number)
{
llPlaySound(llGetNotecardLine(gName, gLine), 1.0);
}


}
Jon Marlin
Builder, Coder, RL & SL
Join date: 10 Mar 2005
Posts: 297
06-02-2005 18:39
The problem is llGetNotecardLine doesn't return the line from the notecard. It returns a key, which is matched to the key passed into the dataserver event.

The 'data' argument in the dataserver event contains the line from the notecard. The dataserver event is called once for each time you call llGetNotecardLine, with the corresponding line from the notecard as the data string argument.

- Jon
Ploy Vogel
Registered User
Join date: 27 Aug 2004
Posts: 133
06-02-2005 18:42
So Jon, is there a quick and easy solution to what I want to do?
Escort DeFarge
Together
Join date: 18 Nov 2004
Posts: 681
06-03-2005 01:31
Here's a working example I use for the radio tuner at my house. It checks the id of the query, and also (defensively) nulls it out immediately after the check.

The basic notecard format expected by the script is:

# Comment
ADD,http://whatever,My Radio Station Name

It also remembers textures you drop onto the prim so you see that picture next time you choose that station (this is just sugar). The only reason for the 3 second delay between choosing stations is to allow "flicking through" prior to trying to play the stream.

CODE
// Radio Tuner
// Escort DeFarge 2005

integer SIDE = 0;
key DEFAULT_TEXTURE = "06f338cb-18f3-251b-0213-7d0c2f334be2";

// Strided [url, name, texture]
list stations = [ "", "Music OFF", DEFAULT_TEXTURE ];
integer current_station = 0;

key query = NULL_KEY;
string notecard = "Radio Stations";
integer current_line = 0;

default {
//
state_entry() {
current_line = 0;
query = llGetNotecardLine(notecard, current_line);
}

//
dataserver(key id, string info) {
if (id == query) {
query = NULL_KEY;
if (info != EOF) {
if (llStringLength(info) > 0 && llGetSubString(info, 0, 0) != "#") {
list tokens = llParseString2List(info, [","], []);
string command = llToUpper(llList2String(tokens, 0));
if (command == "RESET") {
llSay(0, "Resetting all");
llResetScript();
} else if (command == "REMOVE" && llGetListLength(tokens) > 1) {
string url = llList2String(tokens, 1);
integer index = llListFindList(stations, );
if (index != -1) {
stations = llDeleteSubList(stations, index, index + 2);
llSay(0, "Removed " + url);
}
} else if (command == "ADD" && llGetListLength(tokens) > 1) {
string url = llList2String(tokens, 1);
integer index = llListFindList(stations, [url]);
string name = "Station no. ";
if (llGetListLength(tokens) > 2) {
name = llList2String(tokens, 2);
} else {
if (index == -1) {
name += (string)llGetListLength(stations);
} else {
name += llList2String(stations, index + 1);
}
}
if (index == -1) {
stations += [url, name, llList2Key(stations, 2) ];
} else {
index++;
llListReplaceList(stations, [name], index, index);
}
llSay(0, "Added " + name);
}
}
current_line++;
query = llGetNotecardLine(notecard, current_line);
} else {
llSetText(llList2String(stations, current_station + 1), <1, 1, 1>, 1);
llSetTexture(llList2Key(stations, current_station + 2), SIDE);
llSetTimerEvent(3.0);
}
}
}

//
touch_start(integer num) {
llSetTimerEvent(0.0);
stations = llListReplaceList(stations, [llGetTexture(SIDE)], current_station + 2, current_station + 2);
current_station += 3;
if (current_station >= llGetListLength(stations)) {
current_station = 0;
}
llSetText(llList2String(stations, current_station + 1), <1, 1, 1>, 1);
llSetTexture(llList2Key(stations, current_station + 2), SIDE);
llSetTimerEvent(3.0);
}

//
timer() {
llSetTimerEvent(0.0);
llSetParcelMusicURL(llList2String(stations, current_station));
llSetText("", <1,1,1>, 1);
}

// We don't just do a reset or we'd lose all the textures.
changed(integer change) {
if (change & CHANGED_INVENTORY) {
current_line = 0;
query = llGetNotecardLine(notecard, current_line);
}
}
}
_____________________
http://slurl.com/secondlife/Together
Escort DeFarge
Together
Join date: 18 Nov 2004
Posts: 681
06-03-2005 01:56
...er the quick and easy way... why do you need the notecard at all?

CODE
integer number_of_sounds = 0;
integer current_sound = 0;

default {
state_entry() {
current_sound = 0;
number_of_sounds = llGetInventoryNumber(INVENTORY_SOUND);
}

touch_start(integer num) {
llPlaySound(llGetInventoryName(INVENTORY_SOUND, current_sound), 1.0);
current_sound++;
if (current_sound >= number_of_sounds) {
current_sound = 0;
}
}

changed(integer change) {
if (change & CHANGED_INVENTORY) {
llResetScript();
}
}
}
DISCLAIMER: I'm not in-world and so I didn't actually test this... but it should work just fine.
_____________________
http://slurl.com/secondlife/Together
Ploy Vogel
Registered User
Join date: 27 Aug 2004
Posts: 133
06-03-2005 02:28
Hi Escort,

The object I am making will come with several different sounds and it would be the users choice of which sound to use. What I was trying, was to have all the sounds listed in the notecard and the script would only look at the top line, line 0, and that would be the one to play. If the user wants a different sound then he would enter the name in the first line of the notecard. I don't need the script to go through all the sounds just one but all of the sounds will be available in the contents of the object.

Thanks.
Jon Marlin
Builder, Coder, RL & SL
Join date: 10 Mar 2005
Posts: 297
06-03-2005 05:21
From: Ploy Vogel
So Jon, is there a quick and easy solution to what I want to do?


Yes, you call llGetNotecardInfo once, and the dataserver event will be triggered. The line of the notecard you asked for will be in the second (string) argument of the dataserver event.

If the notecard is empty, the data argument will be EOF.

CODE

string gName = "Sounds"; // name of a notecard in the object's inventory
key gSoundNotecardEventKey = NULL_KEY;

default {

touch_start (integer total_number) {

gSoundNotecardEventKey = llGetNotecardLine (gName, 0);}

dataserver (key query_id, string data) {

if (query_id == gSoundNotecardEventKey)
if (data != EOF) { // not at the end of the notecard
llSay (0, data); // output the line
llPlaySound (data, 1.0);}}
}


- Jon
Ploy Vogel
Registered User
Join date: 27 Aug 2004
Posts: 133
06-03-2005 06:29
This is great Jon, exactly what I need, thanks again.
Kungfu Grasshopper
Registered User
Join date: 19 May 2005
Posts: 3
06-03-2005 14:51
You can also put them all in a list and when you want to call them you can do the same thing.
You can use list2string to get the data you need.