BOOL LLGestureMgr::triggerGesture(KEY key, MASK mask)
{
	std::vector <LLMultiGesture *> matching;
	item_map_t::iterator it;

	// collect matching gestures
	for (it = mActive.begin(); it != mActive.end(); ++it)
	{
		LLMultiGesture* gesture = (*it).second;

		// asset data might not have arrived yet
		if (!gesture) continue;

		if (gesture->mKey == key
			&& gesture->mMask == mask)
		{
			matching.push_back(gesture);
		}
	}

	// choose one and play it
	if (matching.size() > 0)
	{
		U32 random = ll_rand(matching.size());
		
		LLMultiGesture* gesture = matching[random];
			
		playGesture(gesture);
		return TRUE;
	}
	return FALSE;
}
Exemple #2
0
// get a random file in the directory
void LLDir_Mac::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
{
	S32 which_file;
	glob_t g;
	fname = "";
	
	std::string tmp_str;
	tmp_str = dirname;
	tmp_str += mask;
	
	if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
	{
		if(g.gl_pathc > 0)
		{
			
			which_file = ll_rand(g.gl_pathc);
	
//			llinfos << "getRandomFileInDir: returning number " << which_file << ", path is " << g.gl_pathv[which_file] << llendl;
			// The API wants just the filename, not the full path.
			//fname = g.gl_pathv[which_file];

			char *s = strrchr(g.gl_pathv[which_file], '/');
			
			if(s == NULL)
				s = g.gl_pathv[which_file];
			else if(s[0] == '/')
				s++;
				
			fname = s;
		}
		
		globfree(&g);
	}
}
Exemple #3
0
LLScriptLibData* lsa_randomize(LLScriptLibData* src, S32 stride)
{
	S32 number = src->getListLength();
	if (number <= 0)
	{
		return NULL;
	}
	if (stride <= 0)
	{
		stride = 1;
	}
	if(number % stride)
	{
		LLScriptLibData* retval = src->mListp;
		src->mListp = NULL;
		return retval;
	}
	S32 buckets = number / stride;

	// Copy everything into a special vector for sorting;
	std::vector<LLScriptLibData*> sort_array;
	sort_array.reserve(number);
	LLScriptLibData* temp = src->mListp;
	while(temp)
	{
		sort_array.push_back(temp);
		temp = temp->mListp;
	}

	// We cannot simply call random_shuffle or similar algorithm since
	// we need to obey the stride. So, we iterate over what we have
	// and swap each with a random other segment.
	S32 index = 0;
	S32 ii = 0;
	for(; ii < number; ii += stride)
	{
		index = ll_rand(buckets) * stride;
		for(S32 jj = 0; jj < stride; ++jj)
		{
			std::swap(sort_array[ii + jj], sort_array[index + jj]);
		}
	}

	// copy the pointers back out
	ii = 1;
	temp = sort_array[0];
	while (ii < number)
	{
		temp->mListp = sort_array[ii++];
		temp = temp->mListp;
	}
	temp->mListp = NULL;

	src->mListp = NULL;

	LLScriptLibData* ret_value = sort_array[0];
	return ret_value;
}
Exemple #4
0
	void random_object_t::test<7>()
	{
		S32 number = 0;
		for(S32 ii = 0; ii < 100000; ++ii)
		{
			number = ll_rand(-127);
			ensure("rand <= 0", (number <= 0));
			ensure("rand > -127", (number > -127));
		}
	}
Exemple #5
0
	void random_object_t::test<6>()
	{
		S32 number = 0;
		for(S32 ii = 0; ii < 100000; ++ii)
		{
			number = ll_rand(100);
			ensure("rand >= 0", (number >= 0));
			ensure("rand < 100", (number < 100));
		}
	}
Exemple #6
0
void LLPanelLogin::fillVer()
{
	getChild<LLSpinCtrl>("vermaj_spin")->forceSetValue((S32)gSavedSettings.getU32("SpecifiedVersionMaj"));
	getChild<LLSpinCtrl>("vermin_spin")->forceSetValue((S32)gSavedSettings.getU32("SpecifiedVersionMin"));
	getChild<LLSpinCtrl>("verpatch_spin")->forceSetValue((S32)gSavedSettings.getU32("SpecifiedVersionPatch"));

	//simple hack to stop bans based on specific versions, 257 is a reasonable upper limit for a build number.
	if(gSavedSettings.getU32("SpecifiedVersionBuild") == 100000)
		gSavedSettings.setU32("SpecifiedVersionBuild", ll_rand(257));

	getChild<LLSpinCtrl>("verbuild_spin")->forceSetValue((S32)gSavedSettings.getU32("SpecifiedVersionBuild"));

}
void exoFlickr::signRequest(LLSD& params, std::string method, std::string url)
{
	// Oauth junk
	params["oauth_consumer_key"] = EXO_FLICKR_API_KEY;
	std::string oauth_token = gSavedPerAccountSettings.getString("ExodusFlickrToken");
	if(oauth_token.length())
	{
	   params["oauth_token"] = oauth_token;
	}
	params["oauth_signature_method"] = "HMAC-SHA1";
	params["oauth_timestamp"] = (LLSD::Integer)time(NULL);
	params["oauth_nonce"] = ll_rand();
	params["oauth_version"] = "1.0";
	params["oauth_signature"] = getSignatureForCall(params, url, method); // This must be the last one set.
}
Exemple #8
0
LLUUID LLFloaterAO::GetRandomAnimIDFromState(const int state)
{
	std::vector<struct_all_anims> mAORandomizeAnims;
	struct_all_anims random_anims_loader;
	if (!mAOAllAnims.empty())
	{
		for (std::vector<struct_all_anims>::iterator iter = mAOAllAnims.begin(); iter != mAOAllAnims.end(); ++iter)
		{
			if (iter->state == state)
			{
				random_anims_loader.ao_id = iter->ao_id; mAORandomizeAnims.push_back(random_anims_loader);
			}
		}
		return mAORandomizeAnims[ll_rand(mAORandomizeAnims.size()-1)].ao_id;
	}
	else
	{
		return LLUUID::null;
	}
}
// get a random file in the directory
// automatically wrap if we've hit the end
void LLDir_Win32::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
{
    S32 num_files;
    S32 which_file;
    HANDLE random_search_h;

    fname = "";

    llutf16string pathname = utf8str_to_utf16str(dirname);
    pathname += utf8str_to_utf16str(mask);

    WIN32_FIND_DATA FileData;
    fname[0] = NULL;

    num_files = countFilesInDir(dirname,mask);
    if (!num_files)
    {
        return;
    }

    which_file = ll_rand(num_files);

//	llinfos << "Random select mp3 #" << which_file << llendl;

    // which_file now indicates the (zero-based) index to which file to play

    if ((random_search_h = FindFirstFile(pathname.c_str(), &FileData)) != INVALID_HANDLE_VALUE)
    {
        while (which_file--)
        {
            if (!FindNextFile(random_search_h, &FileData))
            {
                return;
            }
        }
        FindClose(random_search_h);

        fname = utf16str_to_utf8str(llutf16string(FileData.cFileName));
    }
}
Exemple #10
0
// get a random file in the directory
// automatically wrap if we've hit the end
void LLDir_Solaris::getRandomFileInDir(const std::string &dirname, const std::string &mask, std::string &fname)
{
	S32 num_files;
	S32 which_file;
	DIR *dirp;
	dirent *entryp = NULL;

	fname = "";

	num_files = countFilesInDir(dirname,mask);
	if (!num_files)
	{
		return;
	}

	which_file = ll_rand(num_files);

//	llinfos << "Random select file #" << which_file << llendl;

    // which_file now indicates the (zero-based) index to which file to play
	
	if (!((dirp = opendir(dirname.c_str()))))
	{
		while (which_file--)
		{
			if (!((entryp = readdir(dirp))))
			{
				return;
			}
		}		   

		if ((!which_file) && entryp)
		{
			fname = entryp->d_name;
		}
		
		closedir(dirp);
	}
}
S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname)
{
#define READ_BUFFER 1024
	unsigned char readbuffer[READ_BUFFER*4+44];   /* out of the data segment, not the stack */	/*Flawfinder: ignore*/

	ogg_stream_state os; /* take physical pages, weld into a logical stream of packets */
	ogg_page         og; /* one Ogg bitstream page.  Vorbis packets are inside */
	ogg_packet       op; /* one raw packet of data for decode */
	
	vorbis_info      vi; /* struct that stores all the static vorbis bitstream settings */
	vorbis_comment   vc; /* struct that stores all the user comments */
	
	vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
	vorbis_block     vb; /* local working space for packet->PCM decode */
	
	int eos=0;
	int result;

	U16 num_channels = 0;
	U32 sample_rate = 0;
	U32 bits_per_sample = 0;

	S32 format_error = 0;
	std::string error_msg;
	if ((format_error = check_for_invalid_wav_formats(in_fname, error_msg)))
	{
		llwarns << error_msg << ": " << in_fname << llendl;
		return(format_error);
	}

#if 1
	unsigned char wav_header[44];	/*Flawfinder: ignore*/

	S32 data_left = 0;

	LLAPRFile infile ;
	infile.open(in_fname,LL_APR_RB);
	if (!infile.getFileHandle())
	{
		llwarns << "Couldn't open temporary ogg file for writing: " << in_fname
			<< llendl;
		return(LLVORBISENC_SOURCE_OPEN_ERR);
	}

	LLAPRFile outfile ;
	outfile.open(out_fname,LL_APR_WPB);
	if (!outfile.getFileHandle())
	{
		llwarns << "Couldn't open upload sound file for reading: " << in_fname
			<< llendl;
		return(LLVORBISENC_DEST_OPEN_ERR);
	}
	
	 // parse the chunks
	 U32 chunk_length = 0;
	 U32 file_pos = 12;  // start at the first chunk (usually fmt but not always)
	 
	 while (infile.eof() != APR_EOF)
	 {
		 infile.seek(APR_SET,file_pos);
		 infile.read(wav_header, 44);
		 
		 chunk_length = ((U32) wav_header[7] << 24) 
			 + ((U32) wav_header[6] << 16) 
			 + ((U32) wav_header[5] << 8) 
			 + wav_header[4];
		 
//		 llinfos << "chunk found: '" << wav_header[0] << wav_header[1] << wav_header[2] << wav_header[3] << "'" << llendl;
		 
		 if (!(strncmp((char *)&(wav_header[0]),"fmt ",4)))
		 {
			 num_channels = ((U16) wav_header[11] << 8) + wav_header[10];
			 sample_rate = ((U32) wav_header[15] << 24) 
				 + ((U32) wav_header[14] << 16) 
				 + ((U32) wav_header[13] << 8) 
				 + wav_header[12];
			 bits_per_sample = ((U16) wav_header[23] << 8) + wav_header[22];
		 }
	 	 else if (!(strncmp((char *)&(wav_header[0]),"data",4)))
		 {
			 infile.seek(APR_SET,file_pos+8);
			 // leave the file pointer at the beginning of the data chunk data
			 data_left = chunk_length;			
			 break;
		 }
		 file_pos += (chunk_length + 8);
		 chunk_length = 0;
	 } 
	 

	 /********** Encode setup ************/
	 
	 /* choose an encoding mode */
	 /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */
	 vorbis_info_init(&vi);

	 // always encode to mono

	 // SL-52913 & SL-53779 determined this quality level to be our 'good
	 // enough' general-purpose quality level with a nice low bitrate.
	 // Equivalent to oggenc -q0.5
	 F32 quality = 0.05f;
//	 quality = (bitrate==128000 ? 0.4f : 0.1);

//	 if (vorbis_encode_init(&vi, /* num_channels */ 1 ,sample_rate, -1, bitrate, -1))
	 if (vorbis_encode_init_vbr(&vi, /* num_channels */ 1 ,sample_rate, quality))
//	 if (vorbis_encode_setup_managed(&vi,1,sample_rate,-1,bitrate,-1) ||
//		vorbis_encode_ctl(&vi,OV_ECTL_RATEMANAGE_AVG,NULL) ||
//		vorbis_encode_setup_init(&vi))
	{
		llwarns << "unable to initialize vorbis codec at quality " << quality << llendl;
		//		llwarns << "unable to initialize vorbis codec at bitrate " << bitrate << llendl;
		return(LLVORBISENC_DEST_OPEN_ERR);
	}
	 
	 /* add a comment */
	 vorbis_comment_init(&vc);
//	 vorbis_comment_add(&vc,"Linden");
	 
	 /* set up the analysis state and auxiliary encoding storage */
	 vorbis_analysis_init(&vd,&vi);
	 vorbis_block_init(&vd,&vb);
	 
	 /* set up our packet->stream encoder */
	 /* pick a random serial number; that way we can more likely build
		chained streams just by concatenation */
	 ogg_stream_init(&os, ll_rand());
	 
	 /* Vorbis streams begin with three headers; the initial header (with
		most of the codec setup parameters) which is mandated by the Ogg
		bitstream spec.  The second header holds any comment fields.  The
		third header holds the bitstream codebook.  We merely need to
		make the headers, then pass them to libvorbis one at a time;
		libvorbis handles the additional Ogg bitstream constraints */
	 
	 {
		 ogg_packet header;
		 ogg_packet header_comm;
		 ogg_packet header_code;
		 
		 vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code);
		 ogg_stream_packetin(&os,&header); /* automatically placed in its own
											  page */
		 ogg_stream_packetin(&os,&header_comm);
		 ogg_stream_packetin(&os,&header_code);
		 
		 /* We don't have to write out here, but doing so makes streaming 
		  * much easier, so we do, flushing ALL pages. This ensures the actual
		  * audio data will start on a new page
		  */
		 while(!eos){
			 int result=ogg_stream_flush(&os,&og);
			 if(result==0)break;
			 outfile.write(og.header, og.header_len);
			 outfile.write(og.body, og.body_len);
		 }
		 
	 }
	 
	 
	 while(!eos)
	 {
		 long bytes_per_sample = bits_per_sample/8;

		 long bytes=(long)infile.read(readbuffer,llclamp((S32)(READ_BUFFER*num_channels*bytes_per_sample),0,data_left)); /* stereo hardwired here */
		 
		 if (bytes==0)
		 {
			 /* end of file.  this can be done implicitly in the mainline,
				but it's easier to see here in non-clever fashion.
				Tell the library we're at end of stream so that it can handle
				the last frame and mark end of stream in the output properly */

			 vorbis_analysis_wrote(&vd,0);
//			 eos = 1;
			 
		 }
		 else
		 {
			 long i;
			 long samples;
			 int temp;

			 data_left -= bytes;
             /* data to encode */
			 
			 /* expose the buffer to submit data */
			 float **buffer=vorbis_analysis_buffer(&vd,READ_BUFFER);
			
			 i = 0;
			 samples = bytes / (num_channels * bytes_per_sample);

			 if (num_channels == 2)
			 {
				 if (bytes_per_sample == 2)
				 {
					 /* uninterleave samples */
					 for(i=0; i<samples ;i++)
					 {
					 	 temp =  ((signed char *)readbuffer)[i*4+1];	/*Flawfinder: ignore*/
						 temp += ((signed char *)readbuffer)[i*4+3];	/*Flawfinder: ignore*/
						 temp <<= 8;
						 temp += readbuffer[i*4];
						 temp += readbuffer[i*4+2];

						 buffer[0][i] = ((float)temp) / 65536.f;
					 }
				 }
				 else // presume it's 1 byte per which is unsigned (F#@%ing wav "standard")
				 {
					 /* uninterleave samples */
					 for(i=0; i<samples ;i++)
					 {
					 	 temp  = readbuffer[i*2+0];
						 temp += readbuffer[i*2+1];
						 temp -= 256;
						 buffer[0][i] = ((float)temp) / 256.f;
					 }
				 } 
			 }
			 else if (num_channels == 1)
			 {
				 if (bytes_per_sample == 2)
				 {
					 for(i=0; i < samples ;i++)
					 {
					 	 temp = ((signed char*)readbuffer)[i*2+1];
						 temp <<= 8;
						 temp += readbuffer[i*2];
						 buffer[0][i] = ((float)temp) / 32768.f;
					 }
				 }
				 else // presume it's 1 byte per which is unsigned (F#@%ing wav "standard")
				 {
					 for(i=0; i < samples ;i++)
					 {
						 temp = readbuffer[i];
						 temp -= 128;
						 buffer[0][i] = ((float)temp) / 128.f;
					 }
				 }
			 }
				
			 /* tell the library how much we actually submitted */
			 vorbis_analysis_wrote(&vd,i);
		 }
			 
		 /* vorbis does some data preanalysis, then divvies up blocks for
			more involved (potentially parallel) processing.  Get a single
			block for encoding now */
		 while(vorbis_analysis_blockout(&vd,&vb)==1)
		 {
			 
			 /* analysis */
			/* Do the main analysis, creating a packet */
			vorbis_analysis(&vb, NULL);
			vorbis_bitrate_addblock(&vb);

			while(vorbis_bitrate_flushpacket(&vd, &op)) 
			{
			 
			 /* weld the packet into the bitstream */
			 ogg_stream_packetin(&os,&op);
			 
			 /* write out pages (if any) */
			 while(!eos)
			 {
				 result = ogg_stream_pageout(&os,&og);

				 if(result==0)
				 	break;

				 outfile.write(og.header, og.header_len);
				 outfile.write(og.body, og.body_len);
				 
				 /* this could be set above, but for illustrative purposes, I do
					it here (to show that vorbis does know where the stream ends) */
				 
				 if(ogg_page_eos(&og))
				 	eos=1;
				 
			 }
			}
		 }
	 }
	 
	 
	 
	 /* clean up and exit.  vorbis_info_clear() must be called last */
	 
	 ogg_stream_clear(&os);
	 vorbis_block_clear(&vb);
	 vorbis_dsp_clear(&vd);
	 vorbis_comment_clear(&vc);
	 vorbis_info_clear(&vi);
	 
	 /* ogg_page and ogg_packet structs always point to storage in
		libvorbis.  They're never freed or manipulated directly */
	 
//	 fprintf(stderr,"Vorbis encoding: Done.\n");
	 llinfos << "Vorbis encoding: Done." << llendl;
	 
#endif
	 return(LLVORBISENC_NOERR);
	 
}
// Iterates through space delimited tokens in string, triggering any gestures found.
// Generates a revised string that has the found tokens replaced by their replacement strings
// and (as a minor side effect) has multiple spaces in a row replaced by single spaces.
BOOL LLGestureMgr::triggerAndReviseString(const std::string &utf8str, std::string* revised_string)
{
	std::string tokenized = utf8str;

	BOOL found_gestures = FALSE;
	BOOL first_token = TRUE;

	typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
	boost::char_separator<char> sep(" ");
	tokenizer tokens(tokenized, sep);
	tokenizer::iterator token_iter;

	for( token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
	{
		const char* cur_token = token_iter->c_str();
		LLMultiGesture* gesture = NULL;

		// Only pay attention to the first gesture in the string.
		if( !found_gestures )
		{
			// collect gestures that match
			std::vector <LLMultiGesture *> matching;
			item_map_t::iterator it;
			for (it = mActive.begin(); it != mActive.end(); ++it)
			{
				gesture = (*it).second;

				// Gesture asset data might not have arrived yet
				if (!gesture) continue;
				
				if (LLStringUtil::compareInsensitive(gesture->mTrigger, cur_token) == 0)
				{
					matching.push_back(gesture);
				}
				
				gesture = NULL;
			}

			
			if (matching.size() > 0)
			{
				// choose one at random
				{
					S32 random = ll_rand(matching.size());

					gesture = matching[random];
					
					playGesture(gesture);

					if (!gesture->mReplaceText.empty())
					{
						if( !first_token )
						{
							if (revised_string)
								revised_string->append( " " );
						}

						// Don't muck with the user's capitalization if we don't have to.
						if( LLStringUtil::compareInsensitive(cur_token, gesture->mReplaceText) == 0)
						{
							if (revised_string)
								revised_string->append( cur_token );
						}
						else
						{
							if (revised_string)
								revised_string->append( gesture->mReplaceText );
						}
					}
					found_gestures = TRUE;
				}
			}
		}
		
		if(!gesture)
		{
			// This token doesn't match a gesture.  Pass it through to the output.
			if( !first_token )
			{
				if (revised_string)
					revised_string->append( " " );
			}
			if (revised_string)
				revised_string->append( cur_token );
		}

		first_token = FALSE;
		gesture = NULL;
	}
	return found_gestures;
}
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);
}
Exemple #14
0
S32 ll_rand()
{
	return ll_rand(RAND_MAX);
}
Exemple #15
0
F32 gpu_benchmark()
{
    if (!gGLManager.mHasShaderObjects || !gGLManager.mHasTimerQuery)
    {   // don't bother benchmarking the fixed function
        // or venerable drivers which don't support accurate timing anyway
        // and are likely to be correctly identified by the GPU table already.
        return -1.f;
    }

    if (gBenchmarkProgram.mProgramObject == 0)
    {
        LLViewerShaderMgr::instance()->initAttribsAndUniforms();

        gBenchmarkProgram.mName = "Benchmark Shader";
        gBenchmarkProgram.mFeatures.attachNothing = true;
        gBenchmarkProgram.mShaderFiles.clear();
        gBenchmarkProgram.mShaderFiles.push_back(std::make_pair("interface/benchmarkV.glsl", GL_VERTEX_SHADER_ARB));
        gBenchmarkProgram.mShaderFiles.push_back(std::make_pair("interface/benchmarkF.glsl", GL_FRAGMENT_SHADER_ARB));
        gBenchmarkProgram.mShaderLevel = 1;
        if (!gBenchmarkProgram.createShader(NULL, NULL))
        {
            return -1.f;
        }
    }

    LLGLDisable blend(GL_BLEND);

    //measure memory bandwidth by:
    // - allocating a batch of textures and render targets
    // - rendering those textures to those render targets
    // - recording time taken
    // - taking the median time for a given number of samples

    //resolution of textures/render targets
    const U32 res = 1024;

    //number of textures
    const U32 count = 32;

    //number of samples to take
    const S32 samples = 64;

    if (gGLManager.mHasTimerQuery)
    {
        LLGLSLShader::initProfile();
    }

    LLRenderTarget dest[count];
    U32 source[count];
    LLImageGL::generateTextures(count, source);
    std::vector<F32> results;

    //build a random texture
    U8* pixels = new U8[res*res*4];

    for (U32 i = 0; i < res*res*4; ++i)
    {
        pixels[i] = (U8) ll_rand(255);
    }


    gGL.setColorMask(true, true);
    LLGLDepthTest depth(GL_FALSE);

    for (U32 i = 0; i < count; ++i)
    {   //allocate render targets and textures
        dest[i].allocate(res,res,GL_RGBA,false, false, LLTexUnit::TT_TEXTURE, true);
        dest[i].bindTarget();
        dest[i].clear();
        dest[i].flush();

        gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, source[i]);
        LLImageGL::setManualImage(GL_TEXTURE_2D, 0, GL_RGBA, res,res,GL_RGBA, GL_UNSIGNED_BYTE, pixels);
    }

    delete [] pixels;

    //make a dummy triangle to draw with
    LLPointer<LLVertexBuffer> buff = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, GL_STATIC_DRAW_ARB);
    buff->allocateBuffer(3, 0, true);

    LLStrider<LLVector3> v;
    LLStrider<LLVector2> tc;

    buff->getVertexStrider(v);

    v[0].set(-1,1,0);
    v[1].set(-1,-3,0);
    v[2].set(3,1,0);

    buff->flush();

    gBenchmarkProgram.bind();

    bool busted_finish = false;

    buff->setBuffer(LLVertexBuffer::MAP_VERTEX);
    glFinish();

    for (S32 c = -1; c < samples; ++c)
    {
        LLTimer timer;
        timer.start();

        for (U32 i = 0; i < count; ++i)
        {
            dest[i].bindTarget();
            gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, source[i]);
            buff->drawArrays(LLRender::TRIANGLES, 0, 3);
            dest[i].flush();
        }

        //wait for current batch of copies to finish
        if (busted_finish)
        {
            //read a pixel off the last target since some drivers seem to ignore glFinish
            dest[count-1].bindTarget();
            U32 pixel = 0;
            glReadPixels(0,0,1,1,GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
            dest[count-1].flush();
        }
        else
        {
            glFinish();
        }

        F32 time = timer.getElapsedTimeF32();

        if (c >= 0) // <-- ignore the first sample as it tends to be artificially slow
        {
            //store result in gigabytes per second
            F32 gb = (F32) ((F64) (res*res*8*count))/(1000000000);

            F32 gbps = gb/time;

            if (!gGLManager.mHasTimerQuery && !busted_finish && gbps > 128.f)
            {   //unrealistically high bandwidth for a card without timer queries, glFinish is probably ignored
                busted_finish = true;
                LL_WARNS() << "GPU Benchmark detected GL driver with broken glFinish implementation." << LL_ENDL;
            }
            else
            {
                results.push_back(gbps);
            }
        }
    }

    gBenchmarkProgram.unbind();

    if (gGLManager.mHasTimerQuery)
    {
        LLGLSLShader::finishProfile(false);
    }

    LLImageGL::deleteTextures(count, source);

    std::sort(results.begin(), results.end());

    F32 gbps = results[results.size()/2];

    LL_INFOS() << "Memory bandwidth is " << llformat("%.3f", gbps) << "GB/sec according to CPU timers" << LL_ENDL;

#if LL_DARWIN
    if (gbps > 512.f)
    {
        LL_WARNS() << "Memory bandwidth is improbably high and likely incorrect; discarding result." << LL_ENDL;
        //OSX is probably lying, discard result
        gbps = -1.f;
    }
#endif

    F32 ms = gBenchmarkProgram.mTimeElapsed/1000000.f;
    F32 seconds = ms/1000.f;

    F64 samples_drawn = res*res*count*samples;
    F32 samples_sec = (samples_drawn/1000000000.0)/seconds;
    gbps = samples_sec*8;

    LL_INFOS() << "Memory bandwidth is " << llformat("%.3f", gbps) << "GB/sec according to ARB_timer_query" << LL_ENDL;

    return gbps;
}