//--------------------------------------------------------------------
// LLPolyMeshSharedData::loadMesh()
//--------------------------------------------------------------------
BOOL LLPolyMeshSharedData::loadMesh( const std::string& fileName )
{
        //-------------------------------------------------------------------------
        // Open the file
        //-------------------------------------------------------------------------
        if(fileName.empty())
        {
                LL_ERRS() << "Filename is Empty!" << LL_ENDL;
                return FALSE;
        }
        LLFILE* fp = LLFile::fopen(fileName, "rb");                     /*Flawfinder: ignore*/
        if (!fp)
        {
                LL_ERRS() << "can't open: " << fileName << LL_ENDL;
                return FALSE;
        }

        //-------------------------------------------------------------------------
        // Read a chunk
        //-------------------------------------------------------------------------
        char header[128];               /*Flawfinder: ignore*/
        if (fread(header, sizeof(char), 128, fp) != 128)
        {
                LL_WARNS() << "Short read" << LL_ENDL;
        }

        //-------------------------------------------------------------------------
        // Check for proper binary header
        //-------------------------------------------------------------------------
        BOOL status = FALSE;
        if ( strncmp(header, HEADER_BINARY, strlen(HEADER_BINARY)) == 0 )       /*Flawfinder: ignore*/
        {
                LL_DEBUGS() << "Loading " << fileName << LL_ENDL;

                //----------------------------------------------------------------
                // File Header (seek past it)
                //----------------------------------------------------------------
                fseek(fp, 24, SEEK_SET);

                //----------------------------------------------------------------
                // HasWeights
                //----------------------------------------------------------------
                U8 hasWeights;
                size_t numRead = fread(&hasWeights, sizeof(U8), 1, fp);
                if (numRead != 1)
                {
                        LL_ERRS() << "can't read HasWeights flag from " << fileName << LL_ENDL;
                        return FALSE;
                }
                if (!isLOD())
                {
                        mHasWeights = (hasWeights==0) ? FALSE : TRUE;
                }

                //----------------------------------------------------------------
                // HasDetailTexCoords
                //----------------------------------------------------------------
                U8 hasDetailTexCoords;
                numRead = fread(&hasDetailTexCoords, sizeof(U8), 1, fp);
                if (numRead != 1)
                {
                        LL_ERRS() << "can't read HasDetailTexCoords flag from " << fileName << LL_ENDL;
                        return FALSE;
                }

                //----------------------------------------------------------------
                // Position
                //----------------------------------------------------------------
                LLVector3 position;
                numRead = fread(position.mV, sizeof(float), 3, fp);
                llendianswizzle(position.mV, sizeof(float), 3);
                if (numRead != 3)
                {
                        LL_ERRS() << "can't read Position from " << fileName << LL_ENDL;
                        return FALSE;
                }
                setPosition( position );

                //----------------------------------------------------------------
                // Rotation
                //----------------------------------------------------------------
                LLVector3 rotationAngles;
                numRead = fread(rotationAngles.mV, sizeof(float), 3, fp);
                llendianswizzle(rotationAngles.mV, sizeof(float), 3);
                if (numRead != 3)
                {
                        LL_ERRS() << "can't read RotationAngles from " << fileName << LL_ENDL;
                        return FALSE;
                }

                U8 rotationOrder;
                numRead = fread(&rotationOrder, sizeof(U8), 1, fp);

                if (numRead != 1)
                {
                        LL_ERRS() << "can't read RotationOrder from " << fileName << LL_ENDL;
                        return FALSE;
                }

                rotationOrder = 0;

                setRotation( mayaQ(     rotationAngles.mV[0],
                                        rotationAngles.mV[1],
                                        rotationAngles.mV[2],
                                        (LLQuaternion::Order)rotationOrder ) );

                //----------------------------------------------------------------
                // Scale
                //----------------------------------------------------------------
                LLVector3 scale;
                numRead = fread(scale.mV, sizeof(float), 3, fp);
                llendianswizzle(scale.mV, sizeof(float), 3);
                if (numRead != 3)
                {
                        LL_ERRS() << "can't read Scale from " << fileName << LL_ENDL;
                        return FALSE;
                }
                setScale( scale );

                //-------------------------------------------------------------------------
                // Release any existing mesh geometry
                //-------------------------------------------------------------------------
                freeMeshData();

                U16 numVertices = 0;

                //----------------------------------------------------------------
                // NumVertices
                //----------------------------------------------------------------
                if (!isLOD())
                {
                        numRead = fread(&numVertices, sizeof(U16), 1, fp);
                        llendianswizzle(&numVertices, sizeof(U16), 1);
                        if (numRead != 1)
                        {
                                LL_ERRS() << "can't read NumVertices from " << fileName << LL_ENDL;
                                return FALSE;
                        }

                        allocateVertexData( numVertices );      

						for (U16 i = 0; i < numVertices; ++i)
						{
							//----------------------------------------------------------------
							// Coords
							//----------------------------------------------------------------
							numRead = fread(&mBaseCoords[i], sizeof(float), 3, fp);
							llendianswizzle(&mBaseCoords[i], sizeof(float), 3);
							if (numRead != 3)
							{
									LL_ERRS() << "can't read Coordinates from " << fileName << LL_ENDL;
									return FALSE;
							}
						}

						for (U16 i = 0; i < numVertices; ++i)
						{
							//----------------------------------------------------------------
							// Normals
							//----------------------------------------------------------------
							numRead = fread(&mBaseNormals[i], sizeof(float), 3, fp);
							llendianswizzle(&mBaseNormals[i], sizeof(float), 3);
							if (numRead != 3)
							{
									LL_ERRS() << " can't read Normals from " << fileName << LL_ENDL;
									return FALSE;
							}
						}

						for (U16 i = 0; i < numVertices; ++i)
						{
							//----------------------------------------------------------------
							// Binormals
							//----------------------------------------------------------------
							numRead = fread(&mBaseBinormals[i], sizeof(float), 3, fp);
							llendianswizzle(&mBaseBinormals[i], sizeof(float), 3);
							if (numRead != 3)
							{
									LL_ERRS() << " can't read Binormals from " << fileName << LL_ENDL;
									return FALSE;
							}
						}

                        //----------------------------------------------------------------
                        // TexCoords
                        //----------------------------------------------------------------
                        numRead = fread(mTexCoords, 2*sizeof(float), numVertices, fp);
                        llendianswizzle(mTexCoords, sizeof(float), 2*numVertices);
                        if (numRead != numVertices)
                        {
                                LL_ERRS() << "can't read TexCoords from " << fileName << LL_ENDL;
                                return FALSE;
                        }

                        //----------------------------------------------------------------
                        // DetailTexCoords
                        //----------------------------------------------------------------
                        if (mHasDetailTexCoords)
                        {
                                numRead = fread(mDetailTexCoords, 2*sizeof(float), numVertices, fp);
                                llendianswizzle(mDetailTexCoords, sizeof(float), 2*numVertices);
                                if (numRead != numVertices)
                                {
                                        LL_ERRS() << "can't read DetailTexCoords from " << fileName << LL_ENDL;
                                        return FALSE;
                                }
                        }

                        //----------------------------------------------------------------
                        // Weights
                        //----------------------------------------------------------------
                        if (mHasWeights)
                        {
                                numRead = fread(mWeights, sizeof(float), numVertices, fp);
                                llendianswizzle(mWeights, sizeof(float), numVertices);
                                if (numRead != numVertices)
                                {
                                        LL_ERRS() << "can't read Weights from " << fileName << LL_ENDL;
                                        return FALSE;
                                }
                        }
                }

                //----------------------------------------------------------------
                // NumFaces
                //----------------------------------------------------------------
                U16 numFaces;
                numRead = fread(&numFaces, sizeof(U16), 1, fp);
                llendianswizzle(&numFaces, sizeof(U16), 1);
                if (numRead != 1)
                {
                        LL_ERRS() << "can't read NumFaces from " << fileName << LL_ENDL;
                        return FALSE;
                }
                allocateFaceData( numFaces );


                //----------------------------------------------------------------
                // Faces
                //----------------------------------------------------------------
                U32 i;
                U32 numTris = 0;
                for (i = 0; i < numFaces; i++)
                {
                        S16 face[3];
                        numRead = fread(face, sizeof(U16), 3, fp);
                        llendianswizzle(face, sizeof(U16), 3);
                        if (numRead != 3)
                        {
                                LL_ERRS() << "can't read Face[" << i << "] from " << fileName << LL_ENDL;
                                return FALSE;
                        }
                        if (mReferenceData)
                        {
                                llassert(face[0] < mReferenceData->mNumVertices);
                                llassert(face[1] < mReferenceData->mNumVertices);
                                llassert(face[2] < mReferenceData->mNumVertices);
                        }
                        
                        if (isLOD())
                        {
                                // store largest index in case of LODs
                                for (S32 j = 0; j < 3; j++)
                                {
                                        if (face[j] > mNumVertices - 1)
                                        {
                                                mNumVertices = face[j] + 1;
                                        }
                                }
                        }
                        mFaces[i][0] = face[0];
                        mFaces[i][1] = face[1];
                        mFaces[i][2] = face[2];

//                      S32 j;
//                      for(j = 0; j < 3; j++)
//                      {
//                              std::vector<S32> *face_list = mVertFaceMap.getIfThere(face[j]);
//                              if (!face_list)
//                              {
//                                      face_list = new std::vector<S32>;
//                                      mVertFaceMap.addData(face[j], face_list);
//                              }
//                              face_list->put(i);
//                      }

                        numTris++;
                }

                LL_DEBUGS() << "verts: " << numVertices 
                         << ", faces: "   << numFaces
                         << ", tris: "    << numTris
                         << LL_ENDL;

                //----------------------------------------------------------------
                // NumSkinJoints
                //----------------------------------------------------------------
                if (!isLOD())
                {
                        U16 numSkinJoints = 0;
                        if ( mHasWeights )
                        {
                                numRead = fread(&numSkinJoints, sizeof(U16), 1, fp);
                                llendianswizzle(&numSkinJoints, sizeof(U16), 1);
                                if (numRead != 1)
                                {
                                        LL_ERRS() << "can't read NumSkinJoints from " << fileName << LL_ENDL;
                                        return FALSE;
                                }
                                allocateJointNames( numSkinJoints );
                        }

                        //----------------------------------------------------------------
                        // SkinJoints
                        //----------------------------------------------------------------
                        for (i=0; i < numSkinJoints; i++)
                        {
                                char jointName[64+1];
                                numRead = fread(jointName, sizeof(jointName)-1, 1, fp);
                                jointName[sizeof(jointName)-1] = '\0'; // ensure nul-termination
                                if (numRead != 1)
                                {
                                        LL_ERRS() << "can't read Skin[" << i << "].Name from " << fileName << LL_ENDL;
                                        return FALSE;
                                }

                                std::string *jn = &mJointNames[i];
                                *jn = jointName;
                        }

                        //-------------------------------------------------------------------------
                        // look for morph section
                        //-------------------------------------------------------------------------
                        char morphName[64+1];
                        morphName[sizeof(morphName)-1] = '\0'; // ensure nul-termination
                        while(fread(morphName, sizeof(char), 64, fp) == 64)
                        {
                                if (!strcmp(morphName, "End Morphs"))
                                {
                                        // we reached the end of the morphs
                                        break;
                                }
                                LLPolyMorphData* morph_data = new LLPolyMorphData(std::string(morphName));

                                BOOL result = morph_data->loadBinary(fp, this);

                                if (!result)
                                {
                                        delete morph_data;
                                        continue;
                                }

                                mMorphData.insert(morph_data);

                                if (!strcmp(morphName, "Breast_Female_Cleavage"))
                                {
                                        mMorphData.insert(clone_morph_param_cleavage(morph_data,
                                                                                     .75f,
                                                                                     "Breast_Physics_LeftRight_Driven"));
                                }

                                if (!strcmp(morphName, "Breast_Female_Cleavage"))
                                {
                                        mMorphData.insert(clone_morph_param_duplicate(morph_data,
										      "Breast_Physics_InOut_Driven"));
                                }
                                if (!strcmp(morphName, "Breast_Gravity"))
                                {
                                        mMorphData.insert(clone_morph_param_duplicate(morph_data,
										      "Breast_Physics_UpDown_Driven"));
                                }

                                if (!strcmp(morphName, "Big_Belly_Torso"))
                                {
                                        mMorphData.insert(clone_morph_param_direction(morph_data,
										      LLVector3(0,0,0.05f),
										      "Belly_Physics_Torso_UpDown_Driven"));
                                }

                                if (!strcmp(morphName, "Big_Belly_Legs"))
                                {
                                        mMorphData.insert(clone_morph_param_direction(morph_data,
										      LLVector3(0,0,0.05f),
										      "Belly_Physics_Legs_UpDown_Driven"));
                                }

                                if (!strcmp(morphName, "skirt_belly"))
                                {
                                        mMorphData.insert(clone_morph_param_direction(morph_data,
										      LLVector3(0,0,0.05f),
										      "Belly_Physics_Skirt_UpDown_Driven"));
                                }

                                if (!strcmp(morphName, "Small_Butt"))
                                {
                                        mMorphData.insert(clone_morph_param_direction(morph_data,
										      LLVector3(0,0,0.05f),
										      "Butt_Physics_UpDown_Driven"));
                                }
                                if (!strcmp(morphName, "Small_Butt"))
                                {
                                        mMorphData.insert(clone_morph_param_direction(morph_data,
										      LLVector3(0,0.03f,0),
										      "Butt_Physics_LeftRight_Driven"));
                                }
                        }

                        S32 numRemaps;
                        if (fread(&numRemaps, sizeof(S32), 1, fp) == 1)
                        {
                                llendianswizzle(&numRemaps, sizeof(S32), 1);
                                for (S32 i = 0; i < numRemaps; i++)
                                {
                                        S32 remapSrc;
                                        S32 remapDst;
                                        if (fread(&remapSrc, sizeof(S32), 1, fp) != 1)
                                        {
                                                LL_ERRS() << "can't read source vertex in vertex remap data" << LL_ENDL;
                                                break;
                                        }
                                        if (fread(&remapDst, sizeof(S32), 1, fp) != 1)
                                        {
                                                LL_ERRS() << "can't read destination vertex in vertex remap data" << LL_ENDL;
                                                break;
                                        }
                                        llendianswizzle(&remapSrc, sizeof(S32), 1);
                                        llendianswizzle(&remapDst, sizeof(S32), 1);

                                        mSharedVerts[remapSrc] = remapDst;
                                }
                        }
                }

                status = TRUE;
        }
        else
        {
                LL_ERRS() << "invalid mesh file header: " << fileName << LL_ENDL;
                status = FALSE;
        }

        if (0 == mNumJointNames)
        {
                allocateJointNames(1);
        }

        fclose( fp );

        return status;
}
LLSD LLObjectBackup::primsToLLSD(LLViewerObject::child_list_t child_list,
								 bool is_attachment)
{
	LLViewerObject* object;
	LLSD llsd;
	char localid[16];
	LLUUID t_id;

	for (LLViewerObject::child_list_t::iterator i = child_list.begin();
		 i != child_list.end(); ++i)
	{
		object = (*i);
		LLUUID id = object->getID();

		LL_INFOS() << "Exporting prim " << object->getID().asString() << LL_ENDL;

		// Create an LLSD object that represents this prim. It will be injected
		// in to the overall LLSD tree structure
		LLSD prim_llsd;

		if (!object->isRoot())
		{
			// Parent id
			snprintf(localid, sizeof(localid), "%u",
					 object->getSubParent()->getLocalID());
			prim_llsd["parent"] = localid;
		}

		// Name and description
		LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->findNode(object);
		if (node)
		{
			prim_llsd["name"] = node->mName;
			prim_llsd["description"] = node->mDescription;
		}

		// Transforms
		if (is_attachment)
		{
			prim_llsd["position"] = object->getPositionEdit().getValue();
			prim_llsd["rotation"] = ll_sd_from_quaternion(object->getRotationEdit());
		}
		else
		{
			prim_llsd["position"] = object->getPosition().getValue();
			prim_llsd["rotation"] = ll_sd_from_quaternion(object->getRotation());
		}
		prim_llsd["scale"] = object->getScale().getValue();

		// Flags
		prim_llsd["phantom"] = object->flagPhantom();		// legacy
		prim_llsd["physical"] = object->flagUsePhysics();	// legacy
		prim_llsd["flags"] = (S32)object->getFlags();		// new way

		// Extra physics flags
		if (mGotExtraPhysics)
		{
			LLSD& physics = prim_llsd["ExtraPhysics"];
			physics["PhysicsShapeType"] = object->getPhysicsShapeType();
			physics["Gravity"] = object->getPhysicsGravity();
			physics["Friction"] = object->getPhysicsFriction();
			physics["Density"] = object->getPhysicsDensity();
			physics["Restitution"] = object->getPhysicsRestitution();
		}

		// Click action
		if (S32 action = object->getClickAction()) // Non-zero
			prim_llsd["clickaction"] = action;

		// Prim material
		prim_llsd["material"] = object->getMaterial();

		// Volume params
		LLVolumeParams params = object->getVolume()->getParams();
		prim_llsd["volume"] = params.asLLSD();

		// Extra paramsb6fab961-af18-77f8-cf08-f021377a7244

		if (object->isFlexible())
		{
			// Flexible
			LLFlexibleObjectData* flex;
			flex = (LLFlexibleObjectData*)object->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE);
			prim_llsd["flexible"] = flex->asLLSD();
		}

		if (object->getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT))
		{
			// Light
			LLLightParams* light;
			light = (LLLightParams*)object->getParameterEntry(LLNetworkData::PARAMS_LIGHT);
			prim_llsd["light"] = light->asLLSD();
		}
		if (object->getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE))
		{
			// Light image
			LLLightImageParams* light_param;
			light_param = (LLLightImageParams*)object->getParameterEntry(LLNetworkData::PARAMS_LIGHT_IMAGE);
			t_id = validateTextureID(light_param->getLightTexture());
			if (mTexturesList.count(t_id) == 0)
			{
				LL_INFOS() << "Found a light texture, adding to list " << t_id
						<< LL_ENDL;
				mTexturesList.insert(t_id);
			}
			prim_llsd["light_texture"] = light_param->asLLSD();
		}

		if (object->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT))
		{
			// Sculpt
			LLSculptParams* sculpt;
			sculpt = (LLSculptParams*)object->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
			prim_llsd["sculpt"] = sculpt->asLLSD();
			if ((sculpt->getSculptType() & LL_SCULPT_TYPE_MASK) != LL_SCULPT_TYPE_MESH)
			{
				LLUUID sculpt_texture = sculpt->getSculptTexture();
				if (sculpt_texture == validateTextureID(sculpt_texture))
				{
					if (mTexturesList.count(sculpt_texture) == 0)
					{
						LL_INFOS() << "Found a sculpt texture, adding to list "
								<< sculpt_texture << LL_ENDL;
						mTexturesList.insert(sculpt_texture);
					}
				}
				else
				{
					LL_WARNS() << "Incorrect permission to export a sculpt texture."
							<< LL_ENDL;
					mExportState = EXPORT_FAILED;
				}
			}
		}

		// Textures and materials
		LLSD te_llsd;
		LLSD this_te_llsd;
		LLSD te_mat_llsd;
		LLSD this_te_mat_llsd;
		bool has_materials = false;
		for (U8 i = 0, count = object->getNumTEs(); i < count; ++i)
		{
			LLTextureEntry* te = object->getTE(i);
			if (!te) continue;	// Paranoia

			// Normal texture/diffuse map
			t_id = validateTextureID(te->getID());
			this_te_llsd = te->asLLSD();
			this_te_llsd["imageid"] = t_id;
			te_llsd.append(this_te_llsd);
			// Do not export non-existent default textures
			if (t_id != LL_TEXTURE_BLANK && t_id != LL_TEXTURE_INVISIBLE)
			{
				if (mTexturesList.count(t_id) == 0)
				{
					mTexturesList.insert(t_id);
				}
			}

			// Materials
			LLMaterial* mat = te->getMaterialParams().get();
			if (mat)
			{
				has_materials = true;
				this_te_mat_llsd = mat->asLLSD();

				t_id = validateTextureID(mat->getNormalID());
				this_te_mat_llsd["NormMap"] = t_id;
				if (mTexturesList.count(t_id) == 0)
				{
					mTexturesList.insert(t_id);
				}

				t_id = validateTextureID(mat->getSpecularID());
				this_te_mat_llsd["SpecMap"] = t_id;
				if (mTexturesList.count(t_id) == 0)
				{
					mTexturesList.insert(t_id);
				}

				te_mat_llsd.append(this_te_mat_llsd);
			}
		}
		prim_llsd["textures"] = te_llsd;
		if (has_materials)
		{
			prim_llsd["materials"] = te_mat_llsd;
		}

		// The keys in the primitive maps do not have to be localids, they can
		// be any string. We simply use localids because they are a unique
		// identifier
		snprintf(localid, sizeof(localid), "%u", object->getLocalID());
		llsd[(const char*)localid] = prim_llsd;
	}

	updateExportNumbers();

	return llsd;
}
void LLObjectBackup::exportNextTexture()
{
	LLUUID id;
	textures_set_t::iterator iter = mTexturesList.begin();
	while (true)
	{
		if (mTexturesList.empty())
		{
			mCheckNextTexture = true;
			LL_INFOS() << "Finished exporting textures." << LL_ENDL;
			return;
		}
		if (iter == mTexturesList.end())
		{
			// Not yet ready, wait and re-check at next idle callback...
			mCheckNextTexture = true;
			return;
		}

		id = *iter++;
		if (id.isNull())
		{
			// NULL texture id: just remove and ignore.
			mTexturesList.erase(id);
			LL_DEBUGS("ObjectBackup") << "Null texture UUID found, ignoring."
									  << LL_ENDL;
			continue;
		}

		LLViewerTexture* imagep = LLViewerTextureManager::findTexture(id);
		if (imagep)
		{
			if (imagep->getDiscardLevel() > 0)
			{
				// Boost texture loading
				imagep->setBoostLevel(LLGLTexture::BOOST_PREVIEW);
				LL_DEBUGS("ObjectBackup") << "Boosting texture: " << id
										  << LL_ENDL;
				LLViewerFetchedTexture* tex;
				tex = LLViewerTextureManager::staticCastToFetchedTexture(imagep);
				if (tex && tex->getDesiredDiscardLevel() > 0)
				{
					// Set min discard level to 0
					tex->setMinDiscardLevel(0);
					LL_DEBUGS("ObjectBackup") << "Min discard level set to 0 for texture: "
											  << id << LL_ENDL;
				}
			}
			else
			{
				// Texture is ready !
				break;
			}
		}
		else
		{
			LL_WARNS() << "We *DON'T* have the texture " << id << LL_ENDL;
			mNonExportedTextures |= TEXTURE_MISSING;
			mTexturesList.erase(id);
		}
	}

	mTexturesList.erase(id);

	LL_INFOS() << "Requesting texture " << id << " from cache." << LL_ENDL;
	LLImageJ2C* mFormattedImage = new LLImageJ2C;
	BackupCacheReadResponder* responder;
	responder = new BackupCacheReadResponder(id, mFormattedImage);
	LLAppViewer::getTextureCache()->readFromCache(id,
												  LLWorkerThread::PRIORITY_HIGH,
												  0, 999999, responder);
}
void FSFloaterVoiceControls::updateSession()
{
	LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel();
	if (voice_channel)
	{
		LL_DEBUGS("Voice") << "Current voice channel: " << voice_channel->getSessionID() << LL_ENDL;

		if (mSpeakerManager && voice_channel->getSessionID() == mSpeakerManager->getSessionID())
		{
			LL_DEBUGS("Voice") << "Speaker manager is already set for session: " << voice_channel->getSessionID() << LL_ENDL;
			return;
		}
		else
		{
			mSpeakerManager = NULL;
		}
	}

	const LLUUID& session_id = voice_channel ? voice_channel->getSessionID() : LLUUID::null;

	LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id);
	if (im_session)
	{
		mSpeakerManager = LLIMModel::getInstance()->getSpeakerManager(session_id);
		switch (im_session->mType)
		{
		case IM_NOTHING_SPECIAL:
		case IM_SESSION_P2P_INVITE:
			mVoiceType = VC_PEER_TO_PEER;

			if (!im_session->mOtherParticipantIsAvatar)
			{
				mVoiceType = VC_PEER_TO_PEER_AVALINE;
			}
			break;
		case IM_SESSION_CONFERENCE_START:
		case IM_SESSION_GROUP_START:
		case IM_SESSION_INVITE:
			if (gAgent.isInGroup(session_id))
			{
				mVoiceType = VC_GROUP_CHAT;
			}
			else
			{
				mVoiceType = VC_AD_HOC_CHAT;				
			}
			break;
		default:
			LL_WARNS() << "Failed to determine voice call IM type" << LL_ENDL;
			mVoiceType = VC_GROUP_CHAT;
			break;
		}
	}

	if (NULL == mSpeakerManager)
	{
		// By default show nearby chat participants
		mSpeakerManager = LLLocalSpeakerMgr::getInstance();
		LL_DEBUGS("Voice") << "Set DEFAULT speaker manager" << LL_ENDL;
		mVoiceType = VC_LOCAL_CHAT;
	}

	updateTitle();

	// Hide "Leave Call" button for nearby chat
	bool is_local_chat = mVoiceType == VC_LOCAL_CHAT;
	getChildView("leave_call_btn_panel")->setVisible( !is_local_chat);

	refreshParticipantList();
	updateAgentModeratorState();

	// Show floater for voice calls & only in CONNECTED to voice channel state
	if (!is_local_chat &&
	    voice_channel &&
	    LLVoiceChannel::STATE_CONNECTED == voice_channel->getState())
	{
		// <FS:Ansariel> [FS communication UI]
		//LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
		FSFloaterIM* im_floater = FSFloaterIM::findInstance(session_id);
		// </FS:Ansariel> [FS communication UI]
		bool show_me = !(im_floater && im_floater->getVisible());
		if (show_me) 
		{
			setVisible(true);
		}
	}

// [RLVa:KB] - Checked: 2010-06-05 (RLVa-1.2.0d) | Added: RLVa-1.2.0d
	mAvatarList->setRlvCheckShowNames(is_local_chat);
// [/RLVa:KB]
}
// This is fired when the update packet is processed so we know the prim
// settings have stuck
//static
void LLObjectBackup::primUpdate(LLViewerObject* object)
{
	LLObjectBackup* self = findInstance();
	if (!object || !self || !self->mRunning ||
		object->mID != self->mExpectingUpdate)
	{
			return;
	}

	++self->mCurPrim;
	self->updateImportNumbers();
	++self->mPrimImportIter;

	self->mExpectingUpdate.setNull();

	if (self->mPrimImportIter == self->mThisGroup.endMap())
	{
		LL_INFOS() << "Trying to link..." << LL_ENDL;

		if (self->mToSelect.size() > 1)
		{
			std::reverse(self->mToSelect.begin(), self->mToSelect.end());
			// Now link
			LLSelectMgr::getInstance()->deselectAll();
			LLSelectMgr::getInstance()->selectObjectAndFamily(self->mToSelect, true);
			LLSelectMgr::getInstance()->sendLink();
			LLViewerObject* root = self->mToSelect.back();
			root->setRotation(self->mRootRot);
		}

		++self->mCurObject;
		++self->mGroupPrimImportIter;
		if (self->mGroupPrimImportIter != self->mLLSD["data"].endArray())
		{
			self->importNextObject();
			return;
		}

		self->mRunning = false;
		self->destroy();
		return;
	}

	LLSD prim_llsd = self->mThisGroup[self->mPrimImportIter->first];

	if (self->mToSelect.empty())
	{
		LL_WARNS() << "error: ran out of objects to mod." << LL_ENDL;
		self->mRunning = false;
		self->destroy();
		return;
	}

	if (self->mPrimImportIter != self->mThisGroup.endMap())
	{
		//rezAgentOffset(LLVector3(1.0, 0.0, 0.0));
		LLSD prim_llsd =self-> mThisGroup[self->mPrimImportIter->first];
		++self->mProcessIter;
		self->xmlToPrim(prim_llsd, *(self->mProcessIter));
	}
}
void LLPluginProcessParent::idle(void)
{
	bool idle_again;

	do
	{
		// process queued messages
		mIncomingQueueMutex.lock();
		while(!mIncomingQueue.empty())
		{
			LLPluginMessage message = mIncomingQueue.front();
			mIncomingQueue.pop();
			mIncomingQueueMutex.unlock();
				
			receiveMessage(message);
			
			mIncomingQueueMutex.lock();
		}

		mIncomingQueueMutex.unlock();
		
		// Give time to network processing
		if(mMessagePipe)
		{
			// Drain any queued outgoing messages
			mMessagePipe->pumpOutput();
			
			// Only do input processing here if this instance isn't in a pollset.
			if(!mPolledInput)
			{
				mMessagePipe->pumpInput();
			}
		}
		
		if(mState <= STATE_RUNNING)
		{
			if(APR_STATUS_IS_EOF(mSocketError))
			{
				// Plugin socket was closed.  This covers both normal plugin termination and plugin crashes.
				errorState();
			}
			else if(mSocketError != APR_SUCCESS)
			{
				// The socket is in an error state -- the plugin is gone.
				LL_WARNS("Plugin") << "Socket hit an error state (" << mSocketError << ")" << LL_ENDL;
				errorState();
			}
		}	
		
		// If a state needs to go directly to another state (as a performance enhancement), it can set idle_again to true after calling setState().
		// USE THIS CAREFULLY, since it can starve other code.  Specifically make sure there's no way to get into a closed cycle and never return.
		// When in doubt, don't do it.
		idle_again = false;
		switch(mState)
		{
			case STATE_UNINITIALIZED:
			break;

			case STATE_INITIALIZED:
			{
				apr_status_t status = APR_SUCCESS;
				apr_sockaddr_t* addr = NULL;
				mListenSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP);
				mBoundPort = 0;
				
				// This code is based on parts of LLSocket::create() in lliosocket.cpp.
				
				status = apr_sockaddr_info_get(
					&addr,
					"127.0.0.1",
					APR_INET,
					mPortToBind,	// port 0 = ephemeral ("find me a port")
					0,
					gAPRPoolp);
					
				if(ll_apr_warn_status(status))
				{
					killSockets();
					errorState();
					break;
				}

				// This allows us to reuse the address on quick down/up. This is unlikely to create problems.
				ll_apr_warn_status(apr_socket_opt_set(mListenSocket->getSocket(), APR_SO_REUSEADDR, 1));
				
				status = apr_socket_bind(mListenSocket->getSocket(), addr);
				if(ll_apr_warn_status(status))
				{
					killSockets();
					errorState();
					break;
				}

				// Get the actual port the socket was bound to
				{
					apr_sockaddr_t* bound_addr = NULL;
					if(ll_apr_warn_status(apr_socket_addr_get(&bound_addr, APR_LOCAL, mListenSocket->getSocket())))
					{
						killSockets();
						errorState();
						break;
					}
					mBoundPort = bound_addr->port;	

					if(mBoundPort == 0)
					{
						LL_WARNS("Plugin") << "Bound port number unknown, bailing out." << LL_ENDL;
						
						killSockets();

						// <ND> FIRE-3877;  Some drivers, eg bigfoot. Refuse to tell us which port is used when the socket is bound on port 0 (= choose a free port).
						// If not out of retry attempts, choose a random port between 5500 - 60000 and try again.
						if( mBindRetries > 10 ) //In theory we could have bad luck and randomly draft already used ports each try. In practice we already deal with a buggy driver anyway. So just fail instead hogging resources in a loop.
							errorState();
						else
						{
							++mBindRetries;
							mPortToBind = ll_rand(55000)+5000; // Ports < 4096 are reserved for root (at least on BSD like systems), do never touch them.
							setState( STATE_INITIALIZED );
							idle_again = true; // Just try a new loop to bind the socket
						}
						// </ND>

						break;
					}
				}
				
				LL_DEBUGS("Plugin") << "Bound tcp socket to port: " << addr->port << LL_ENDL;

				// Make the listen socket non-blocking
				status = apr_socket_opt_set(mListenSocket->getSocket(), APR_SO_NONBLOCK, 1);
				if(ll_apr_warn_status(status))
				{
					killSockets();
					errorState();
					break;
				}

				apr_socket_timeout_set(mListenSocket->getSocket(), 0);
				if(ll_apr_warn_status(status))
				{
					killSockets();
					errorState();
					break;
				}
				
				// If it's a stream based socket, we need to tell the OS
				// to keep a queue of incoming connections for ACCEPT.
				status = apr_socket_listen(
					mListenSocket->getSocket(),
					10); // FIXME: Magic number for queue size
					
				if(ll_apr_warn_status(status))
				{
					killSockets();
					errorState();
					break;
				}
				
				// If we got here, we're listening.
				setState(STATE_LISTENING);
			}
			break;
			
			case STATE_LISTENING:
			{
				// Launch the plugin process.
				
				// Only argument to the launcher is the port number we're listening on
				mProcessParams.args.add(stringize(mBoundPort));
				if (! (mProcess = LLProcess::create(mProcessParams)))
				{
					errorState();
				}
				else
				{
					if(mDebug)
					{
						#if LL_DARWIN
						// If we're set to debug, start up a gdb instance in a new terminal window and have it attach to the plugin process and continue.
						
						// The command we're constructing would look like this on the command line:
						// osascript -e 'tell application "Terminal"' -e 'set win to do script "gdb -pid 12345"' -e 'do script "continue" in win' -e 'end tell'

						LLProcess::Params params;
						params.executable = "/usr/bin/osascript";
						params.args.add("-e");
						params.args.add("tell application \"Terminal\"");
						params.args.add("-e");
						params.args.add(STRINGIZE("set win to do script \"gdb -pid "
												  << mProcess->getProcessID() << "\""));
						params.args.add("-e");
						params.args.add("do script \"continue\" in win");
						params.args.add("-e");
						params.args.add("end tell");
						mDebugger = LLProcess::create(params);

						#endif
					}
					
					// This will allow us to time out if the process never starts.
					mHeartbeat.start();
					mHeartbeat.setTimerExpirySec(mPluginLaunchTimeout);
					setState(STATE_LAUNCHED);
				}
			}
			break;

			case STATE_LAUNCHED:
				// waiting for the plugin to connect
				if(pluginLockedUpOrQuit())
				{
					errorState();
				}
				else
				{
					// Check for the incoming connection.
					if(accept())
					{
						// Stop listening on the server port
						mListenSocket.reset();
						setState(STATE_CONNECTED);
					}
				}
			break;
			
			case STATE_CONNECTED:
				// waiting for hello message from the plugin

				if(pluginLockedUpOrQuit())
				{
					errorState();
				}
			break;

			case STATE_HELLO:
				LL_DEBUGS("Plugin") << "received hello message" << LL_ENDL;
				
				// Send the message to load the plugin
				{
					LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "load_plugin");
					message.setValue("file", mPluginFile);
					message.setValue("dir", mPluginDir);
					sendMessage(message);
				}

				setState(STATE_LOADING);
			break;
			
			case STATE_LOADING:
				// The load_plugin_response message will kick us from here into STATE_RUNNING
				if(pluginLockedUpOrQuit())
				{
					errorState();
				}
			break;
			
			case STATE_RUNNING:
				if(pluginLockedUpOrQuit())
				{
					errorState();
				}
			break;
			
			case STATE_EXITING:
				if (! LLProcess::isRunning(mProcess))
				{
					setState(STATE_CLEANUP);
				}
				else if(pluginLockedUp())
				{
					LL_WARNS("Plugin") << "timeout in exiting state, bailing out" << LL_ENDL;
					errorState();
				}
			break;

			case STATE_LAUNCH_FAILURE:
				if(mOwner != NULL)
				{
					mOwner->pluginLaunchFailed();
				}
				setState(STATE_CLEANUP);
			break;

			case STATE_ERROR:
				if(mOwner != NULL)
				{
					mOwner->pluginDied();
				}
				setState(STATE_CLEANUP);
			break;
			
			case STATE_CLEANUP:
				LLProcess::kill(mProcess);
				killSockets();
				setState(STATE_DONE);
			break;
			
			
			case STATE_DONE:
				// just sit here.
			break;
			
		}
	
	} while (idle_again);
}
void LLPluginProcessParent::poll(F64 timeout)
{
	if(sPollsetNeedsRebuild || !sUseReadThread)
	{
		sPollsetNeedsRebuild = false;
		updatePollset();
	}
	
	if(sPollSet)
	{
		apr_status_t status;
		apr_int32_t count;
		const apr_pollfd_t *descriptors;
		status = apr_pollset_poll(sPollSet, (apr_interval_time_t)(timeout * 1000000), &count, &descriptors);
		if(status == APR_SUCCESS)
		{
			// One or more of the descriptors signalled.  Call them.
			for(int i = 0; i < count; i++)
			{
				LLPluginProcessParent *self = (LLPluginProcessParent *)(descriptors[i].client_data);
				// NOTE: the descriptor returned here is actually a COPY of the original (even though we create the pollset with APR_POLLSET_NOCOPY).
				// This means that even if the parent has set its mPollFD.client_data to NULL, the old pointer may still there in this descriptor.
				// It's even possible that the old pointer no longer points to a valid LLPluginProcessParent.
				// This means that we can't safely dereference the 'self' pointer here without some extra steps...
				if(self)
				{
					// Make sure this pointer is still in the instances list
					bool valid = false;
					{
						LLMutexLock lock(sInstancesMutex);
						for(std::list<LLPluginProcessParent*>::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter)
						{
							if(*iter == self)
							{
								// Lock the instance's mutex before unlocking the global mutex.  
								// This avoids a possible race condition where the instance gets deleted between this check and the servicePoll() call.
								self->mIncomingQueueMutex.lock();
								valid = true;
								break;
							}
						}
					}
					
					if(valid)
					{
						// The instance is still valid.
						// Pull incoming messages off the socket
						self->servicePoll();
						self->mIncomingQueueMutex.unlock();
					}
					else
					{
						LL_DEBUGS("PluginPoll") << "detected deleted instance " << self << LL_ENDL;
					}

				}
			}
		}
		else if(APR_STATUS_IS_TIMEUP(status))
		{
			// timed out with no incoming data.  Just return.
		}
		else if(status == EBADF)
		{
			// This happens when one of the file descriptors in the pollset is destroyed, which happens whenever a plugin's socket is closed.
			// The pollset has been or will be recreated, so just return.
			LL_DEBUGS("PluginPoll") << "apr_pollset_poll returned EBADF" << LL_ENDL;
		}
		else if(status != APR_SUCCESS)
		{
			LL_WARNS("PluginPoll") << "apr_pollset_poll failed with status " << status << LL_ENDL;
		}
	}
}
/* virtual */
void LLPluginProcessChild::receivePluginMessage(const std::string &message)
{
	LL_DEBUGS("PluginChild") << "Received from plugin: " << message << LL_ENDL;
	
	if(mBlockingRequest)
	{
		// 
		LL_ERRS("Plugin") << "Can't send a message while already waiting on a blocking request -- aborting!" << LL_ENDL;
	}
	
	// Incoming message from the plugin instance
	bool passMessage = true;

	// FIXME: how should we handle queueing here?
	
	// Intercept certain base messages (responses to ones sent by this class)
	{
		// Decode this message
		LLPluginMessage parsed;
		parsed.parse(message);
		
		if(parsed.hasValue("blocking_request"))
		{
			mBlockingRequest = true;
		}

		std::string message_class = parsed.getClass();
		if(message_class == "base")
		{
			std::string message_name = parsed.getName();
			if(message_name == "init_response")
			{
				// The plugin has finished initializing.
				setState(STATE_RUNNING);

				// Don't pass this message up to the parent
				passMessage = false;
				
				LLPluginMessage new_message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "load_plugin_response");
				LLSD versions = parsed.getValueLLSD("versions");
				new_message.setValueLLSD("versions", versions);
				
				if(parsed.hasValue("plugin_version"))
				{
					std::string plugin_version = parsed.getValue("plugin_version");
					new_message.setValueLLSD("plugin_version", plugin_version);
				}

				// Let the parent know it's loaded and initialized.
				sendMessageToParent(new_message);
			}
			else if(message_name == "shm_remove_response")
			{
				// Don't pass this message up to the parent
				passMessage = false;

				std::string name = parsed.getValue("name");
				sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);				
				if(iter != mSharedMemoryRegions.end())
				{
					// detach the shared memory region
					iter->second->detach();
					
					// and remove it from our map
					mSharedMemoryRegions.erase(iter);
					
					// Finally, send the response to the parent.
					LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_remove_response");
					message.setValue("name", name);
					sendMessageToParent(message);
				}
				else
				{
					LL_WARNS("PluginChild") << "shm_remove_response for unknown memory segment!" << LL_ENDL;
				}
			}
			else if (message_name == "cleanup_reply")
			{
				LL_DEBUGS("PluginChild") << "cleanup_reply message received" << LL_ENDL;
				passMessage = false;

				setState(STATE_UNLOADING_CLEANED);

				// Clean up this and tell the parent
				LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "cleanup_reply");
				sendMessageToParent(message);
			}
		}
	}

	if(passMessage)
	{
		LL_DEBUGS("PluginChild") << "Passing through to parent: " << message << LL_ENDL;
		writeMessageRaw(message);
	}
	
	while(mBlockingRequest)
	{
		// The plugin wants to block and wait for a response to this message.
		sleep(mSleepTime);	// this will pump the message pipe and process messages

		if(mBlockingResponseReceived || mSocketError != APR_SUCCESS || (mMessagePipe == NULL))
		{
			// Response has been received, or we've hit an error state.  Stop waiting.
			mBlockingRequest = false;
			mBlockingResponseReceived = false;
		}
	}
}
LLSD LLUserAuth::parseValues(UserAuthcode &auth_code, const std::string& key_pfx, XMLRPC_VALUE param)
{
	auth_code = E_OK;
	LLSD responses;
	for(XMLRPC_VALUE current = XMLRPC_VectorRewind(param); current;
		current = XMLRPC_VectorNext(param))
	{
		std::string key(XMLRPC_GetValueID(current));
		LL_DEBUGS() << "key: " << key_pfx << key << LL_ENDL;
		XMLRPC_VALUE_TYPE_EASY type = XMLRPC_GetValueTypeEasy(current);
		if(xmlrpc_type_string == type)
		{
			LLSD::String val(XMLRPC_GetValueString(current));
			LL_DEBUGS() << "val: " << val << LL_ENDL;
			responses.insert(key,val);
		}
		else if(xmlrpc_type_int == type)
		{
			LLSD::Integer val(XMLRPC_GetValueInt(current));
			LL_DEBUGS() << "val: " << val << LL_ENDL;
			responses.insert(key,val);
		}
		else if (xmlrpc_type_double == type)
        {
			LLSD::Real val(XMLRPC_GetValueDouble(current));
            LL_DEBUGS() << "val: " << val << LL_ENDL;
			responses.insert(key,val);
		}
		else if(xmlrpc_type_array == type)
		{
			// We expect this to be an array of submaps. Walk the array,
			// recursively parsing each submap and collecting them.
			LLSD array;
			int i = 0;          // for descriptive purposes
			for (XMLRPC_VALUE row = XMLRPC_VectorRewind(current); row;
				row = XMLRPC_VectorNext(current), ++i)
			{
				// Recursive call. For the lower-level key_pfx, if 'key'
				// is "foo", pass "foo[0]:", then "foo[1]:", etc. In the
				// nested call, a subkey "bar" will then be logged as
				// "foo[0]:bar", and so forth.
				// Parse the scalar subkey/value pairs from this array
				// entry into a temp submap. Collect such submaps in 'array'.
				std::string key_prefix = key_pfx;
				array.append(parseValues(auth_code,
									STRINGIZE(key_pfx << key << '[' << i << "]:"),
									row));
			}
			// Having collected an 'array' of 'submap's, insert that whole
			// 'array' as the value of this 'key'.
			responses.insert(key, array);
		}
		else if (xmlrpc_type_struct == type)
    	{
    		LLSD submap = parseValues(auth_code,
            						STRINGIZE(key_pfx << key << ':'),
            						current);
            responses.insert(key, submap);
        }
        else
        {
        	// whoops - unrecognized type
            LL_WARNS() << "Unhandled xmlrpc type " << type << " for key "
                                        << key_pfx << key << LL_ENDL;
            responses.insert(key, STRINGIZE("<bad XMLRPC type " << type << '>'));
            auth_code = E_UNHANDLED_ERROR;
        }
    }
    return responses;
}
//-----------------------------------------------------------------------------
// setPointAt()
// called by agent logic to set look at behavior locally, and propagate to sim
//-----------------------------------------------------------------------------
BOOL LLHUDEffectPointAt::setPointAt(EPointAtType target_type, LLViewerObject *object, LLVector3 position)
{
	if (!mSourceObject)
	{
		return FALSE;
	}
	
	if (target_type >= POINTAT_NUM_TARGETS)
	{
		LL_WARNS() << "Bad target_type " << (int)target_type << " - ignoring." << LL_ENDL;
		return FALSE;
	}

	// must be same or higher priority than existing effect
	if (POINTAT_PRIORITIES[target_type] < POINTAT_PRIORITIES[mTargetType])
	{
		return FALSE;
	}

	F32 current_time  = mTimer.getElapsedTimeF32();
	
	// type of pointat behavior or target object has changed
	BOOL targetTypeChanged = (target_type != mTargetType) ||
		(object != mTargetObject);

	BOOL targetPosChanged = (dist_vec_squared(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE_SQUARED) && 
		((current_time - mLastSendTime) > (1.f / MAX_SENDS_PER_SEC));

	if (targetTypeChanged || targetPosChanged)
	{
		mLastSentOffsetGlobal = position;
		setDuration(POINTAT_TIMEOUTS[target_type]);
		setNeedsSendToSim(TRUE);
//		LL_INFOS() << "Sending pointat data" << LL_ENDL;
	}

	if (target_type == POINTAT_TARGET_CLEAR)
	{
		clearPointAtTarget();
	}
	else
	{
		mTargetType = target_type;
		mTargetObject = object;
		if (object)
		{
			mTargetOffsetGlobal.setVec(position);
		}
		else
		{
			mTargetOffsetGlobal = gAgent.getPosGlobalFromAgent(position);
		}

		mKillTime = mTimer.getElapsedTimeF32() + mDuration;

		//set up requisite animation data
		update();
	}

	return TRUE;
}
void LLPluginProcessChild::receiveMessageRaw(const std::string &message)
{
	// Incoming message from the TCP Socket

	LL_DEBUGS("PluginChild") << "Received from parent: " << message << LL_ENDL;

	// Decode this message
	LLPluginMessage parsed;
	parsed.parse(message);

	if(mBlockingRequest)
	{
		// We're blocking the plugin waiting for a response.

		if(parsed.hasValue("blocking_response"))
		{
			// This is the message we've been waiting for -- fall through and send it immediately. 
			mBlockingResponseReceived = true;
		}
		else
		{
			// Still waiting.  Queue this message and don't process it yet.
			mMessageQueue.push(message);
			return;
		}
	}
	
	bool passMessage = true;
	
	// FIXME: how should we handle queueing here?
	
	{
		std::string message_class = parsed.getClass();
		if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL)
		{
			passMessage = false;
			
			std::string message_name = parsed.getName();
			if(message_name == "load_plugin")
			{
				mPluginFile = parsed.getValue("file");
				mPluginDir = parsed.getValue("dir");
			}
			else if(message_name == "shm_add")
			{
				std::string name = parsed.getValue("name");
				size_t size = (size_t)parsed.getValueS32("size");
				
				sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
				if(iter != mSharedMemoryRegions.end())
				{
					// Need to remove the old region first
					LL_WARNS("PluginChild") << "Adding a duplicate shared memory segment!" << LL_ENDL;
				}
				else
				{
					// This is a new region
					LLPluginSharedMemory *region = new LLPluginSharedMemory;
					if(region->attach(name, size))
					{
						mSharedMemoryRegions.insert(sharedMemoryRegionsType::value_type(name, region));
						
						std::stringstream addr;
						addr << region->getMappedAddress();
						
						// Send the add notification to the plugin
						LLPluginMessage message("base", "shm_added");
						message.setValue("name", name);
						message.setValueS32("size", (S32)size);
						message.setValuePointer("address", region->getMappedAddress());
						sendMessageToPlugin(message);
						
						// and send the response to the parent
						message.setMessage(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "shm_add_response");
						message.setValue("name", name);
						sendMessageToParent(message);
					}
					else
					{
						LL_WARNS("PluginChild") << "Couldn't create a shared memory segment!" << LL_ENDL;
						delete region;
					}
				}
				
			}
			else if(message_name == "shm_remove")
			{
				std::string name = parsed.getValue("name");
				sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
				if(iter != mSharedMemoryRegions.end())
				{
					// forward the remove request to the plugin -- its response will trigger us to detach the segment.
					LLPluginMessage message("base", "shm_remove");
					message.setValue("name", name);
					sendMessageToPlugin(message);
				}
				else
				{
					LL_WARNS("PluginChild") << "shm_remove for unknown memory segment!" << LL_ENDL;
				}
			}
			else if(message_name == "sleep_time")
			{
				mSleepTime = llmax(parsed.getValueReal("time"), 1.0 / 100.0); // clamp to maximum of 100Hz
			}
     		#if LL_WINDOWS
			else if(message_name == "show_console")
			{
				createConsole();
			}
			#endif
			else if(message_name == "crash")
			{
				// Crash the plugin
				LL_ERRS("PluginChild") << "Plugin crash requested." << LL_ENDL;
			}
			else if(message_name == "hang")
			{
				// Hang the plugin
				LL_WARNS("PluginChild") << "Plugin hang requested." << LL_ENDL;
				while(1)
				{
					// wheeeeeeeee......
				}
			}
			else
			{
				LL_WARNS("PluginChild") << "Unknown internal message from parent: " << message_name << LL_ENDL;
			}
		}
	}
	
	if(passMessage && mInstance != NULL)
	{
		LLTimer elapsed;

		mInstance->sendMessage(message);

		mCPUElapsed += elapsed.getElapsedTimeF64();
	}
}
/*virtual*/
void LLClassifiedStatsResponder::httpFailure()
{
	LL_WARNS() << dumpResponse() << LL_ENDL;
}
Beispiel #13
0
BOOL LLDXHardware::getInfo(BOOL vram_only)
{
	LLTimer hw_timer;
	BOOL ok = FALSE;
    HRESULT       hr;

    CoInitialize(NULL);

    IDxDiagProvider *dx_diag_providerp = NULL;
    IDxDiagContainer *dx_diag_rootp = NULL;
	IDxDiagContainer *devices_containerp = NULL;
	// IDxDiagContainer *system_device_containerp= NULL;
	IDxDiagContainer *device_containerp = NULL;
	IDxDiagContainer *file_containerp = NULL;
	IDxDiagContainer *driver_containerp = NULL;

    // CoCreate a IDxDiagProvider*
	LL_DEBUGS("AppInit") << "CoCreateInstance IID_IDxDiagProvider" << LL_ENDL;
    hr = CoCreateInstance(CLSID_DxDiagProvider,
                          NULL,
                          CLSCTX_INPROC_SERVER,
                          IID_IDxDiagProvider,
                          (LPVOID*) &dx_diag_providerp);

	if (FAILED(hr))
	{
		LL_WARNS("AppInit") << "No DXDiag provider found!  DirectX 9 not installed!" << LL_ENDL;
		gWriteDebug("No DXDiag provider found!  DirectX 9 not installed!\n");
		goto LCleanup;
	}
    if (SUCCEEDED(hr)) // if FAILED(hr) then dx9 is not installed
    {
        // Fill out a DXDIAG_INIT_PARAMS struct and pass it to IDxDiagContainer::Initialize
        // Passing in TRUE for bAllowWHQLChecks, allows dxdiag to check if drivers are 
        // digital signed as logo'd by WHQL which may connect via internet to update 
        // WHQL certificates.    
        DXDIAG_INIT_PARAMS dx_diag_init_params;
        ZeroMemory(&dx_diag_init_params, sizeof(DXDIAG_INIT_PARAMS));

        dx_diag_init_params.dwSize                  = sizeof(DXDIAG_INIT_PARAMS);
        dx_diag_init_params.dwDxDiagHeaderVersion   = DXDIAG_DX9_SDK_VERSION;
        dx_diag_init_params.bAllowWHQLChecks        = TRUE;
        dx_diag_init_params.pReserved               = NULL;

		LL_DEBUGS("AppInit") << "dx_diag_providerp->Initialize" << LL_ENDL;
        hr = dx_diag_providerp->Initialize(&dx_diag_init_params);
        if(FAILED(hr))
		{
            goto LCleanup;
		}

		LL_DEBUGS("AppInit") << "dx_diag_providerp->GetRootContainer" << LL_ENDL;
        hr = dx_diag_providerp->GetRootContainer( &dx_diag_rootp );
        if(FAILED(hr) || !dx_diag_rootp)
		{
            goto LCleanup;
		}

		HRESULT hr;

		// Get display driver information
		LL_DEBUGS("AppInit") << "dx_diag_rootp->GetChildContainer" << LL_ENDL;
		hr = dx_diag_rootp->GetChildContainer(L"DxDiag_DisplayDevices", &devices_containerp);
		if(FAILED(hr) || !devices_containerp)
		{
            goto LCleanup;
		}

		// Get device 0
		LL_DEBUGS("AppInit") << "devices_containerp->GetChildContainer" << LL_ENDL;
		hr = devices_containerp->GetChildContainer(L"0", &device_containerp);
		if(FAILED(hr) || !device_containerp)
		{
            goto LCleanup;
		}
		
		// Get the English VRAM string
		{
		  std::string ram_str = get_string(device_containerp, L"szDisplayMemoryEnglish");

		  // We don't need the device any more
		  SAFE_RELEASE(device_containerp);

		  // Dump the string as an int into the structure
		  char *stopstring;
		  mVRAM = strtol(ram_str.c_str(), &stopstring, 10); 
		  LL_INFOS("AppInit") << "VRAM Detected: " << mVRAM << " DX9 string: " << ram_str << LL_ENDL;
		}

		if (vram_only)
		{
			ok = TRUE;
			goto LCleanup;
		}


		/* for now, we ONLY do vram_only the rest of this
		   is commented out, to ensure no-one is tempted
		   to use it
		
		// Now let's get device and driver information
		// Get the IDxDiagContainer object called "DxDiag_SystemDevices".
		// This call may take some time while dxdiag gathers the info.
		DWORD num_devices = 0;
	    WCHAR wszContainer[256];
		LL_DEBUGS("AppInit") << "dx_diag_rootp->GetChildContainer DxDiag_SystemDevices" << LL_ENDL;
		hr = dx_diag_rootp->GetChildContainer(L"DxDiag_SystemDevices", &system_device_containerp);
		if (FAILED(hr))
		{
			goto LCleanup;
		}

		hr = system_device_containerp->GetNumberOfChildContainers(&num_devices);
		if (FAILED(hr))
		{
			goto LCleanup;
		}

		LL_DEBUGS("AppInit") << "DX9 iterating over devices" << LL_ENDL;
		S32 device_num = 0;
		for (device_num = 0; device_num < (S32)num_devices; device_num++)
		{
			hr = system_device_containerp->EnumChildContainerNames(device_num, wszContainer, 256);
			if (FAILED(hr))
			{
				goto LCleanup;
			}

			hr = system_device_containerp->GetChildContainer(wszContainer, &device_containerp);
			if (FAILED(hr) || device_containerp == NULL)
			{
				goto LCleanup;
			}

			std::string device_name = get_string(device_containerp, L"szDescription");

			std::string device_id = get_string(device_containerp, L"szDeviceID");

			LLDXDevice *dxdevicep = new LLDXDevice;
			dxdevicep->mName = device_name;
			dxdevicep->mPCIString = device_id;
			mDevices[dxdevicep->mPCIString] = dxdevicep;

			// Split the PCI string based on vendor, device, subsys, rev.
			std::string str(device_id);
			typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
			boost::char_separator<char> sep("&\\", "", boost::keep_empty_tokens);
			tokenizer tokens(str, sep);

			tokenizer::iterator iter = tokens.begin();
			S32 count = 0;
			BOOL valid = TRUE;
			for (;(iter != tokens.end()) && (count < 3);++iter)
			{
				switch (count)
				{
				case 0:
					if (strcmp(iter->c_str(), "PCI"))
					{
						valid = FALSE;
					}
					break;
				case 1:
					dxdevicep->mVendorID = iter->c_str();
					break;
				case 2:
					dxdevicep->mDeviceID = iter->c_str();
					break;
				default:
					// Ignore it
					break;
				}
				count++;
			}




			// Now, iterate through the related drivers
			hr = device_containerp->GetChildContainer(L"Drivers", &driver_containerp);
			if (FAILED(hr) || !driver_containerp)
			{
				goto LCleanup;
			}

			DWORD num_files = 0;
			hr = driver_containerp->GetNumberOfChildContainers(&num_files);
			if (FAILED(hr))
			{
				goto LCleanup;
			}

			S32 file_num = 0;
			for (file_num = 0; file_num < (S32)num_files; file_num++ )
			{

				hr = driver_containerp->EnumChildContainerNames(file_num, wszContainer, 256);
				if (FAILED(hr))
				{
					goto LCleanup;
				}

				hr = driver_containerp->GetChildContainer(wszContainer, &file_containerp);
				if (FAILED(hr) || file_containerp == NULL)
				{
					goto LCleanup;
				}

				std::string driver_path = get_string(file_containerp, L"szPath");
				std::string driver_name = get_string(file_containerp, L"szName");
				std::string driver_version = get_string(file_containerp, L"szVersion");
				std::string driver_date = get_string(file_containerp, L"szDatestampEnglish");

				LLDXDriverFile *dxdriverfilep = new LLDXDriverFile;
				dxdriverfilep->mName = driver_name;
				dxdriverfilep->mFilepath= driver_path;
				dxdriverfilep->mVersionString = driver_version;
				dxdriverfilep->mVersion.set(driver_version);
				dxdriverfilep->mDateString = driver_date;

				dxdevicep->mDriverFiles[driver_name] = dxdriverfilep;

				SAFE_RELEASE(file_containerp);
			}
			SAFE_RELEASE(device_containerp);
		}
		*/
    }

    // dumpDevices();
    ok = TRUE;
	
LCleanup:
	if (!ok)
	{
		LL_WARNS("AppInit") << "DX9 probe failed" << LL_ENDL;
		gWriteDebug("DX9 probe failed\n");
	}

	SAFE_RELEASE(file_containerp);
	SAFE_RELEASE(driver_containerp);
	SAFE_RELEASE(device_containerp);
	SAFE_RELEASE(devices_containerp);
    SAFE_RELEASE(dx_diag_rootp);
    SAFE_RELEASE(dx_diag_providerp);
    
    CoUninitialize();
    
    return ok;
    }
	/*virtual*/ void httpFailure()
	{
		LL_WARNS() << "experience responder failed [status:" << getStatus() << "]: " << getContent() << LL_ENDL;
	}
void LLDrawable::shiftPos(const LLVector4a &shift_vector)
{
	if (isDead())
	{
		LL_WARNS() << "Shifting dead drawable" << LL_ENDL;
		return;
	}

	if (mParent)
	{
		mXform.setPosition(mVObjp->getPosition());
	}
	else
	{
		mXform.setPosition(mVObjp->getPositionAgent());
	}

	mXform.updateMatrix();

	if (isStatic())
	{
		LLVOVolume* volume = getVOVolume();

		bool rebuild = (!volume && 
						getRenderType() != LLPipeline::RENDER_TYPE_TREE &&
						getRenderType() != LLPipeline::RENDER_TYPE_TERRAIN &&
						getRenderType() != LLPipeline::RENDER_TYPE_SKY &&
						getRenderType() != LLPipeline::RENDER_TYPE_GROUND);

		if (rebuild)
		{
			gPipeline.markRebuild(this, LLDrawable::REBUILD_ALL, TRUE);
		}

		for (S32 i = 0; i < getNumFaces(); i++)
		{
			LLFace *facep = getFace(i);
			if (facep)
			{
				facep->mCenterAgent += LLVector3(shift_vector.getF32ptr());
				facep->mExtents[0].add(shift_vector);
				facep->mExtents[1].add(shift_vector);
			
				if (rebuild && facep->hasGeometry())
				{
					facep->clearVertexBuffer();
				}
			}
		}
		
		shift(shift_vector);
	}
	else if (mSpatialBridge)
	{
		mSpatialBridge->shiftPos(shift_vector);
	}
	else if (isAvatar())
	{
		shift(shift_vector);
	}
	
	mVObjp->onShift(shift_vector);
}
// Called instead of exit() if Libjpeg encounters an error.
void on_jpeg_error(j_common_ptr cinfo)
{
	(void) cinfo;
	sJpegErrorEncountered = true;
	LL_WARNS() << "Libjpeg has encountered an error!" << LL_ENDL;
}
BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)
{
	LL_RECORD_BLOCK_TIME(FTM_UPDATE_PARTICLES);

	dirtySpatialGroup();
	
	S32 num_parts = mViewerPartGroupp->getCount();
	LLFace *facep;
	LLSpatialGroup* group = drawable->getSpatialGroup();
	if (!group && num_parts)
	{
		drawable->movePartition();
		group = drawable->getSpatialGroup();
	}

	if (group && group->isVisible())
	{
		dirtySpatialGroup(TRUE);
	}

	if (!num_parts)
	{
		if (group && drawable->getNumFaces())
		{
			group->setState(LLSpatialGroup::GEOM_DIRTY);
		}
		drawable->setNumFaces(0, NULL, getTEImage(0));
		LLPipeline::sCompiles++;
		return TRUE;
	}

 	if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES)))
	{
		return TRUE;
	}

	if (num_parts > drawable->getNumFaces())
	{
		drawable->setNumFacesFast(num_parts+num_parts/4, NULL, getTEImage(0));
	}

	F32 tot_area = 0;

	F32 max_area = LLViewerPartSim::getMaxPartCount() * MAX_PARTICLE_AREA_SCALE; 
	F32 pixel_meter_ratio = LLViewerCamera::getInstance()->getPixelMeterRatio();
	pixel_meter_ratio *= pixel_meter_ratio;

	LLViewerPartSim::checkParticleCount(mViewerPartGroupp->mParticles.size()) ;

	S32 count=0;
	mDepth = 0.f;
	S32 i = 0 ;
	LLVector3 camera_agent = getCameraPosition();
	
	F32 max_scale = 0.f;


	for (i = 0 ; i < (S32)mViewerPartGroupp->mParticles.size(); i++)
	{
		const LLViewerPart *part = mViewerPartGroupp->mParticles[i];


		//remember the largest particle
		max_scale = llmax(max_scale, part->mScale.mV[0], part->mScale.mV[1]);

		if (part->mFlags & LLPartData::LL_PART_RIBBON_MASK)
		{ //include ribbon segment length in scale
			const LLVector3* pos_agent = NULL;
			if (part->mParent)
			{
				pos_agent = &(part->mParent->mPosAgent);
			}
			else if (part->mPartSourcep.notNull())
			{
				pos_agent = &(part->mPartSourcep->mPosAgent);
			}

			if (pos_agent)
			{
				F32 dist = (*pos_agent-part->mPosAgent).length();

				max_scale = llmax(max_scale, dist);
			}
		}

		LLVector3 part_pos_agent(part->mPosAgent);
		LLVector3 at(part_pos_agent - camera_agent);

		
		F32 camera_dist_squared = at.lengthSquared();
		F32 inv_camera_dist_squared;
		if (camera_dist_squared > 1.f)
			inv_camera_dist_squared = 1.f / camera_dist_squared;
		else
			inv_camera_dist_squared = 1.f;

		llassert(llfinite(inv_camera_dist_squared));
		llassert(!llisnan(inv_camera_dist_squared));

		F32 area = part->mScale.mV[0] * part->mScale.mV[1] * inv_camera_dist_squared;
		tot_area = llmax(tot_area, area);
 		
		if (tot_area > max_area)
		{
			break;
		}
	
		count++;

		facep = drawable->getFace(i);
		if (!facep)
		{
			LL_WARNS() << "No face found for index " << i << "!" << LL_ENDL;
			continue;
		}

		facep->setTEOffset(i);
		const F32 NEAR_PART_DIST_SQ = 5.f*5.f;  // Only discard particles > 5 m from the camera
		const F32 MIN_PART_AREA = .005f*.005f;  // only less than 5 mm x 5 mm at 1 m from camera
		
		if (camera_dist_squared > NEAR_PART_DIST_SQ && area < MIN_PART_AREA)
		{
			facep->setSize(0, 0);
			continue;
		}

		facep->setSize(4, 6);
		
		facep->setViewerObject(this);

		if (part->mFlags & LLPartData::LL_PART_EMISSIVE_MASK)
		{
			facep->setState(LLFace::FULLBRIGHT);
		}
		else
		{
			facep->clearState(LLFace::FULLBRIGHT);
		}

		facep->mCenterLocal = part->mPosAgent;
		facep->setFaceColor(part->mColor);
		facep->setTexture(part->mImagep);
			
		//check if this particle texture is replaced by a parcel media texture.
		if(part->mImagep.notNull() && part->mImagep->hasParcelMedia()) 
		{
			part->mImagep->getParcelMedia()->addMediaToFace(facep) ;
		}

		mPixelArea = tot_area * pixel_meter_ratio;
		const F32 area_scale = 10.f; // scale area to increase priority a bit
		facep->setVirtualSize(mPixelArea*area_scale);
	}
	for (i = count; i < drawable->getNumFaces(); i++)
	{
		LLFace* facep = drawable->getFace(i);
		if (!facep)
		{
			LL_WARNS() << "No face found for index " << i << "!" << LL_ENDL;
			continue;
		}
		facep->setTEOffset(i);
		facep->setSize(0, 0);
	}

	//record max scale (used to stretch bounding box for visibility culling)
	
	mScale.set(max_scale, max_scale, max_scale);

	mDrawable->movePartition();
	LLPipeline::sCompiles++;
	return TRUE;
}
Beispiel #18
0
////////////////////////////////////////////////////////////////////////////////
// inherited from LLViewerMediaObserver
//virtual 
void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
{
	switch(event)
	{
		case MEDIA_EVENT_CONTENT_UPDATED:
		{
			// LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CONTENT_UPDATED " << LL_ENDL;
		};
		break;
		
		case MEDIA_EVENT_TIME_DURATION_UPDATED:
		{
			// LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_TIME_DURATION_UPDATED, time is " << self->getCurrentTime() << " of " << self->getDuration() << LL_ENDL;
		};
		break;
		
		case MEDIA_EVENT_SIZE_CHANGED:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_SIZE_CHANGED " << LL_ENDL;
			LLRect r = getRect();
			reshape( r.getWidth(), r.getHeight(), FALSE );
		};
		break;
		
		case MEDIA_EVENT_CURSOR_CHANGED:
		{
			LL_INFOS("Media") <<  "Media event:  MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << self->getCursorName() << LL_ENDL;

			std::string cursor = self->getCursorName();
			
			if(cursor == "arrow")
				mLastSetCursor = UI_CURSOR_ARROW;
			else if(cursor == "ibeam")
				mLastSetCursor = UI_CURSOR_IBEAM;
			else if(cursor == "splith")
				mLastSetCursor = UI_CURSOR_SIZEWE;
			else if(cursor == "splitv")
				mLastSetCursor = UI_CURSOR_SIZENS;
			else if(cursor == "hand")
				mLastSetCursor = UI_CURSOR_HAND;
			else // for anything else, default to the arrow
				mLastSetCursor = UI_CURSOR_ARROW;
		};
		break;
		
		case MEDIA_EVENT_NAVIGATE_BEGIN:
		{
			LL_INFOS("Media") <<  "Media event:  MEDIA_EVENT_NAVIGATE_BEGIN, url is " << self->getNavigateURI() << LL_ENDL;
		};
		break;
		
		case MEDIA_EVENT_NAVIGATE_COMPLETE:
		{
			LL_INFOS("Media") <<  "Media event:  MEDIA_EVENT_NAVIGATE_COMPLETE, result string is: " << self->getNavigateResultString() << LL_ENDL;
			if(mHidingInitialLoad)
			{
				mHidingInitialLoad = false;
			}
		};
		break;

		case MEDIA_EVENT_PROGRESS_UPDATED:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_PROGRESS_UPDATED, loading at " << self->getProgressPercent() << "%" << LL_ENDL;
		};
		break;

		case MEDIA_EVENT_STATUS_TEXT_CHANGED:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_STATUS_TEXT_CHANGED, new status text is: " << self->getStatusText() << LL_ENDL;
		};
		break;

		case MEDIA_EVENT_LOCATION_CHANGED:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_LOCATION_CHANGED, new uri is: " << self->getLocation() << LL_ENDL;
		};
		break;

		case MEDIA_EVENT_NAVIGATE_ERROR_PAGE:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_NAVIGATE_ERROR_PAGE" << LL_ENDL;
			if (mErrorPageURL.length() > 0)
			{
				navigateTo(mErrorPageURL, "text/html");
			};
		};
		break;

		case MEDIA_EVENT_CLICK_LINK_HREF:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << self->getClickTarget() << "\", uri is " << self->getClickURL() << LL_ENDL;
		};
		break;
		
		case MEDIA_EVENT_CLICK_LINK_NOFOLLOW:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is " << self->getClickURL() << LL_ENDL;
			onClickLinkNoFollow(self);
		};
		break;

		case MEDIA_EVENT_PLUGIN_FAILED:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_PLUGIN_FAILED" << LL_ENDL;
		};
		break;

		case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << LL_ENDL;
		};
		break;
		
		case MEDIA_EVENT_NAME_CHANGED:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_NAME_CHANGED" << LL_ENDL;
		};
		break;
		
		case MEDIA_EVENT_CLOSE_REQUEST:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CLOSE_REQUEST" << LL_ENDL;
		}
		break;
		
		case MEDIA_EVENT_PICK_FILE_REQUEST:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_PICK_FILE_REQUEST" << LL_ENDL;
		}
		break;
		
		case MEDIA_EVENT_GEOMETRY_CHANGE:
		{
			LL_DEBUGS("Media") << "Media event:  MEDIA_EVENT_GEOMETRY_CHANGE, uuid is " << self->getClickUUID() << LL_ENDL;
		}
		break;

		case MEDIA_EVENT_STATUS_CHANGED:
		{
			LL_DEBUGS("Media") << "Media event:  MEDIA_EVENT_STATUS_CHANGED" << LL_ENDL;
		}
		break;

		case MEDIA_EVENT_AUTH_REQUEST:
		{
			LL_WARNS("Media") <<  "Unimplemented Media event:  MEDIA_EVENT_AUTH_REQUEST" << LL_ENDL;
		};
		break;

		case MEDIA_EVENT_LINK_HOVERED:
		{
			LL_WARNS("Media") <<  "Unimplemented Media event:  MEDIA_EVENT_LINK_HOVERED" << LL_ENDL;
		};
		break;
	};

	// chain all events to any potential observers of this object.
	emitEvent(self, event);
}
void LLPluginProcessParent::updatePollset()
{
	if(!sInstancesMutex)
	{
		// No instances have been created yet.  There's no work to do.
		return;
	}
		
	LLMutexLock lock(sInstancesMutex);

	if(sPollSet)
	{
		LL_DEBUGS("PluginPoll") << "destroying pollset " << sPollSet << LL_ENDL;
		// delete the existing pollset.
		apr_pollset_destroy(sPollSet);
		sPollSet = NULL;
	}
	
	std::list<LLPluginProcessParent*>::iterator iter;
	int count = 0;
	
	// Count the number of instances that want to be in the pollset
	for(iter = sInstances.begin(); iter != sInstances.end(); iter++)
	{
		(*iter)->mPolledInput = false;
		if((*iter)->mPollFD.client_data)
		{
			// This instance has a socket that needs to be polled.
			++count;
		}
	}

	if(sUseReadThread && sReadThread && !sReadThread->isQuitting())
	{
		if(!sPollSet && (count > 0))
		{
#ifdef APR_POLLSET_NOCOPY
			// The pollset doesn't exist yet.  Create it now.
			apr_status_t status = apr_pollset_create(&sPollSet, count, gAPRPoolp, APR_POLLSET_NOCOPY);
			if(status != APR_SUCCESS)
			{
#endif // APR_POLLSET_NOCOPY
				LL_WARNS("PluginPoll") << "Couldn't create pollset.  Falling back to non-pollset mode." << LL_ENDL;
				sPollSet = NULL;
#ifdef APR_POLLSET_NOCOPY
			}
			else
			{
				LL_DEBUGS("PluginPoll") << "created pollset " << sPollSet << LL_ENDL;
				
				// Pollset was created, add all instances to it.
				for(iter = sInstances.begin(); iter != sInstances.end(); iter++)
				{
					if((*iter)->mPollFD.client_data)
					{
						status = apr_pollset_add(sPollSet, &((*iter)->mPollFD));
						if(status == APR_SUCCESS)
						{
							(*iter)->mPolledInput = true;
						}
						else
						{
							LL_WARNS("PluginPoll") << "apr_pollset_add failed with status " << status << LL_ENDL;
						}
					}
				}
			}
#endif // APR_POLLSET_NOCOPY
		}
	}
}
LLLocationInputCtrl::LLLocationInputCtrl(const LLLocationInputCtrl::Params& p)
:	LLComboBox(p),
	mIconHPad(p.icon_hpad),
	mAddLandmarkHPad(p.add_landmark_hpad),
	mLocationContextMenu(NULL),
	mAddLandmarkBtn(NULL),
	mForSaleBtn(NULL),
	mInfoBtn(NULL),
	mRegionCrossingSlot(),
	mNavMeshSlot(),
	mIsNavMeshDirty(false),
	mLandmarkImageOn(NULL),
	mLandmarkImageOff(NULL),
	mIconMaturityGeneral(NULL),
	mIconMaturityAdult(NULL),
	mIconMaturityModerate(NULL),
	mMaturityHelpTopic(p.maturity_help_topic)
{
	// Lets replace default LLLineEditor with LLLocationLineEditor
	// to make needed escaping while copying and cutting url
	delete mTextEntry;

	// Can't access old mTextEntry fields as they are protected, so lets build new params
	// That is C&P from LLComboBox::createLineEditor function
	static LLUICachedControl<S32> drop_shadow_button ("DropShadowButton", 0);
	S32 arrow_width = mArrowImage ? mArrowImage->getWidth() : 0;
	LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
	text_entry_rect.mRight -= llmax(8,arrow_width) + 2 * drop_shadow_button;

	LLLineEditor::Params params = p.combo_editor;
	params.rect(text_entry_rect);
	params.default_text(LLStringUtil::null);
	params.max_length.bytes(p.max_chars);
	params.keystroke_callback(boost::bind(&LLLocationInputCtrl::onTextEntry, this, _1));
	params.commit_on_focus_lost(false);
	params.follows.flags(FOLLOWS_ALL);
	mTextEntry = LLUICtrlFactory::create<LLURLLineEditor>(params);
	mTextEntry->setContextMenu(NULL);
	addChild(mTextEntry);
	// LLLineEditor is replaced with LLLocationLineEditor

	// "Place information" button.
	LLButton::Params info_params = p.info_button;
	mInfoBtn = LLUICtrlFactory::create<LLButton>(info_params);
	mInfoBtn->setClickedCallback(boost::bind(&LLLocationInputCtrl::onInfoButtonClicked, this));
	addChild(mInfoBtn);

	// "Add landmark" button.
	LLButton::Params al_params = p.add_landmark_button;

	// Image for unselected state will be set in updateAddLandmarkButton(),
	// it will be either mLandmarkOn or mLandmarkOff
	if (p.add_landmark_image_enabled())
	{
		mLandmarkImageOn = p.add_landmark_image_enabled;
	}
	if (p.add_landmark_image_disabled())
	{
		mLandmarkImageOff = p.add_landmark_image_disabled;
	}

	if(p.add_landmark_image_selected)
	{
		al_params.image_selected = p.add_landmark_image_selected;
	}
	if (p.add_landmark_image_hover())
	{
		al_params.image_hover_unselected = p.add_landmark_image_hover;
	}

	al_params.click_callback.function(boost::bind(&LLLocationInputCtrl::onAddLandmarkButtonClicked, this));
	mAddLandmarkBtn = LLUICtrlFactory::create<LLButton>(al_params);
	enableAddLandmarkButton(true);
	addChild(mAddLandmarkBtn);

	if (p.icon_maturity_general())
	{
		mIconMaturityGeneral = p.icon_maturity_general;
	}		
	if (p.icon_maturity_adult())
	{
		mIconMaturityAdult = p.icon_maturity_adult;
	}
	if(p.icon_maturity_moderate())
	{
		mIconMaturityModerate = p.icon_maturity_moderate;
	}
	
	LLButton::Params maturity_button = p.maturity_button;
	mMaturityButton = LLUICtrlFactory::create<LLButton>(maturity_button);
	addChild(mMaturityButton);
	mMaturityButton->setClickedCallback(boost::bind(&LLLocationInputCtrl::onMaturityButtonClicked, this));

	LLButton::Params for_sale_button = p.for_sale_button;
	for_sale_button.tool_tip = LLTrans::getString("LocationCtrlForSaleTooltip");
	for_sale_button.click_callback.function(
		boost::bind(&LLLocationInputCtrl::onForSaleButtonClicked, this));
	mForSaleBtn = LLUICtrlFactory::create<LLButton>( for_sale_button );
	addChild(mForSaleBtn);

	// Parcel property icons
	// Must be mouse-opaque so cursor stays as an arrow when hovering to
	// see tooltip.
	LLIconCtrl::Params voice_icon = p.voice_icon;
	voice_icon.tool_tip = LLTrans::getString("LocationCtrlVoiceTooltip");
	voice_icon.mouse_opaque = true;
	mParcelIcon[VOICE_ICON] = LLUICtrlFactory::create<LLIconCtrl>(voice_icon);
	mParcelIcon[VOICE_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, VOICE_ICON));
	addChild(mParcelIcon[VOICE_ICON]);

	LLIconCtrl::Params fly_icon = p.fly_icon;
	fly_icon.tool_tip = LLTrans::getString("LocationCtrlFlyTooltip");
	fly_icon.mouse_opaque = true;
	mParcelIcon[FLY_ICON] = LLUICtrlFactory::create<LLIconCtrl>(fly_icon);
	mParcelIcon[FLY_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, FLY_ICON));
	addChild(mParcelIcon[FLY_ICON]);

	LLIconCtrl::Params push_icon = p.push_icon;
	push_icon.tool_tip = LLTrans::getString("LocationCtrlPushTooltip");
	push_icon.mouse_opaque = true;
	mParcelIcon[PUSH_ICON] = LLUICtrlFactory::create<LLIconCtrl>(push_icon);
	mParcelIcon[PUSH_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, PUSH_ICON));
	addChild(mParcelIcon[PUSH_ICON]);

	LLIconCtrl::Params build_icon = p.build_icon;
	build_icon.tool_tip = LLTrans::getString("LocationCtrlBuildTooltip");
	build_icon.mouse_opaque = true;
	mParcelIcon[BUILD_ICON] = LLUICtrlFactory::create<LLIconCtrl>(build_icon);
	mParcelIcon[BUILD_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, BUILD_ICON));
	addChild(mParcelIcon[BUILD_ICON]);

	LLIconCtrl::Params scripts_icon = p.scripts_icon;
	scripts_icon.tool_tip = LLTrans::getString("LocationCtrlScriptsTooltip");
	scripts_icon.mouse_opaque = true;
	mParcelIcon[SCRIPTS_ICON] = LLUICtrlFactory::create<LLIconCtrl>(scripts_icon);
	mParcelIcon[SCRIPTS_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, SCRIPTS_ICON));
	addChild(mParcelIcon[SCRIPTS_ICON]);

	LLIconCtrl::Params damage_icon = p.damage_icon;
	damage_icon.tool_tip = LLTrans::getString("LocationCtrlDamageTooltip");
	damage_icon.mouse_opaque = true;
	mParcelIcon[DAMAGE_ICON] = LLUICtrlFactory::create<LLIconCtrl>(damage_icon);
	mParcelIcon[DAMAGE_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, DAMAGE_ICON));
	addChild(mParcelIcon[DAMAGE_ICON]);

	LLIconCtrl::Params pathfinding_dirty_icon = p.pathfinding_dirty_icon;
	pathfinding_dirty_icon.tool_tip = LLTrans::getString("LocationCtrlPathfindingDirtyTooltip");
	pathfinding_dirty_icon.mouse_opaque = true;
	mParcelIcon[PATHFINDING_DIRTY_ICON] = LLUICtrlFactory::create<LLIconCtrl>(pathfinding_dirty_icon);
	mParcelIcon[PATHFINDING_DIRTY_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, PATHFINDING_DIRTY_ICON));
	addChild(mParcelIcon[PATHFINDING_DIRTY_ICON]);

	LLIconCtrl::Params pathfinding_disabled_icon = p.pathfinding_disabled_icon;
	pathfinding_disabled_icon.tool_tip = LLTrans::getString("LocationCtrlPathfindingDisabledTooltip");
	pathfinding_disabled_icon.mouse_opaque = true;
	mParcelIcon[PATHFINDING_DISABLED_ICON] = LLUICtrlFactory::create<LLIconCtrl>(pathfinding_disabled_icon);
	mParcelIcon[PATHFINDING_DISABLED_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, PATHFINDING_DISABLED_ICON));
	addChild(mParcelIcon[PATHFINDING_DISABLED_ICON]);

	LLTextBox::Params damage_text = p.damage_text;
	damage_text.tool_tip = LLTrans::getString("LocationCtrlDamageTooltip");
	damage_text.mouse_opaque = true;
	mDamageText = LLUICtrlFactory::create<LLTextBox>(damage_text);
	addChild(mDamageText);
	
	LLIconCtrl::Params see_avatars_icon = p.see_avatars_icon;
	see_avatars_icon.tool_tip = LLTrans::getString("LocationCtrlSeeAVsTooltip");
	see_avatars_icon.mouse_opaque = true;
	mParcelIcon[SEE_AVATARS_ICON] = LLUICtrlFactory::create<LLIconCtrl>(see_avatars_icon);
	mParcelIcon[SEE_AVATARS_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, SEE_AVATARS_ICON));
	addChild(mParcelIcon[SEE_AVATARS_ICON]);
	
	// Register callbacks and load the location field context menu (NB: the order matters).
	LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Navbar.Action", boost::bind(&LLLocationInputCtrl::onLocationContextMenuItemClicked, this, _2));
	LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Navbar.EnableMenuItem", boost::bind(&LLLocationInputCtrl::onLocationContextMenuItemEnabled, this, _2));
		
	setPrearrangeCallback(boost::bind(&LLLocationInputCtrl::onLocationPrearrange, this, _2));
	getTextEntry()->setMouseUpCallback(boost::bind(&LLLocationInputCtrl::changeLocationPresentation, this));

	// Load the location field context menu
	mLocationContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_navbar.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
	if (!mLocationContextMenu)
	{
		LL_WARNS() << "Error loading navigation bar context menu" << LL_ENDL;
		
	}
	getTextEntry()->setRightMouseUpCallback(boost::bind(&LLLocationInputCtrl::onTextEditorRightClicked,this,_2,_3,_4));
	updateWidgetlayout();

	// Connecting signal for updating location on "Show Coordinates" setting change.
	LLControlVariable* coordinates_control = gSavedSettings.getControl("NavBarShowCoordinates").get();
	if (coordinates_control)
	{
		mCoordinatesControlConnection = coordinates_control->getSignal()->connect(boost::bind(&LLLocationInputCtrl::refreshLocation, this));
	}

	// Connecting signal for updating parcel icons on "Show Parcel Properties" setting change.
	LLControlVariable* parcel_properties_control = gSavedSettings.getControl("NavBarShowParcelProperties").get();
	if (parcel_properties_control)
	{
		mParcelPropertiesControlConnection = parcel_properties_control->getSignal()->connect(boost::bind(&LLLocationInputCtrl::refreshParcelIcons, this));
	}

	// - Make the "Add landmark" button updated when either current parcel gets changed
	//   or a landmark gets created or removed from the inventory.
	// - Update the location string on parcel change.
	mParcelMgrConnection = gAgent.addParcelChangedCallback(
		boost::bind(&LLLocationInputCtrl::onAgentParcelChange, this));
	// LLLocationHistory instance is being created before the location input control, so we have to update initial state of button manually.
	mButton->setEnabled(LLLocationHistory::instance().getItemCount() > 0);
	mLocationHistoryConnection = LLLocationHistory::getInstance()->setChangedCallback(
			boost::bind(&LLLocationInputCtrl::onLocationHistoryChanged, this,_1));

	mRegionCrossingSlot = gAgent.addRegionChangedCallback(boost::bind(&LLLocationInputCtrl::onRegionBoundaryCrossed, this));
	createNavMeshStatusListenerForCurrentRegion();

	mRemoveLandmarkObserver	= new LLRemoveLandmarkObserver(this);
	mAddLandmarkObserver	= new LLAddLandmarkObserver(this);
	gInventory.addObserver(mRemoveLandmarkObserver);
	gInventory.addObserver(mAddLandmarkObserver);

	mParcelChangeObserver = new LLParcelChangeObserver(this);
	LLViewerParcelMgr::getInstance()->addObserver(mParcelChangeObserver);

	mAddLandmarkTooltip = LLTrans::getString("LocationCtrlAddLandmarkTooltip");
	mEditLandmarkTooltip = LLTrans::getString("LocationCtrlEditLandmarkTooltip");
	mButton->setToolTip(LLTrans::getString("LocationCtrlComboBtnTooltip"));
	mInfoBtn->setToolTip(LLTrans::getString("LocationCtrlInfoBtnTooltip"));

	// <FS:ND> Prevent querying LLTrans each frame
	mTooltips.push_back( LLTrans::getString("LocationCtrlGeneralIconTooltip") );
	mTooltips.push_back( LLTrans::getString("LocationCtrlAdultIconTooltip") );
	mTooltips.push_back( LLTrans::getString("LocationCtrlModerateIconTooltip") );
	// </FS:ND>
}
void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
{
	std::string message_class = message.getClass();
	if(message_class == LLPLUGIN_MESSAGE_CLASS_INTERNAL)
	{
		// internal messages should be handled here
		std::string message_name = message.getName();
		if(message_name == "hello")
		{
			if(mState == STATE_CONNECTED)
			{
				// Plugin host has launched.  Tell it which plugin to load.
				setState(STATE_HELLO);
			}
			else
			{
				LL_WARNS("Plugin") << "received hello message in wrong state -- bailing out" << LL_ENDL;
				errorState();
			}
			
		}
		else if(message_name == "load_plugin_response")
		{
			if(mState == STATE_LOADING)
			{
				// Plugin has been loaded. 
				
				mPluginVersionString = message.getValue("plugin_version");
				LL_INFOS("Plugin") << "plugin version string: " << mPluginVersionString << LL_ENDL;

				// Check which message classes/versions the plugin supports.
				// TODO: check against current versions
				// TODO: kill plugin on major mismatches?
				mMessageClassVersions = message.getValueLLSD("versions");
				LLSD::map_iterator iter;
				for(iter = mMessageClassVersions.beginMap(); iter != mMessageClassVersions.endMap(); iter++)
				{
					LL_INFOS("Plugin") << "message class: " << iter->first << " -> version: " << iter->second.asString() << LL_ENDL;
				}
				
				// Send initial sleep time
				llassert_always(mSleepTime != 0.f);
				setSleepTime(mSleepTime, true);			

				setState(STATE_RUNNING);
			}
			else
			{
				LL_WARNS("Plugin") << "received load_plugin_response message in wrong state -- bailing out" << LL_ENDL;
				errorState();
			}
		}
		else if(message_name == "heartbeat")
		{
			// this resets our timer.
			mHeartbeat.setTimerExpirySec(mPluginLockupTimeout);

			mCPUUsage = message.getValueReal("cpu_usage");

			LL_DEBUGS("Plugin") << "cpu usage reported as " << mCPUUsage << LL_ENDL;
			
		}
		else if(message_name == "shm_add_response")
		{
			// Nothing to do here.
		}
		else if(message_name == "shm_remove_response")
		{
			std::string name = message.getValue("name");
			sharedMemoryRegionsType::iterator iter = mSharedMemoryRegions.find(name);
			
			if(iter != mSharedMemoryRegions.end())
			{
				// destroy the shared memory region
				iter->second->destroy();
				
				// and remove it from our map
				mSharedMemoryRegions.erase(iter);
			}
		}
		else
		{
			LL_WARNS("Plugin") << "Unknown internal message from child: " << message_name << LL_ENDL;
		}
	}
	else
	{
		if(mOwner != NULL)
		{
			mOwner->receivePluginMessage(message);
		}
	}
}
// resolve a simstring from a slurl
LLSLURL::LLSLURL(const std::string& slurl)
{
	// by default we go to agni.
	mType = INVALID;

	if(slurl == SIM_LOCATION_HOME)
	{
		mType = HOME_LOCATION;
	}
	else if(slurl.empty() || (slurl == SIM_LOCATION_LAST))
	{
		mType = LAST_LOCATION;
	}
	else
	{
		LLURI slurl_uri;
		// parse the slurl as a uri
		if(slurl.find(':') == std::string::npos)
		{
			// There may be no scheme ('secondlife:' etc.) passed in.  In that case
			// we want to normalize the slurl by putting the appropriate scheme
			// in front of the slurl.  So, we grab the appropriate slurl base
			// from the grid manager which may be http://slurl.com/secondlife/ for maingrid, or
			// https://<hostname>/region/ for Standalone grid (the word region, not the region name)
			// these slurls are typically passed in from the 'starting location' box on the login panel,
			// where the user can type in <regionname>/<x>/<y>/<z>
			std::string fixed_slurl = LLGridManager::getInstance()->getSLURLBase();

			// the slurl that was passed in might have a prepended /, or not.  So,
			// we strip off the prepended '/' so we don't end up with http://slurl.com/secondlife/<region>/<x>/<y>/<z>
			// or some such.
			
			if(slurl[0] == '/')
		    {
				fixed_slurl += slurl.substr(1);
		    }
			else
		    {
				fixed_slurl += slurl;
		    }
			// We then load the slurl into a LLURI form
			slurl_uri = LLURI(fixed_slurl);
		}
		else
		{
		    // as we did have a scheme, implying a URI style slurl, we
		    // simply parse it as a URI
		    slurl_uri = LLURI(slurl);
		}
		
		LLSD path_array = slurl_uri.pathArray();
		
		// determine whether it's a maingrid URI or an Standalone/open style URI
		// by looking at the scheme.  If it's a 'secondlife:' slurl scheme or
		// 'sl:' scheme, we know it's maingrid
		
		// At the end of this if/else block, we'll have determined the grid,
		// and the slurl type (APP or LOCATION)
		if(slurl_uri.scheme() == LLSLURL::SLURL_SECONDLIFE_SCHEME)
		{
			// parse a maingrid style slurl.  We know the grid is maingrid
			// so grab it.
			// A location slurl for maingrid (with the special schemes) can be in the form
			// secondlife://<regionname>/<x>/<y>/<z>
			// or
			// secondlife://<Grid>/secondlife/<region>/<x>/<y>/<z>
			// where if grid is empty, it specifies Agni
			
			// An app style slurl for maingrid can be
			// secondlife://<Grid>/app/<app parameters>
			// where an empty grid implies Agni
			
			// we'll start by checking the top of the 'path' which will be 
			// either 'app', 'secondlife', or <x>.
			
			// default to maingrid
			
			mGrid = MAINGRID;
			
			if ((path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH) ||
				(path_array[0].asString() == LLSLURL::SLURL_APP_PATH))
		    {
				// it's in the form secondlife://<grid>/(app|secondlife)
				// so parse the grid name to derive the grid ID
				if (!slurl_uri.hostName().empty())
				{
					mGrid = LLGridManager::getInstance()->getGridId(slurl_uri.hostName());
				}
				else if(path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH)
				{
					// If the slurl is in the form secondlife:///secondlife/<region> form, 
					// then we are in fact on maingrid.  
					mGrid = MAINGRID;
				}
				else if(path_array[0].asString() == LLSLURL::SLURL_APP_PATH)
				{
					// for app style slurls, where no grid name is specified, assume the currently
					// selected or logged in grid.
					mGrid =  LLGridManager::getInstance()->getGridId();
				}

				if(mGrid.empty())
				{
					// we couldn't find the grid in the grid manager, so bail
					LL_WARNS("AppInit")<<"unable to find grid"<<LL_ENDL;
					return;
				}
				// set the type as appropriate.
				if(path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH)
				{
					mType = LOCATION;
				}
				else
				{
					mType = APP;
				}
				path_array.erase(0);
		    }
			else
		    {
				// it wasn't a /secondlife/<region> or /app/<params>, so it must be secondlife://<region>
				// therefore the hostname will be the region name, and it's a location type
				mType = LOCATION;
				// 'normalize' it so the region name is in fact the head of the path_array
				path_array.insert(0, slurl_uri.hostName());
		    }
		}
		else if((slurl_uri.scheme() == LLSLURL::SLURL_HTTP_SCHEME) ||
		   (slurl_uri.scheme() == LLSLURL::SLURL_HTTPS_SCHEME) || 
		   (slurl_uri.scheme() == LLSLURL::SLURL_X_GRID_LOCATION_INFO_SCHEME))
		{
		    // We're dealing with either a Standalone style slurl or slurl.com slurl
		  if ((slurl_uri.hostName() == LLSLURL::SLURL_COM) ||
		      (slurl_uri.hostName() == LLSLURL::WWW_SLURL_COM) || 
		      (slurl_uri.hostName() == LLSLURL::MAPS_SECONDLIFE_COM))
			{
				// slurl.com implies maingrid
				mGrid = MAINGRID;
			}
		    else
			{
				// Don't try to match any old http://<host>/ URL as a SLurl.
				// SLE SLurls will have the grid hostname in the URL, so only
				// match http URLs if the hostname matches the grid hostname
				// (or its a slurl.com or maps.secondlife.com URL).
				if ((slurl_uri.scheme() == LLSLURL::SLURL_HTTP_SCHEME ||
					 slurl_uri.scheme() == LLSLURL::SLURL_HTTPS_SCHEME) &&
					slurl_uri.hostName() != LLGridManager::getInstance()->getGrid())
				{
					return;
				}

				// As it's a Standalone grid/open, we will always have a hostname, as Standalone/open  style
				// urls are properly formed, unlike the stinky maingrid style
				mGrid = slurl_uri.hostName();
			}
		    if (path_array.size() == 0)
			{
				// um, we need a path...
				return;
			}
			
			// we need to normalize the urls so
			// the path portion starts with the 'command' that we want to do
			// it can either be region or app.  
		    if ((path_array[0].asString() == LLSLURL::SLURL_REGION_PATH) ||
				(path_array[0].asString() == LLSLURL::SLURL_SECONDLIFE_PATH))
			{
				// strip off 'region' or 'secondlife'
				path_array.erase(0);
				// it's a location
				mType = LOCATION;
			}
			else if (path_array[0].asString() == LLSLURL::SLURL_APP_PATH)
			{
				mType = APP;
				path_array.erase(0);
				// leave app appended.  
			}
			else
			{
				// not a valid https/http/x-grid-location-info slurl, so it'll likely just be a URL
				return;
			}
		}
		else
		{
		    // invalid scheme, so bail
		    return;
		}
		
		
		if(path_array.size() == 0)
		{
			// we gotta have some stuff after the specifier as to whether it's a region or command
			return;
		}
		
		// now that we know whether it's an app slurl or a location slurl,
		// parse the slurl into the proper data structures.
		if(mType == APP)
		{		
			// grab the app command type and strip it (could be a command to jump somewhere, 
			// or whatever )
			mAppCmd = path_array[0].asString();
			path_array.erase(0);
			
			// Grab the parameters
			mAppPath = path_array;
			// and the query
			mAppQuery = slurl_uri.query();
			mAppQueryMap = slurl_uri.queryMap();
			return;
		}
		else if(mType == LOCATION)
		{
			// at this point, head of the path array should be [ <region>, <x>, <y>, <z> ] where x, y and z 
			// are collectively optional
			// are optional
			mRegion = LLURI::unescape(path_array[0].asString());
			path_array.erase(0);
			
			// parse the x, y, and optionally z
			if(path_array.size() >= 2)
			{	
			  
			  mPosition = LLVector3(path_array); // this construction handles LLSD without all components (values default to 0.f)
			  if((F32(mPosition[VX]) < 0.f) || 
                             (mPosition[VX] > REGION_WIDTH_METERS) ||
			     (F32(mPosition[VY]) < 0.f) || 
                             (mPosition[VY] > REGION_WIDTH_METERS) ||
			     (F32(mPosition[VZ]) < 0.f) || 
                             (mPosition[VZ] > REGION_HEIGHT_METERS))
			    {
			      mType = INVALID;
			      return;
			    }
 
			}
			else
			{
				// if x, y and z were not fully passed in, go to the middle of the region.
				// teleport will adjust the actual location to make sure you're on the ground
				// and such
				mPosition = LLVector3(REGION_WIDTH_METERS/2, REGION_WIDTH_METERS/2, 0);
			}
		}
	}
}
bool LLAudioEngine_FMOD::init(const S32 num_channels, void* userdata)
{
	mFadeIn = -10000;

	LLAudioEngine::init(num_channels, userdata);

	// Reserve one extra channel for the http stream.
	if (!FSOUND_SetMinHardwareChannels(num_channels + 1))
	{
		LL_WARNS("AppInit") << "FMOD::init[0](), error: " << FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
	}

	LL_DEBUGS("AppInit") << "LLAudioEngine_FMOD::init() initializing FMOD" << LL_ENDL;

	F32 version = FSOUND_GetVersion();
	if (version < FMOD_VERSION)
	{
		LL_WARNS("AppInit") << "Error : You are using the wrong FMOD version (" << version
			<< ")!  You should be using FMOD " << FMOD_VERSION << LL_ENDL;
		//return false;
	}

	U32 fmod_flags = 0x0;

#if LL_WINDOWS
	// Windows needs to know which window is frontmost.
	// This must be called before FSOUND_Init() per the FMOD docs.
	// This could be used to let FMOD handle muting when we lose focus,
	// but we don't actually want to do that because we want to distinguish
	// between minimized and not-focused states.
	if (!FSOUND_SetHWND(userdata))
	{
		LL_WARNS("AppInit") << "Error setting FMOD window: "
			<< FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
		return false;
	}
	// Play audio when we don't have focus.
	// (For example, IM client on top of us.)
	// This means we also try to play audio when minimized,
	// so we manually handle muting in that case. JC
	fmod_flags |= FSOUND_INIT_GLOBALFOCUS;
#endif

#if LL_LINUX
	// initialize the FMOD engine

	// This is a hack to use only FMOD's basic FPU mixer
	// when the LL_VALGRIND environmental variable is set,
	// otherwise valgrind will fall over on FMOD's MMX detection
	if (getenv("LL_VALGRIND"))		/*Flawfinder: ignore*/
	{
		LL_INFOS("AppInit") << "Pacifying valgrind in FMOD init." << LL_ENDL;
		FSOUND_SetMixer(FSOUND_MIXER_QUALITY_FPU);
	}

	// If we don't set an output method, Linux FMOD always
	// decides on OSS and fails otherwise.  So we'll manually
	// try ESD, then OSS, then ALSA.
	// Why this order?  See SL-13250, but in short, OSS emulated
	// on top of ALSA is ironically more reliable than raw ALSA.
	// Ack, and ESD has more reliable failure modes - but has worse
	// latency - than all of them, so wins for now.
	bool audio_ok = false;

	if (!audio_ok)
		if (NULL == getenv("LL_BAD_FMOD_ESD")) /*Flawfinder: ignore*/
		{
			LL_DEBUGS("AppInit") << "Trying ESD audio output..." << LL_ENDL;
			if(FSOUND_SetOutput(FSOUND_OUTPUT_ESD) &&
			   FSOUND_Init(44100, num_channels, fmod_flags))
			{
				LL_DEBUGS("AppInit") << "ESD audio output initialized OKAY"
					<< LL_ENDL;
				audio_ok = true;
			} else {
				LL_WARNS("AppInit") << "ESD audio output FAILED to initialize: "
					<< FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
			}
		} else {
			LL_DEBUGS("AppInit") << "ESD audio output SKIPPED" << LL_ENDL;
		}

	if (!audio_ok)
		if (NULL == getenv("LL_BAD_FMOD_OSS")) 	 /*Flawfinder: ignore*/
		{
			LL_DEBUGS("AppInit") << "Trying OSS audio output..."	<< LL_ENDL;
			if(FSOUND_SetOutput(FSOUND_OUTPUT_OSS) &&
			   FSOUND_Init(44100, num_channels, fmod_flags))
			{
				LL_DEBUGS("AppInit") << "OSS audio output initialized OKAY" << LL_ENDL;
				audio_ok = true;
			} else {
				LL_WARNS("AppInit") << "OSS audio output FAILED to initialize: "
					<< FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
			}
		} else {
			LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL;
		}

	if (!audio_ok)
		if (NULL == getenv("LL_BAD_FMOD_ALSA"))		/*Flawfinder: ignore*/
		{
			LL_DEBUGS("AppInit") << "Trying ALSA audio output..." << LL_ENDL;
			if(FSOUND_SetOutput(FSOUND_OUTPUT_ALSA) &&
			   FSOUND_Init(44100, num_channels, fmod_flags))
			{
				LL_DEBUGS("AppInit") << "ALSA audio output initialized OKAY" << LL_ENDL;
				audio_ok = true;
			} else {
				LL_WARNS("AppInit") << "ALSA audio output FAILED to initialize: "
					<< FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
			}
		} else {
			LL_DEBUGS("AppInit") << "OSS audio output SKIPPED" << LL_ENDL;
		}

	if (!audio_ok)
	{
		LL_WARNS("AppInit") << "Overall audio init failure." << LL_ENDL;
		return false;
	}

	// On Linux, FMOD causes a SIGPIPE for some netstream error
	// conditions (an FMOD bug); ignore SIGPIPE so it doesn't crash us.
	// NOW FIXED in FMOD 3.x since 2006-10-01.
	//signal(SIGPIPE, SIG_IGN);

	// We're interested in logging which output method we
	// ended up with, for QA purposes.
	switch (FSOUND_GetOutput())
	{
	case FSOUND_OUTPUT_NOSOUND: LL_DEBUGS("AppInit") << "Audio output: NoSound" << LL_ENDL; break;
	case FSOUND_OUTPUT_OSS:	LL_DEBUGS("AppInit") << "Audio output: OSS" << LL_ENDL; break;
	case FSOUND_OUTPUT_ESD:	LL_DEBUGS("AppInit") << "Audio output: ESD" << LL_ENDL; break;
	case FSOUND_OUTPUT_ALSA: LL_DEBUGS("AppInit") << "Audio output: ALSA" << LL_ENDL; break;
	default: LL_INFOS("AppInit") << "Audio output: Unknown!" << LL_ENDL; break;
	};

#else // LL_LINUX

	// initialize the FMOD engine
	if (!FSOUND_Init(44100, num_channels, fmod_flags))
	{
		LL_WARNS("AppInit") << "Error initializing FMOD: "
			<< FMOD_ErrorString(FSOUND_GetError()) << LL_ENDL;
		return false;
	}
	
#endif

	initInternetStream();

	LL_DEBUGS("AppInit") << "LLAudioEngine_FMOD::init() FMOD initialized correctly" << LL_ENDL;

	mInited = true;

	return true;
}
LLDir_Win32::LLDir_Win32()
{
	mDirDelimiter = "\\";

	WCHAR w_str[MAX_PATH];

	// Application Data is where user settings go
	SHGetSpecialFolderPath(NULL, w_str, CSIDL_APPDATA, TRUE);

	mOSUserDir = utf16str_to_utf8str(llutf16string(w_str));

	// We want cache files to go on the local disk, even if the
	// user is on a network with a "roaming profile".
	//
	// On XP this is:
	//   C:\Docments and Settings\James\Local Settings\Application Data
	// On Vista this is:
	//   C:\Users\James\AppData\Local
	//
	// We used to store the cache in AppData\Roaming, and the installer
	// cleans up that version on upgrade.  JC
	SHGetSpecialFolderPath(NULL, w_str, CSIDL_LOCAL_APPDATA, TRUE);
	mOSCacheDir = utf16str_to_utf8str(llutf16string(w_str));

	if (GetTempPath(MAX_PATH, w_str))
	{
		if (wcslen(w_str))	/* Flawfinder: ignore */ 
		{
			w_str[wcslen(w_str)-1] = '\0'; /* Flawfinder: ignore */ // remove trailing slash
		}
		mTempDir = utf16str_to_utf8str(llutf16string(w_str));
	}
	else
	{
		mTempDir = mOSUserDir;
	}

//	fprintf(stderr, "mTempDir = <%s>",mTempDir);

#if 1
	// Don't use the real app path for now, as we'll have to add parsing to detect if
	// we're in a developer tree, which has a different structure from the installed product.

	S32 size = GetModuleFileName(NULL, w_str, MAX_PATH);
	if (size)
	{
		w_str[size] = '\0';
		mExecutablePathAndName = utf16str_to_utf8str(llutf16string(w_str));
		S32 path_end = mExecutablePathAndName.find_last_of('\\');
		if (path_end != std::string::npos)
		{
			mExecutableDir = mExecutablePathAndName.substr(0, path_end);
			mExecutableFilename = mExecutablePathAndName.substr(path_end+1, std::string::npos);
		}
		else
		{
			mExecutableFilename = mExecutablePathAndName;
		}
		GetCurrentDirectory(MAX_PATH, w_str);
		mWorkingDir = utf16str_to_utf8str(llutf16string(w_str));

	}
	else
	{
		LL_WARNS("AppInit") << "Couldn't get APP path, assuming current directory!\n" << LL_ENDL;
		GetCurrentDirectory(MAX_PATH, w_str);
		mExecutableDir = utf16str_to_utf8str(llutf16string(w_str));
		// Assume it's the current directory
	}
#else
	GetCurrentDirectory(MAX_PATH, w_str);
	mExecutableDir = utf16str_to_utf8str(llutf16string(w_str));
#endif
	
	// When running in a dev tree, app_settings is under indra/newview/
	// but in production it is under Program Files/SecondLife/
	// Attempt to detect which one we're using. JC
	if (mExecutableDir.find("indra") != std::string::npos)
		mAppRODataDir = getCurPath();
	else
		mAppRODataDir = mExecutableDir;


	// Build the default cache directory
	mDefaultCacheDir = buildSLOSCacheDir();
	
	// Make sure it exists
	int res = LLFile::mkdir(mDefaultCacheDir);
	if (res == -1)
	{
		if (errno != EEXIST)
		{
			llwarns << "Couldn't create LL_PATH_CACHE dir " << mDefaultCacheDir << llendl;
		}
	}

	mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin";
}
//static
void LLObjectBackup::exportWorker(void *userdata)
{	
	LLObjectBackup* self = findInstance();
	if (!self)
	{
		gIdleCallbacks.deleteFunction(exportWorker);
		LL_WARNS() << "Export process aborted. LLObjectBackup instance gone !"
				<< LL_ENDL;
		LLNotifications::instance().add("ExportAborted");
		return;
	}

	self->updateExportNumbers();

	switch (self->mExportState)
	{
		case EXPORT_INIT:
		{
			self->showFloater(true);
			//LLSelectMgr::getInstance()->getSelection()->ref(); // Singu Note: Don't do this.
			// Fall through to EXPORT_CHECK_PERMS
		}
		case EXPORT_CHECK_PERMS:
		{
			struct ff : public LLSelectedNodeFunctor
			{
				virtual bool apply(LLSelectNode* node)
				{
					return LLObjectBackup::validateNode(node);
				}
			} func;

			LLViewerObject* object;
			object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
			if (object)
			{
				if (LLSelectMgr::getInstance()->getSelection()->applyToNodes(&func, false))
				{
					self->mExportState = EXPORT_FETCH_PHYSICS;
				}
				else
				{
					struct vv : public LLSelectedNodeFunctor
					{
						virtual bool apply(LLSelectNode* node)
						{
							return node->mValid;
						}
					} func2;

					if (LLSelectMgr::getInstance()->getSelection()->applyToNodes(&func2, false))
					{
						LL_WARNS() << "Incorrect permission to export" << LL_ENDL;
						self->mExportState = EXPORT_FAILED;
						LLSelectMgr::getInstance()->getSelection()->unref();
					}
					else
					{
						LL_DEBUGS("ObjectBackup") << "Nodes permissions not yet received, delaying..."
												  << LL_ENDL;
						self->mExportState = EXPORT_CHECK_PERMS;
					}
				}
			}
			else
			{
				self->mExportState = EXPORT_ABORTED;
				LLSelectMgr::getInstance()->getSelection()->unref();
			}
			break;
		}

		case EXPORT_FETCH_PHYSICS:
		{
			// Don't bother to try and fetch the extra physics flags if we
			// don't have sim support for them...
			if (!self->mGotExtraPhysics)
			{
				self->mExportState = EXPORT_STRUCTURE;
				break;
			}

			struct ff : public LLSelectedNodeFunctor
			{
				virtual bool apply(LLSelectNode* node)
				{
					LLViewerObject* object = node->getObject();
					return gObjectList.gotObjectPhysicsFlags(object);
				}
			} func;

			LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
			if (object)
			{
				if (LLSelectMgr::getInstance()->getSelection()->applyToNodes(&func, false))
				{
					self->mExportState = EXPORT_STRUCTURE;
				}
				else
				{
					LL_DEBUGS("ObjectBackup") << "Nodes physics not yet received, delaying..."
											  << LL_ENDL;
				}
			}
			else
			{
				self->mExportState = EXPORT_ABORTED;
				LLSelectMgr::getInstance()->getSelection()->unref();
			}
			break;
		}

		case EXPORT_STRUCTURE:
		{
			struct ff : public LLSelectedObjectFunctor
			{
				virtual bool apply(LLViewerObject* object)
				{
					bool is_attachment = object->isAttachment();
					object->boostTexturePriority(true);
					LLViewerObject::child_list_t children = object->getChildren();
					children.push_front(object); //push root onto list
					LLObjectBackup* self = findInstance();
					LLSD prim_llsd = self->primsToLLSD(children,
													   is_attachment);
					LLSD stuff;
					if (is_attachment)
					{
						stuff["root_position"] = object->getPositionEdit().getValue();
						stuff["root_rotation"] = ll_sd_from_quaternion(object->getRotationEdit());
					}
					else
					{
						stuff["root_position"] = object->getPosition().getValue();
						stuff["root_rotation"] = ll_sd_from_quaternion(object->getRotation());
					}
					stuff["group_body"] = prim_llsd;
					self->mLLSD["data"].append(stuff);
					return true;
				}
			} func;

			LLViewerObject* object;
			object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
			if (object)
			{
				self->mExportState = EXPORT_LLSD;
				LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, false);
			}
			else
			{
				self->mExportState = EXPORT_ABORTED;
			}
			LLSelectMgr::getInstance()->getSelection()->unref();
			break;
		}

		case EXPORT_TEXTURES:
		{
			if (!self->mCheckNextTexture)
			{
				// The texture is being fetched. Wait till next idle callback.
				return;
			}

			if (self->mTexturesList.empty())
			{
				self->mExportState = EXPORT_DONE;
				return;
			}

			// Ok, we got work to do...
			self->mCheckNextTexture = false;
			self->exportNextTexture();
			break;
		}

		case EXPORT_LLSD:
		{
			// Create a file stream and write to it
			llofstream export_file(self->mFileName);
			LLSDSerialize::toPrettyXML(self->mLLSD, export_file);
			export_file.close();
			self->mCheckNextTexture = true;
			self->mExportState = EXPORT_TEXTURES;
			break;
		}

		case EXPORT_DONE:
		{
			gIdleCallbacks.deleteFunction(exportWorker);
			if (self->mNonExportedTextures == LLObjectBackup::TEXTURE_OK)
			{
				LL_INFOS() << "Export successful and complete." << LL_ENDL;
				LLNotificationsUtil::add("ExportSuccessful");
			}
			else
			{
				LL_INFOS() << "Export successful but incomplete: some texture(s) not saved."
						<< LL_ENDL;
				std::string reason;
				U32 error_bits_map = self->mNonExportedTextures;
				if (error_bits_map & LLObjectBackup::TEXTURE_BAD_PERM)
				{
					reason += "\nBad permissions/creator.";
				}
				if (error_bits_map & LLObjectBackup::TEXTURE_MISSING)
				{
					reason += "\nMissing texture (retrying after full rezzing might work).";
				}
				if (error_bits_map & LLObjectBackup::TEXTURE_BAD_ENCODING)
				{
					reason += "\nBad texture encoding.";
				}
				if (error_bits_map & LLObjectBackup::TEXTURE_IS_NULL)
				{
					reason += "\nNull texture.";
				}
				if (error_bits_map & LLObjectBackup::TEXTURE_SAVED_FAILED)
				{
					reason += "\nCould not write to disk.";
				}
				LLSD args;
				args["REASON"] = reason;
				LLNotificationsUtil::add("ExportPartial", args);
			}
			self->destroy();
			break;
		}

		case EXPORT_FAILED:
		{
			gIdleCallbacks.deleteFunction(exportWorker);
			LL_WARNS() << "Export process failed." << LL_ENDL;
			LLNotificationsUtil::add("ExportFailed");
			self->destroy();
			break;
		}

		case EXPORT_ABORTED:
		{
			gIdleCallbacks.deleteFunction(exportWorker);
			LL_WARNS() << "Export process aborted." << LL_ENDL;
			LLNotificationsUtil::add("ExportAborted");
			self->destroy();
			break;
		}
	}
}
/////////////////////////////////////////////////////////////////////////////////////////
// inherited from LLViewerMediaObserver
// virtual 
void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
{
	switch(event)
	{
		case MEDIA_EVENT_DEBUG_MESSAGE:
		{
			// LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_DEBUG_MESSAGE " << LL_ENDL;
		};
		break;

		case MEDIA_EVENT_CONTENT_UPDATED:
		{
			// LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CONTENT_UPDATED " << LL_ENDL;
		};
		break;
		
		case MEDIA_EVENT_TIME_DURATION_UPDATED:
		{
			// LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_TIME_DURATION_UPDATED, time is " << self->getCurrentTime() << " of " << self->getDuration() << LL_ENDL;
		};
		break;
		
		case MEDIA_EVENT_SIZE_CHANGED:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_SIZE_CHANGED " << LL_ENDL;
		};
		break;
		
		case MEDIA_EVENT_CURSOR_CHANGED:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << self->getCursorName() << LL_ENDL;
		};
		break;
		
		case MEDIA_EVENT_NAVIGATE_BEGIN:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_NAVIGATE_BEGIN " << LL_ENDL;
		};
		break;
		
		case MEDIA_EVENT_NAVIGATE_COMPLETE:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_NAVIGATE_COMPLETE, result string is: " << self->getNavigateResultString() << LL_ENDL;
		};
		break;

		case MEDIA_EVENT_PROGRESS_UPDATED:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_PROGRESS_UPDATED, loading at " << self->getProgressPercent() << "%" << LL_ENDL;
		};
		break;

		case MEDIA_EVENT_STATUS_TEXT_CHANGED:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_STATUS_TEXT_CHANGED, new status text is: " << self->getStatusText() << LL_ENDL;
		};
		break;

		case MEDIA_EVENT_LOCATION_CHANGED:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_LOCATION_CHANGED, new uri is: " << self->getLocation() << LL_ENDL;
		};
		break;

		case MEDIA_EVENT_NAVIGATE_ERROR_PAGE:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_NAVIGATE_ERROR_PAGE" << LL_ENDL;
		};
		break;

		case MEDIA_EVENT_CLICK_LINK_HREF:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << self->getClickTarget() << "\", uri is " << self->getClickURL() << LL_ENDL;
		};
		break;
		
		case MEDIA_EVENT_CLICK_LINK_NOFOLLOW:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is " << self->getClickURL() << LL_ENDL;
		};
		break;

		case MEDIA_EVENT_PLUGIN_FAILED:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_PLUGIN_FAILED" << LL_ENDL;
		};
		break;
		
		case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << LL_ENDL;
		};
		break;
		
		case MEDIA_EVENT_NAME_CHANGED:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_NAME_CHANGED" << LL_ENDL;
		};
		break;

		case MEDIA_EVENT_CLOSE_REQUEST:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CLOSE_REQUEST" << LL_ENDL;
		}
		break;
		
		case MEDIA_EVENT_PICK_FILE_REQUEST:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_PICK_FILE_REQUEST" << LL_ENDL;
		}
		break;

		case MEDIA_EVENT_GEOMETRY_CHANGE:
		{
			LL_DEBUGS("Media") << "Media event:  MEDIA_EVENT_GEOMETRY_CHANGE, uuid is " << self->getClickUUID() << LL_ENDL;
		}
		break;

		case MEDIA_EVENT_AUTH_REQUEST:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_AUTH_REQUEST, url " << self->getAuthURL() << ", realm " << self->getAuthRealm() << LL_ENDL;
		}
		break;

		case MEDIA_EVENT_LINK_HOVERED:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_LINK_HOVERED, hover text is: " << self->getHoverText() << LL_ENDL;
		};
		break;

		default:
		{
			LL_WARNS("Media") <<  "Media event:  unknown event type" << LL_ENDL;
		}
	};
}
	//virtual 
	virtual void uploadComplete(const LLSD& content)
	{
		LLObjectBackup* self = LLObjectBackup::findInstance();
		if (!self)
		{
			LL_WARNS() << "Import aborted, LLObjectBackup instance gone !"
					<< LL_ENDL;
			// remove the "Uploading..." message
			LLUploadDialog::modalUploadFinished();
			return;
		}

		LLAssetType::EType asset_type = LLAssetType::lookup(mPostData["asset_type"].asString());
		LLInventoryType::EType inv_type = LLInventoryType::lookup(mPostData["inventory_type"].asString());

		// Update L$ and ownership credit information
		// since it probably changed on the server
		if (asset_type == LLAssetType::AT_TEXTURE ||
			asset_type == LLAssetType::AT_SOUND ||
			asset_type == LLAssetType::AT_ANIMATION)
		{
			LLMessageSystem* msg = gMessageSystem;
			msg->newMessageFast(_PREHASH_MoneyBalanceRequest);
			msg->nextBlockFast(_PREHASH_AgentData);
			msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
			msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
			msg->nextBlockFast(_PREHASH_MoneyData);
			msg->addUUIDFast(_PREHASH_TransactionID, LLUUID::null);
			gAgent.sendReliableMessage();
		}

		// Actually add the upload to viewer inventory
		LL_INFOS() << "Adding " << content["new_inventory_item"].asUUID() << " "
				<< content["new_asset"].asUUID() << " to inventory." << LL_ENDL;
		if (mPostData["folder_id"].asUUID().notNull())
		{
			LLPermissions perm;
			U32 next_owner_perm;
			perm.init(gAgentID, gAgentID, LLUUID::null, LLUUID::null);
			if (mPostData["inventory_type"].asString() == "snapshot")
			{
				next_owner_perm = PERM_ALL;
			}
			else
			{
				next_owner_perm = PERM_MOVE | PERM_TRANSFER;
			}
			perm.initMasks(PERM_ALL, PERM_ALL, PERM_NONE, PERM_NONE, next_owner_perm);
			S32 creation_date_now = time_corrected();
			LLPointer<LLViewerInventoryItem> item;
			item = new LLViewerInventoryItem(content["new_inventory_item"].asUUID(),
										mPostData["folder_id"].asUUID(),
										perm,
										content["new_asset"].asUUID(),
										asset_type, inv_type,
										mPostData["name"].asString(),
										mPostData["description"].asString(),
										LLSaleInfo::DEFAULT,
										LLInventoryItemFlags::II_FLAGS_NONE,
										creation_date_now);
			gInventory.updateItem(item);
			gInventory.notifyObservers();
		}
		else
		{
			LL_WARNS() << "Can't find a folder to put it into" << LL_ENDL;
		}

		// remove the "Uploading..." message
		LLUploadDialog::modalUploadFinished();

		self->updateMap(content["new_asset"].asUUID());
		self->uploadNextAsset();
	}
void LLDrawable::updateDistance(LLCamera& camera, bool force_update)
{
	if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD)
	{
		LL_WARNS() << "Attempted to update distance for non-world camera." << LL_ENDL;
		return;
	}

	if (gShiftFrame)
	{
		return;
	}

	//switch LOD with the spatial group to avoid artifacts
	//LLSpatialGroup* sg = getSpatialGroup();

	LLVector3 pos;

	//if (!sg || sg->changeLOD())
	{
		LLVOVolume* volume = getVOVolume();
		if (volume)
		{
			if (getGroup())
			{
				pos.set(getPositionGroup().getF32ptr());
			}
			else
			{
				pos = getPositionAgent();
			}
			
			if (isState(LLDrawable::HAS_ALPHA))
			{
				for (S32 i = 0; i < getNumFaces(); i++)
				{
					LLFace* facep = getFace(i);
					if (facep && 
						(force_update || facep->getPoolType() == LLDrawPool::POOL_ALPHA))
					{
						LLVector4a box;
						box.setSub(facep->mExtents[1], facep->mExtents[0]);
						box.mul(0.25f);
						LLVector3 v = (facep->mCenterLocal-camera.getOrigin());
						const LLVector3& at = camera.getAtAxis();
						for (U32 j = 0; j < 3; j++)
						{
							v.mV[j] -= box[j] * at.mV[j];
						}
						facep->mDistance = v * camera.getAtAxis();
					}
				}
			}
		}
		else
		{
			pos = LLVector3(getPositionGroup().getF32ptr());
		}

		pos -= camera.getOrigin();	
		mDistanceWRTCamera = ll_round(pos.magVec(), 0.01f);
		mVObjp->updateLOD();
	}
}
Beispiel #29
0
////////////////////////////////////////////////////////////////////////////////
// inherited from LLViewerMediaObserver
//virtual 
void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
{
	switch(event)
	{
		case MEDIA_EVENT_CONTENT_UPDATED:
		{
			// LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CONTENT_UPDATED " << LL_ENDL;
		};
		break;
		
		case MEDIA_EVENT_TIME_DURATION_UPDATED:
		{
			// LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_TIME_DURATION_UPDATED, time is " << self->getCurrentTime() << " of " << self->getDuration() << LL_ENDL;
		};
		break;
		
		case MEDIA_EVENT_SIZE_CHANGED:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_SIZE_CHANGED " << LL_ENDL;
			LLRect r = getRect();
			reshape( r.getWidth(), r.getHeight(), FALSE );
		};
		break;
		
		case MEDIA_EVENT_CURSOR_CHANGED:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CURSOR_CHANGED, new cursor is " << self->getCursorName() << LL_ENDL;
		}
		break;
			
		case MEDIA_EVENT_NAVIGATE_BEGIN:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_NAVIGATE_BEGIN, url is " << self->getNavigateURI() << LL_ENDL;
			hideNotification();
		};
		break;
		
		case MEDIA_EVENT_NAVIGATE_COMPLETE:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_NAVIGATE_COMPLETE, result string is: " << self->getNavigateResultString() << LL_ENDL;
			if(mHidingInitialLoad)
			{
				mHidingInitialLoad = false;
			}
		};
		break;

		case MEDIA_EVENT_PROGRESS_UPDATED:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_PROGRESS_UPDATED, loading at " << self->getProgressPercent() << "%" << LL_ENDL;
		};
		break;

		case MEDIA_EVENT_STATUS_TEXT_CHANGED:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_STATUS_TEXT_CHANGED, new status text is: " << self->getStatusText() << LL_ENDL;
		};
		break;

		case MEDIA_EVENT_LOCATION_CHANGED:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_LOCATION_CHANGED, new uri is: " << self->getLocation() << LL_ENDL;
			mCurrentNavUrl = self->getLocation();
		};
		break;

		case MEDIA_EVENT_NAVIGATE_ERROR_PAGE:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_NAVIGATE_ERROR_PAGE" << LL_ENDL;
			if ( mErrorPageURL.length() > 0 )
			{
				navigateTo(mErrorPageURL, "text/html");
			};
		};
		break;

		case MEDIA_EVENT_CLICK_LINK_HREF:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << self->getClickTarget() << "\", uri is " << self->getClickURL() << LL_ENDL;
			// retrieve the event parameters
			std::string url = self->getClickURL();
			std::string target = self->getClickTarget();
			std::string uuid = self->getClickUUID();

			LLWeb::loadURL(url, target, std::string());

			//LLNotification::Params notify_params("PopupAttempt");
			//notify_params.payload = LLSD().with("target", target).with("url", url).with("uuid", uuid).with("media_id", mMediaTextureID);
			//notify_params.functor(boost::bind(&LLMediaCtrl::onPopup, this, _1, _2));

			//if (mTrusted)
			//{
			//	LLNotifications::instance().forceResponse(notify_params, 0);
			//}
			//else
			//{
			//	LLNotifications::instance().add(notify_params);
			//}
			break;
		};

		case MEDIA_EVENT_CLICK_LINK_NOFOLLOW:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is " << self->getClickURL() << LL_ENDL;
		};
		break;

		case MEDIA_EVENT_PLUGIN_FAILED:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_PLUGIN_FAILED" << LL_ENDL;
		};
		break;

		case MEDIA_EVENT_PLUGIN_FAILED_LAUNCH:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_PLUGIN_FAILED_LAUNCH" << LL_ENDL;
		};
		break;
		
		case MEDIA_EVENT_NAME_CHANGED:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_NAME_CHANGED" << LL_ENDL;
		};
		break;
		
		case MEDIA_EVENT_CLOSE_REQUEST:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_CLOSE_REQUEST" << LL_ENDL;
		}
		break;
		
		case MEDIA_EVENT_PICK_FILE_REQUEST:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_PICK_FILE_REQUEST" << LL_ENDL;
		}
		break;
		
		case MEDIA_EVENT_GEOMETRY_CHANGE:
		{
			LL_DEBUGS("Media") << "Media event:  MEDIA_EVENT_GEOMETRY_CHANGE, uuid is " << self->getClickUUID() << LL_ENDL;
		}
		break;

		case MEDIA_EVENT_AUTH_REQUEST:
		{
			LLNotification::Params auth_request_params("AuthRequest");

			// pass in host name and realm for site (may be zero length but will always exist)
			LLSD args;
			LLURL raw_url( self->getAuthURL().c_str() );
			args["HOST_NAME"] = raw_url.getAuthority();
			args["REALM"] = self->getAuthRealm();
			auth_request_params.substitutions = args;

			auth_request_params.payload = LLSD().with("media_id", mMediaTextureID);
			auth_request_params.functor(boost::bind(&LLViewerMedia::onAuthSubmit, _1, _2));
			LLNotifications::instance().add(auth_request_params);
		};
		break;

		case MEDIA_EVENT_LINK_HOVERED:
		{
			LL_DEBUGS("Media") <<  "Media event:  MEDIA_EVENT_LINK_HOVERED, hover text is: " << self->getHoverText() << LL_ENDL;
			mHoverTextChanged = true;
		};
		break;

		case MEDIA_EVENT_FILE_DOWNLOAD:
		{
			//llinfos << "Media event - file download requested - filename is " << self->getFileDownloadFilename() << llendl;
			//LLNotificationsUtil::add("MediaFileDownloadUnsupported");
		};
		break;

		case MEDIA_EVENT_DEBUG_MESSAGE:
		{
			LL_INFOS("media") << self->getDebugMessageText() << LL_ENDL; 
		};
		break;
		
		default:
		{
			LL_WARNS("Media") <<  "Media event:  unknown event type" << LL_ENDL;
		};		
	};

	// chain all events to any potential observers of this object.
	emitEvent(self, event);
}
BOOL LLFeatureManager::loadFeatureTables()
{
	// *TODO - if I or anyone else adds something else to the skipped list
	// make this data driven.  Put it in the feature table and parse it
	// correctly
	mSkippedFeatures.insert("RenderAnisotropic");
	mSkippedFeatures.insert("RenderGamma");
	mSkippedFeatures.insert("RenderVBOEnable");
	mSkippedFeatures.insert("RenderFogRatio");

	std::string data_path = gDirUtilp->getAppRODataDir();

	data_path += gDirUtilp->getDirDelimiter();

	data_path += FEATURE_TABLE_FILENAME;
	lldebugs << "Looking for feature table in " << data_path << llendl;

	llifstream file;
	std::string name;
	U32		version;
	
	file.open(data_path); 	 /*Flawfinder: ignore*/

	if (!file)
	{
		LL_WARNS("RenderInit") << "Unable to open feature table!" << LL_ENDL;
		return FALSE;
	}

	// Check file version
	file >> name;
	file >> version;
	if (name != "version")
	{
		LL_WARNS("RenderInit") << data_path << " does not appear to be a valid feature table!" << LL_ENDL;
		return FALSE;
	}

	mTableVersion = version;

	LLFeatureList *flp = NULL;
	while (!file.eof() && file.good())
	{
		char buffer[MAX_STRING];		 /*Flawfinder: ignore*/

		file >> name;
		
		if (name.substr(0,2) == "//")
		{
			// This is a comment.
			file.getline(buffer, MAX_STRING);
			continue;
		}

		if (name.empty())
		{
			// This is a blank line
			file.getline(buffer, MAX_STRING);
			continue;
		}

		if (name == "list")
		{
			if (flp)
			{
				//flp->dump();
			}
			// It's a new mask, create it.
			file >> name;
			if (mMaskList.count(name))
			{
				LL_ERRS("RenderInit") << "Overriding mask " << name << ", this is invalid!" << LL_ENDL;
			}

			flp = new LLFeatureList(name);
			mMaskList[name] = flp;
		}
		else
		{
			if (!flp)
			{
				LL_ERRS("RenderInit") << "Specified parameter before <list> keyword!" << LL_ENDL;
			}
			S32 available;
			F32 recommended;
			file >> available >> recommended;
			flp->addFeature(name, available, recommended);
		}
	}