예제 #1
0
파일: gui_config.cpp 프로젝트: nonametr/mls
void MqsConfig::onCreateChannel()
{
	string channel_plugin_name = ((QAction*)sender())->text().toStdString();

    ChannelManager::create(channel_plugin_name, this);
    updateChannels();
}
예제 #2
0
파일: gui_config.cpp 프로젝트: nonametr/mls
void MqsConfig::onRemoveEncoder()
{
	string user_defined_encoder_name;
	QList<QListWidgetItem*> selected_encoders = ui.list_encoders->selectedItems();
	user_defined_encoder_name = selected_encoders.at(0)->text().toStdString();

	if(user_defined_encoder_name.empty())
		return;

	if(QMessageBox::question(this,"Confirmation","Are you really want to delete channel?",QMessageBox::Yes,QMessageBox::No) ==	QMessageBox::No)
		return;

	QString affected_channels("");
	QSqlQuery affected_channels_result = settings->query("SELECT name FROM channel WHERE encoder='%s'", user_defined_encoder_name.c_str());
	do
	{
		QSqlRecord affected_channel = affected_channels_result.record();
		affected_channels += affected_channel.value("name").toString();
	}while(affected_channels_result.next());
	if(!affected_channels.isEmpty())
	{
		QString question("Next linked channels: " + affected_channels + " will be deleted too. Continue?");

		if(QMessageBox::question(this,"Channel dependencies found", question, QMessageBox::Yes,QMessageBox::No) ==	QMessageBox::No)
			return;
	}
	settings->query("DELETE FROM channel WHERE encoder='%s'", user_defined_encoder_name.c_str());
	settings->query("DELETE FROM encoder WHERE name = '%s'", user_defined_encoder_name.c_str());
	updateEncoders();
	updateChannels();
}
예제 #3
0
void ofApp::update(){
    
    updateSound();
    updateChannels();
    updateTcp();
    
}
예제 #4
0
caScan2D::caScan2D(QWidget *parent) : QWidget(parent)
{
    m_init = true;

    m_widthDefined = false;
    m_heightDefined = false;

    m_xcptDefined = false;
    m_ycptDefined = false;
    m_xnewdataDefined = false;
    m_ynewdataDefined = false;
    m_savedata_pathDefined = false;
    m_savedata_subdirDefined = false;
    m_savedata_filenameDefined = false;

    thisSimpleView = false;
    savedSize = 0;
    savedWidth = 0;
    savedHeight = 0;
    selectionInProgress = false;

    savedData = (float*) 0;

    initWidgets();

    Xpos = Ypos = 0;

    scrollArea = (QScrollArea *) 0;

    mainLayout = new QGridLayout(this);
    mainLayout->setMargin(0);
    mainLayout->setSpacing(0);
    setLayout(mainLayout);
    setup();

    setColormap(spectrum_wavelength);
    setCustomMap("");
    setDiscreteCustomMap(false);
    
    setROIChannelsRead("");
    setROIChannelsWrite("");

    setROIreadType(none);
    setROIwriteType(none);

    setROIwritemarkerType(box);
    setROIreadmarkerType(box);
    
    setAccessW(true);
    installEventFilter(this);

    scaleFactor = 1.0;

    UpdatesPerSecond = 0;
    startTimer(1000);
    
    writeTimer = new QTimer(this);
    connect(writeTimer, SIGNAL(timeout()), this, SLOT(updateChannels()));   
}
void RssSubscribtionManager::addRssChannel(QString url) {
    RssSubscribtion* subscribtion = new RssSubscribtion(url, prefs->getDefaultEncoding());
    subscribtion->update();

    channels.insert(url, subscribtion);

    connect(&updateTimer, SIGNAL(timeout()), this, SLOT(updateChannels()));
}
예제 #6
0
void
pcl::modeler::CloudMeshItem::setProperties()
{
  cloud_mesh_->transform(*translation_x_, *translation_y_, *translation_z_,
    *rotation_x_, *rotation_y_, *rotation_z_);

  updateChannels();
}
예제 #7
0
AudioPortAudio::setupWidget::~setupWidget()
{
	disconnect( &m_setupUtil.m_backendModel, SIGNAL( dataChanged() ),
			&m_setupUtil, SLOT( updateDevices() ) );
			
	disconnect( &m_setupUtil.m_deviceModel, SIGNAL( dataChanged() ),
			&m_setupUtil, SLOT( updateChannels() ) );
}
void SBusRxClass::process(void)
{
  uint8_t RxChar, Finished = 0;
  
  if(RxSerial)
  {
    if(millis8() - StartMs > MAX_FRAME_TIME_MS)
    {
      RxState = SBUS_WAIT_FOR_0x0F;
    }
    while(RxSerial->available() > 0)
    {
      RxChar = RxSerial->read();
      switch(RxState)
      {
        case SBUS_WAIT_FOR_0x0F:
        if(RxChar == 0x0F)
        {
          StartMs = millis8(); /* Start of frame */
          RxIdx = 0;
          RxState = SBUS_WAIT_FOR_END_OF_DATA;
        }
        break;

        case SBUS_WAIT_FOR_END_OF_DATA:
        Data[RxIdx] = RxChar;
        RxIdx++;
        if(RxIdx >= SBUS_RX_DATA_NB) // 23
        {
          /* Check next byte is 0x00 */
          RxState = SBUS_WAIT_FOR_0x00;	
        }
        break;

        case SBUS_WAIT_FOR_0x00:
        if(RxChar == 0x00)
        {
          if(RxIdx == SBUS_RX_DATA_NB) // 23
          {
            /* Data received with good synchro */
            updateChannels();
            Synchro  = 0xFF;
            Finished = 1;
          }
        }
        RxState = SBUS_WAIT_FOR_0x0F;
        break;
      }
      if(Finished) break;
    }
  }
}
예제 #9
0
	void Control::setValue(float value)
	{
		float previousValue = mValue;

		mValue = std::max<float>(0.0,std::min<float>(1.0,value));

		if(mValue != previousValue)
		{
			updateChannels();

			notifyListeners(previousValue);
		}
	}
예제 #10
0
파일: gui_config.cpp 프로젝트: nonametr/mls
void MqsConfig::onRemoveChannel()
{
	string user_defined_channel_name;
	QList<QListWidgetItem*> selected_channels = ui.list_channel->selectedItems();
    if(!selected_channels.size())
        return;

	user_defined_channel_name = selected_channels.at(0)->text().toStdString();

	if(QMessageBox::question(this,"Confirmation","Are you really want to delete channel?",QMessageBox::Yes,QMessageBox::No) ==	QMessageBox::No)
		return;

	settings->query("DELETE FROM channel WHERE name = '%s'", user_defined_channel_name.c_str());
	updateChannels();
}
예제 #11
0
void IRCSession::processResponse(shared_ptr<IIRCCommand> command)
{
	OS_ASSERT(command != nullptr);
	
	switch(command->getType())
	{
	case ircCommandTypeMessage:				processCommandMessage(boost::dynamic_pointer_cast<IRCCommandMessage>(command));
											break;

	case ircCommandTypeChannelListStart:	invalidateChannels();
											break;

	case ircCommandTypeChannel:				{
												shared_ptr<IRCCommandChannel> commandChannel = boost::dynamic_pointer_cast<IRCCommandChannel>(command);
												OS_ASSERT(commandChannel != nullptr);
												validateChannel(commandChannel->getChannelName(), commandChannel->getChannelDescription(), commandChannel->getChannelUsers());
											}

											break;

	case ircCommandTypeChannelListEnd:		updateChannels(true);
											break;

	case ircCommandTypeJoin:				processCommandJoin(boost::dynamic_pointer_cast<IRCCommandJoin>(command));
											break;

	case ircCommandTypePart:				processCommandPart(boost::dynamic_pointer_cast<IRCCommandPart>(command));
											break;

	case ircCommandTypeNames:				processCommandNames(boost::dynamic_pointer_cast<IRCCommandNames>(command));
											break;

	case ircCommandTypeEndOfNames:			processCommandEndOfNames(boost::dynamic_pointer_cast<IRCCommandEndOfNames>(command));
											break;

	case ircCommandTypeQuit:				processCommandQuit(boost::dynamic_pointer_cast<IRCCommandQuit>(command));
											break;

	case ircCommandTypeNick:				processCommandNick(boost::dynamic_pointer_cast<IRCCommandNick>(command));
											break;

	case ircCommandTypeMode:				processCommandMode(boost::dynamic_pointer_cast<IRCCommandMode>(command));
											break;

	case ircCommandTypeKick:				processCommandKick(boost::dynamic_pointer_cast<IRCCommandKick>(command));
											break;
	}
}
예제 #12
0
void AM2400Commander::Panel::doLoad(const Settings::Object::State &s) {    
	if (s.loadInteger("Maximized"))
		showMaximized();
	else if (s.loadInteger("Minimized"))
		showMinimized();
	if (s.loadInteger("W") != NULL) {
		resize(s.loadInteger("W"), s.loadInteger("H"));
		parentWidget()->move(s.loadInteger("X"), s.loadInteger("Y"));
	}
    
    ui->inputChannelSpinBox->setValue( s.loadInteger("Input Channel") );
    ui->outputChannelSpinBox->setValue( s.loadInteger("Output Channel") );
    ui->ampModeButtonGroup->setButton( s.loadInteger("Mode") );
    
    updateChannels();
    updateMode( s.loadInteger("Mode") );
}
예제 #13
0
파일: gui_config.cpp 프로젝트: nonametr/mls
MqsConfig::MqsConfig(QWidget *parent, Qt::WindowFlags flags)
	: QWidget(parent, flags)
{
	ui.setupUi(this);

	updateEncoders();
	updateChannels();
	updateResolutions();
    vector<string> suported_channels = ChannelManager::getSuportedPlugins();
	for(unsigned int i = 0; i < suported_channels.size(); ++i)
	{
		QAction* act = new QAction(suported_channels[i].c_str(), 0);
		add_channel_menu.addAction(act);
		connect(act, SIGNAL(triggered()), this, SLOT(onCreateChannel()));
	}

    QSqlRecord plugin_path_rec = settings->query("SELECT value as plugin_path FROM property WHERE name = 'plugin_path'").record();
    QSqlRecord screen_shot_path_rec = settings->query("SELECT value as screen_shot_path FROM property WHERE name = 'screen_shot_path'").record();
    ui.line_plugin_path->setText(plugin_path_rec.value("plugin_path").toString());
    ui.line_screen_shot_path->setText(screen_shot_path_rec.value("screen_shot_path").toString());

    QObject::connect(this, SIGNAL(updateMain(GUIUpdate)), parent, SLOT(updateMain(GUIUpdate)));

	QObject::connect(ui.button_add_channel, SIGNAL(clicked()), this, SLOT(onAddChannel()));
	QObject::connect(ui.button_edit_channel, SIGNAL(clicked()), this, SLOT(onEditChannel()));
	QObject::connect(ui.button_remove_channel, SIGNAL(clicked()), this, SLOT(onRemoveChannel()));

	QObject::connect(ui.button_add_encoder, SIGNAL(clicked()), this, SLOT(onAddEncoder()));
	QObject::connect(ui.button_edit_encoder, SIGNAL(clicked()), this, SLOT(onEditEncoder()));
	QObject::connect(ui.button_remove_encoder, SIGNAL(clicked()), this, SLOT(onRemoveEncoder()));

	QObject::connect(ui.list_resolutions, SIGNAL(itemChanged(QListWidgetItem *)), this, SLOT(onResolutionItemChanged(QListWidgetItem *)));
	QObject::connect(ui.button_clearall_resolutions, SIGNAL(clicked()), this, SLOT(onClearAllResolutions()));
	QObject::connect(ui.button_sellectall_resolutions, SIGNAL(clicked()), this, SLOT(onSellectAllResolutions()));
	QObject::connect(ui.button_loaddefaults_resolutions, SIGNAL(clicked()), this, SLOT(onLoadDefaultResolutions()));
	QObject::connect(ui.button_add_resolutions, SIGNAL(clicked()), this, SLOT(onAddResolutions()));
	QObject::connect(ui.button_remove_resolutions, SIGNAL(clicked()), this, SLOT(onRemoveResolutions()));
	QObject::connect(ui.button_edit_resolutions, SIGNAL(clicked()), this, SLOT(onEditResolutions()));
	QObject::connect(ui.line_screen_shot_path, SIGNAL(textChanged(const QString &)), this, SLOT(onEditScreenShotPath(const QString &)));
	QObject::connect(ui.line_plugin_path, SIGNAL(textChanged(const QString &)), this, SLOT(onEditPluginPath(const QString &)));
	QObject::connect(ui.select_plugins_dir, SIGNAL(clicked()), this, SLOT(onSelectPluginPath()));
	QObject::connect(ui.select_screenshot_dir, SIGNAL(clicked()), this, SLOT(onSelectScreenShotPath()));

	QObject::connect(ui.list_encoders, SIGNAL(currentTextChanged(const QString &)), this, SLOT(onEncoderSelect(const QString &)));
}
예제 #14
0
파일: board.cpp 프로젝트: akru/Netland-NG
void Board::connectAll()
{
  connect(_conn, SIGNAL(boardChannelsRecv(QMap<int, shared_ptr<BoardChannel> >)),
          this, SLOT(updateChannels(QMap<int,shared_ptr<BoardChannel> >)));
  connect(_conn, SIGNAL(boardMessagesRecv(QMap<int,shared_ptr<BoardMessage> >)),
          this, SLOT(updateMessages(QMap<int,shared_ptr<BoardMessage> >)));

  connect(this, SIGNAL(addMessageReady(int,QString, int)),
          _conn, SLOT(boardAddMessage(int,QString,int)));
  connect(this, SIGNAL(addReplyReady(int,QString)),
          _conn, SLOT(boardAddReply(int,QString)));
  connect(this, SIGNAL(editMessageReady(int,QString,int)),
          _conn, SLOT(boardEditMessage(int,QString,int)));
  connect(this, SIGNAL(deleteMessageReady(int)),
          _conn, SLOT(boardDeleteMessage(int)));
  connect(this, SIGNAL(upMessageReady(int)),
          _conn, SLOT(boardUpMessage(int)));
}
void Axon200Commander::Panel::doLoad( const Settings::Object::State &s ) {
	if (s.loadInteger("Maximized"))
		showMaximized();
	else if (s.loadInteger("Minimized"))
		showMinimized();
	if (s.loadInteger("W") != NULL) {
		resize(s.loadInteger("W"), s.loadInteger("H"));
		parentWidget()->move(s.loadInteger("X"), s.loadInteger("Y"));
	}

    mainUI->inputChannelSpinBox->setValue( s.loadInteger("Input Channel") );
    mainUI->outputChannelSpinBox->setValue( s.loadInteger("Output Channel") );
    mainUI->gainComboBox->setCurrentItem( s.loadInteger("Gain") );
    mainUI->configComboBox->setCurrentItem( s.loadInteger("Headstage Config") );
    mainUI->ampModeButtonGroup->setButton( s.loadInteger("Mode") );
    mainUI->autoModeButton->setOn( s.loadInteger("Auto Mode") );

    updateChannels();
    updateGains();
    updateMode( s.loadInteger("Mode") );
}
예제 #16
0
void checkBT() {

	if(readBTPackage()) {

		data_type = data_buffer[TYPE_POS];

		switch(data_type) {
		case(DATA):
    		pwm_status = data_buffer[STATUS_POS];
			memcpy(&bt_data, &data_buffer[DATA_POS], DATA_LENGTH);
			updateChannels();
		break;
		case(RA):
   			sendDataBT();
        break;

		default:
			break;
		}
	}

}
예제 #17
0
void SDRPostThread::runPFBCH(SDRThreadIQData *data_in) {
    if (numChannels != data_in->numChannels || sampleRate != data_in->sampleRate) {
        numChannels = data_in->numChannels;
        sampleRate = data_in->sampleRate;
        initPFBChannelizer();
        doRefresh.store(true);
    }
    
    size_t dataSize = data_in->data.size();
    size_t outSize = data_in->data.size();
    
    if (outSize > dataOut.capacity()) {
        dataOut.reserve(outSize);
    }
    if (outSize != dataOut.size()) {
        dataOut.resize(outSize);
    }
    
    if (iqDataOutQueue != NULL && !iqDataOutQueue->full()) {
        DemodulatorThreadIQData *iqDataOut = visualDataBuffers.getBuffer();
        
        bool doVis = false;
        
        if (iqVisualQueue != NULL && !iqVisualQueue->full()) {
            doVis = true;
        }
        
        iqDataOut->setRefCount(1 + (doVis?1:0));
        
        iqDataOut->frequency = data_in->frequency;
        iqDataOut->sampleRate = data_in->sampleRate;
        iqDataOut->data.assign(data_in->data.begin(), data_in->data.begin() + dataSize);
        
        iqDataOutQueue->push(iqDataOut);
        if (doVis) {
            iqVisualQueue->push(iqDataOut);
        }
    }
    
    if (frequency != data_in->frequency) {
        frequency = data_in->frequency;
        doRefresh.store(true);
    }
    
    if (doRefresh.load()) {
        updateActiveDemodulators();
        updateChannels();
        doRefresh.store(false);
    }
    
    DemodulatorInstance *activeDemod = wxGetApp().getDemodMgr().getLastActiveDemodulator();
    int activeDemodChannel = -1;
    
    // Find active demodulators
    if (nRunDemods) {
        
        // channelize data
        // firpfbch output rate is (input rate / channels)
        for (int i = 0, iMax = dataSize; i < iMax; i+=numChannels) {
            firpfbch_crcf_analyzer_execute(channelizer, &data_in->data[i], &dataOut[i]);
        }
        
        for (int i = 0, iMax = numChannels+1; i < iMax; i++) {
            demodChannelActive[i] = 0;
        }
        
        // Find nearest channel for each demodulator
        for (size_t i = 0; i < nRunDemods; i++) {
            DemodulatorInstance *demod = runDemods[i];
            demodChannel[i] = getChannelAt(demod->getFrequency());
            if (demod == activeDemod) {
                activeDemodChannel = demodChannel[i];
            }
        }
        
        for (size_t i = 0; i < nRunDemods; i++) {
            // cache channel usage refcounts
            if (demodChannel[i] >= 0) {
                demodChannelActive[demodChannel[i]]++;
            }
        }
        
        // Run channels
        for (int i = 0; i < numChannels+1; i++) {
            int doDemodVis = ((activeDemodChannel == i) && (iqActiveDemodVisualQueue != NULL) && !iqActiveDemodVisualQueue->full())?1:0;
            
            if (!doDemodVis && demodChannelActive[i] == 0) {
                continue;
            }
            
            DemodulatorThreadIQData *demodDataOut = buffers.getBuffer();
            demodDataOut->setRefCount(demodChannelActive[i] + doDemodVis);
            demodDataOut->frequency = chanCenters[i];
            demodDataOut->sampleRate = chanBw;
            
            // Calculate channel buffer size
            size_t chanDataSize = (outSize/numChannels);
            
            if (demodDataOut->data.size() != chanDataSize) {
                if (demodDataOut->data.capacity() < chanDataSize) {
                    demodDataOut->data.reserve(chanDataSize);
                }
                demodDataOut->data.resize(chanDataSize);
            }
            
            int idx = i;
            
            // Extra channel wraps lower side band of lowest channel
            // to fix frequency gap on upper side of spectrum
            if (i == numChannels) {
                idx = (numChannels/2);
            }
            
            // prepare channel data buffer
            if (i == 0) {   // Channel 0 requires DC correction
                if (dcBuf.size() != chanDataSize) {
                    dcBuf.resize(chanDataSize);
                }
                for (size_t j = 0; j < chanDataSize; j++) {
                    dcBuf[j] = dataOut[idx];
                    idx += numChannels;
                }
                iirfilt_crcf_execute_block(dcFilter, &dcBuf[0], chanDataSize, &demodDataOut->data[0]);
            } else {
                for (size_t j = 0; j < chanDataSize; j++) {
                    demodDataOut->data[j] = dataOut[idx];
                    idx += numChannels;
                }
            }
            
            if (doDemodVis) {
                iqActiveDemodVisualQueue->push(demodDataOut);
            }
            
            for (size_t j = 0; j < nRunDemods; j++) {
                if (demodChannel[j] == i) {
                    DemodulatorInstance *demod = runDemods[j];
                    demod->getIQInputDataPipe()->push(demodDataOut);
                }
            }
        }
    }
}
예제 #18
0
AudioPortAudio::setupWidget::setupWidget( QWidget * _parent ) :
	AudioDeviceSetupWidget( AudioPortAudio::name(), _parent )
{
	m_backend = new ComboBox( this, "BACKEND" );
	m_backend->setGeometry( 64, 15, 260, 20 );

	QLabel * backend_lbl = new QLabel( tr( "BACKEND" ), this );
	backend_lbl->setFont( pointSize<7>( backend_lbl->font() ) );
	backend_lbl->move( 8, 18 );

	m_device = new ComboBox( this, "DEVICE" );
	m_device->setGeometry( 64, 35, 260, 20 );

	QLabel * dev_lbl = new QLabel( tr( "DEVICE" ), this );
	dev_lbl->setFont( pointSize<7>( dev_lbl->font() ) );
	dev_lbl->move( 8, 38 );
	
/*	LcdSpinBoxModel * m = new LcdSpinBoxModel(  );
	m->setRange( DEFAULT_CHANNELS, SURROUND_CHANNELS );
	m->setStep( 2 );
	m->setValue( ConfigManager::inst()->value( "audioportaudio",
							"channels" ).toInt() );

	m_channels = new LcdSpinBox( 1, this );
	m_channels->setModel( m );
	m_channels->setLabel( tr( "CHANNELS" ) );
	m_channels->move( 308, 20 );*/

	// Setup models
	PaError err = Pa_Initialize();
	if( err != paNoError ) {
		printf( "Couldn't initialize PortAudio: %s\n", Pa_GetErrorText( err ) );
		return;
	}
	
	// todo: setup backend model
	const PaHostApiInfo * hi;
	for( int i = 0; i < Pa_GetHostApiCount(); ++i )
	{
		hi = Pa_GetHostApiInfo( i );
		m_setupUtil.m_backendModel.addItem( hi->name );
	}

	Pa_Terminate();


	const QString& backend = ConfigManager::inst()->value( "audioportaudio",
		"backend" );
	const QString& device = ConfigManager::inst()->value( "audioportaudio",
		"device" );
	
	int i = qMax( 0, m_setupUtil.m_backendModel.findText( backend ) );
	m_setupUtil.m_backendModel.setValue( i );
	
	m_setupUtil.updateDevices();
	
	i = qMax( 0, m_setupUtil.m_deviceModel.findText( device ) );
	m_setupUtil.m_deviceModel.setValue( i );

	connect( &m_setupUtil.m_backendModel, SIGNAL( dataChanged() ),
			&m_setupUtil, SLOT( updateDevices() ) );
			
	connect( &m_setupUtil.m_deviceModel, SIGNAL( dataChanged() ),
			&m_setupUtil, SLOT( updateChannels() ) );
			
	m_backend->setModel( &m_setupUtil.m_backendModel );
	m_device->setModel( &m_setupUtil.m_deviceModel );
}
void LLAudioEngine::idle(F32 max_decode_time)
{
	if (max_decode_time <= 0.f)
	{
		max_decode_time = default_max_decode_time;
	}
	
	// "Update" all of our audio sources, clean up dead ones.
	// Primarily does position updating, cleanup of unused audio sources.
	// Also does regeneration of the current priority of each audio source.

	S32 i;
	for (i = 0; i < MAX_BUFFERS; i++)
	{
		if (mBuffers[i])
		{
			mBuffers[i]->mInUse = false;
		}
	}

	F32 max_priority = -1.f;
	LLAudioSource *max_sourcep = NULL; // Maximum priority source without a channel
	source_map::iterator iter;
	for (iter = mAllSources.begin(); iter != mAllSources.end();)
	{
		LLAudioSource *sourcep = iter->second;

		// Update this source
		sourcep->update();
		sourcep->updatePriority();

		if (sourcep->isDone())
		{
			// The source is done playing, clean it up.
			delete sourcep;
			mAllSources.erase(iter++);
			continue;
		}

		if (sourcep->isMuted())
		{
			++iter;
		  	continue;
		}

		if (!sourcep->getChannel() && sourcep->getCurrentBuffer())
		{
			// We could potentially play this sound if its priority is high enough.
			if (sourcep->getPriority() > max_priority)
			{
				max_priority = sourcep->getPriority();
				max_sourcep = sourcep;
			}
		}

		// Move on to the next source
		iter++;
	}

	// Now, do priority-based organization of audio sources.
	// All channels used, check priorities.
	// Find channel with lowest priority
	if (max_sourcep)
	{
		LLAudioChannel *channelp = getFreeChannel(max_priority);
		if (channelp)
		{
			//llinfos << "Replacing source in channel due to priority!" << llendl;
			max_sourcep->setChannel(channelp);
			channelp->setSource(max_sourcep);
			if (max_sourcep->isSyncSlave())
			{
				// A sync slave, it doesn't start playing until it's synced up with the master.
				// Flag this channel as waiting for sync, and return true.
				channelp->setWaiting(true);
			}
			else
			{
				channelp->setWaiting(false);
				channelp->play();
			}
		}
	}

	
	// Do this BEFORE we update the channels
	// Update the channels to sync up with any changes that the source made,
	// such as changing what sound was playing.
	updateChannels();

	// Update queued sounds (switch to next queued data if the current has finished playing)
	for (iter = mAllSources.begin(); iter != mAllSources.end(); ++iter)
	{
		// This is lame, instead of this I could actually iterate through all the sources
		// attached to each channel, since only those with active channels
		// can have anything interesting happen with their queue? (Maybe not true)
		LLAudioSource *sourcep = iter->second;
		if (!sourcep->mQueuedDatap || sourcep->isMuted())
		{
			// Muted, or nothing queued, so we don't care.
			continue;
		}

		LLAudioChannel *channelp = sourcep->getChannel();
		if (!channelp)
		{
			// This sound isn't playing, so we just process move the queue
			sourcep->mCurrentDatap = sourcep->mQueuedDatap;
			sourcep->mQueuedDatap = NULL;

			// Reset the timer so the source doesn't die.
			sourcep->mAgeTimer.reset();
			// Make sure we have the buffer set up if we just decoded the data
			if (sourcep->mCurrentDatap)
			{
				updateBufferForData(sourcep->mCurrentDatap);
			}

			// Actually play the associated data.
			sourcep->setupChannel();
			channelp = sourcep->getChannel();
			if (channelp)
			{
				channelp->updateBuffer();
				sourcep->getChannel()->play();
			}
			continue;
		}
		else
		{
			// Check to see if the current sound is done playing, or looped.
			if (!channelp->isPlaying())
			{
				sourcep->mCurrentDatap = sourcep->mQueuedDatap;
				sourcep->mQueuedDatap = NULL;

				// Reset the timer so the source doesn't die.
				sourcep->mAgeTimer.reset();

				// Make sure we have the buffer set up if we just decoded the data
				if (sourcep->mCurrentDatap)
				{
					updateBufferForData(sourcep->mCurrentDatap);
				}

				// Actually play the associated data.
				sourcep->setupChannel();
				channelp->updateBuffer();
				sourcep->getChannel()->play();
			}
			else if (sourcep->isLoop())
			{
				// It's a loop, we need to check and see if we're done with it.
				if (channelp->mLoopedThisFrame)
				{
					sourcep->mCurrentDatap = sourcep->mQueuedDatap;
					sourcep->mQueuedDatap = NULL;

					// Actually, should do a time sync so if we're a loop master/slave
					// we don't drift away.
					sourcep->setupChannel();
					sourcep->getChannel()->play();
				}
			}
		}
	}

	// Lame, update the channels AGAIN.
	// Update the channels to sync up with any changes that the source made,
	// such as changing what sound was playing.
	updateChannels();
	
	// Hack!  For now, just use a global sync master;
	LLAudioSource *sync_masterp = NULL;
	LLAudioChannel *master_channelp = NULL;
	F32 max_sm_priority = -1.f;
	for (iter = mAllSources.begin(); iter != mAllSources.end(); ++iter)
	{
		LLAudioSource *sourcep = iter->second;
		if (sourcep->isMuted())
		{
			continue;
		}
		if (sourcep->isSyncMaster())
		{
			if (sourcep->getPriority() > max_sm_priority)
			{
				sync_masterp = sourcep;
				master_channelp = sync_masterp->getChannel();
				max_sm_priority = sourcep->getPriority();
			}
		}
	}

	if (master_channelp && master_channelp->mLoopedThisFrame)
	{
		// Synchronize loop slaves with their masters
		// Update queued sounds (switch to next queued data if the current has finished playing)
		for (iter = mAllSources.begin(); iter != mAllSources.end(); ++iter)
		{
			LLAudioSource *sourcep = iter->second;

			if (!sourcep->isSyncSlave())
			{
				// Not a loop slave, we don't need to do anything
				continue;
			}

			LLAudioChannel *channelp = sourcep->getChannel();
			if (!channelp)
			{
				// Not playing, don't need to bother.
				continue;
			}

			if (!channelp->isPlaying())
			{
				// Now we need to check if our loop master has just looped, and
				// start playback if that's the case.
				if (sync_masterp->getChannel())
				{
					channelp->playSynced(master_channelp);
					channelp->setWaiting(false);
				}
			}
		}
	}

	// Sync up everything that the audio engine needs done.
	commitDeferredChanges();
	
	// Flush unused buffers that are stale enough
	for (i = 0; i < MAX_BUFFERS; i++)
	{
		if (mBuffers[i])
		{
			if (!mBuffers[i]->mInUse && mBuffers[i]->mLastUseTimer.getElapsedTimeF32() > 30.f)
			{
				//llinfos << "Flushing unused buffer!" << llendl;
				mBuffers[i]->mAudioDatap->mBufferp = NULL;
				delete mBuffers[i];
				mBuffers[i] = NULL;
			}
		}
	}


	// Clear all of the looped flags for the channels
	for (i = 0; i < MAX_CHANNELS; i++)
	{
		if (mChannels[i])
		{
			mChannels[i]->mLoopedThisFrame = false;
		}
	}

	// Decode audio files
	gAudioDecodeMgrp->processQueue(max_decode_time);
	
	// Call this every frame, just in case we somehow
	// missed picking it up in all the places that can add
	// or request new data.
	startNextTransfer();

	updateInternetStream();
}
예제 #20
0
void LLAudioEngine::idle(F32 max_decode_time)
{
	if (max_decode_time <= 0.f)
	{
		max_decode_time = default_max_decode_time;
	}
	
	// "Update" all of our audio sources, clean up dead ones.
	// Primarily does position updating, cleanup of unused audio sources.
	// Also does regeneration of the current priority of each audio source.

	S32 i;
	for (i = 0; i < MAX_BUFFERS; i++)
	{
		if (mBuffers[i])
		{
			mBuffers[i]->mInUse = false;
		}
	}

	//Iterate down all queued sources. Remove finished ones, sort active ones by priority. Find highest priority 'master' source if present.
	LLAudioSource *sync_masterp = NULL;	//Highest priority syncmaster
	LLAudioSource *sync_slavep = NULL;	//Highest priority syncslave

	//Priority queue that will be filled with soundsources that have a high likeleyhood of being able to start [re]playing this idle tick.
	//Sort order:  Primary: priority. Secondary: syncmaster. Tertiary: syncslave
	std::priority_queue<LLAudioSource*,std::vector<LLAudioSource*,boost::pool_allocator<LLAudioSource*> >,SourcePriorityComparator> queue;

	//Have to put syncslaves into a temporary list until the syncmaster state is determined.
	//If the syncmaster might be started, or just looped, insert all pending/looping syncslaves into the priority queue.
	//If the there is no active syncmaster, then stop any currently looping syncslaves and add none to the priority queue.
	//This is necessary as any looping soundsources to be stopped, MUST be stopped before iterating down the priority queue.
	static std::vector<LLAudioSource*> slave_list;	
	slave_list.clear();

	//Iterate over all sources. Update their decode or 'done' state, as well as their priorities.
	//Also add sources that might be able to start playing to the priority queue.
	//Only sources without channels should be added to priority queue.
	//Syncslaves must put into the slave list instead of the priority queue.
	for (source_map::iterator iter = mAllSources.begin(); iter != mAllSources.end();)
	{
		LLAudioSource *sourcep = iter->second;

		//Load/decode/queue pop
		sourcep->update();

		//Done after update, as failure to load might mark source as corrupt, which causes isDone to return true.
		if (sourcep->isDone())		
		{
			// The source is done playing, clean it up.
			delete sourcep;
			mAllSources.erase(iter++);
			continue;
		}

		// Increment iter here (it is not used anymore), so we can use continue below to move on to the next source.
		++iter;

		if(!sourcep->isLoop() && sourcep->mPlayedOnce && (!sourcep->mChannelp || !sourcep->mChannelp->isPlaying()))
		{
			continue;
		}

		LLAudioData *adp = sourcep->getCurrentData();
		//If there is no current data at all, or if it hasn't loaded, we must skip this source.
		if (!adp || !adp->getBuffer())
		{
			continue;
		}

		sourcep->updatePriority();	//Calculates current priority. 1.f=ambient. 0.f=muted. Otherwise based off of distance.

		if (sourcep->getPriority() < F_APPROXIMATELY_ZERO)
		{
			// Muted, or nothing queued, or too far, so we don't care.
			continue;
		}
		else if(sourcep->isSyncMaster())
		{
			if(!sync_masterp || sourcep->getPriority() > sync_masterp->getPriority())
			{
				if(sync_masterp && !sync_masterp->getChannel())
					queue.push(sync_masterp);	//Add lower-priority soundmaster to the queue as a normal sound.	
				sync_masterp = sourcep;
				//Don't add master to the queue yet.
				//Add it after highest-priority sound slave is found so we can outrank its priority.
				continue;	
			}
			//Else fall through like a normal sound.
		}
		else if(sourcep->isSyncSlave())
		{
			if(!sync_slavep || sourcep->getPriority() > sync_slavep->getPriority())
			{
				sync_slavep = sourcep;
			}
			//Don't add to the priority queue quite yet. Best primary syncmaster candidate may not have been determined yet.
			slave_list.push_back(sourcep);
			continue;
		}
		if(sourcep->getChannel())
		{
			//If this is just a regular sound and is currently playing then do nothing special.
			continue;
		}
		//Add to our queue. Highest priority will be at the front.
		queue.push(sourcep);		
	}

	// Do this BEFORE we update the channels
	// Update the channels to sync up with any changes that the source made,
	// such as changing what sound was playing.
	updateChannels();

	//Loop over all syncsaves. If no syncmaster, stop looping ones, else add ones that need [re]started to the priority queue.
	//Normally there are zero to one syncslaves, so this loop isn't typically expensive.
	for(std::vector<LLAudioSource*>::iterator iter=slave_list.begin();iter!=slave_list.end();++iter)
	{
		if(!sync_masterp)
		{
			//Stop any looping syncslaves. I'm not sure this behavior is correct, but letting looping syncslaves run
			//off on their own seems wrong. The lsl documentation is unclear.
			if((*iter)->getChannel() && (*iter)->isLoop())
			{
				(*iter)->getChannel()->cleanup();
			}
		}
		//If the syncmaster already has a channel and hasn't looped, then we can skip syncslaves this idle tick (there's nothing to do).
		else if((!sync_masterp->getChannel() || sync_masterp->getChannel()->mLoopedThisFrame))
		{
			//Add syncslaves that we might want to [re]start.
			if(!(*iter)->getChannel() || (*iter)->isLoop())
				queue.push((*iter));		
		}
	}

	if(sync_masterp)	
	{
		//Syncmaster must have priority greater than or equal to priority of highest priority syncslave.
		//The case of slave priority equaling master priority is handled in the comparator (SourcePriorityComparator).
		if(sync_slavep)
			sync_masterp->setPriority(sync_slavep->getPriority());
		if(!sync_masterp->getChannel())
		{
			queue.push(sync_masterp);
		}
	}

	// Dispatch all soundsources.
	bool syncmaster_started = sync_masterp && sync_masterp->getChannel() && sync_masterp->getChannel()->mLoopedThisFrame;
	while(!queue.empty())
	{
		LLAudioSource *sourcep = queue.top();
		queue.pop();

		//If the syncmaster hasn't just started playing, or hasn't just looped then skip this soundslave,
		//as there's nothing to do with it yet.
		if (sourcep->isSyncSlave() && !syncmaster_started)
		{
			continue;
		}

		LLAudioChannel *channelp = sourcep->getChannel();

		if (!channelp)
		{
			//No more channels. We can break here, as in theory, any lower priority sounds should have had their 
			//channel already stolen. There should be nothing playing, nor playable, when iterating beyond this point.
			if(!(channelp = getFreeChannel(sourcep->getPriority())))
			{
				break;
			}

			//If this is the primary syncmaster that we just started, then [re]start syncslaves further down in the priority queue.
			//Due to sorting and priority fudgery, the syncmaster is ALWAYS before any syncslaves in this loop.
			syncmaster_started |= (sourcep == sync_masterp);

			//setSource calls updateBuffer and update3DPosition, and resets the source mAgeTimer
			channelp->setSource(sourcep);	
		}

		if(sourcep->isSyncSlave())
			channelp->playSynced(sync_masterp->getChannel());
		else
			channelp->play();
	}

	// Sync up everything that the audio engine needs done.
	commitDeferredChanges();
	
	// Flush unused buffers that are stale enough
	for (i = 0; i < MAX_BUFFERS; i++)
	{
		if (mBuffers[i])
		{
			if (!mBuffers[i]->mInUse && mBuffers[i]->mLastUseTimer.getElapsedTimeF32() > 30.f)
			{
				LL_DEBUGS("AudioEngine") << "Flushing unused buffer!" << LL_ENDL;
				mBuffers[i]->mAudioDatap->mBufferp = NULL;
				delete mBuffers[i];
				mBuffers[i] = NULL;
			}
		}
	}


	// Clear all of the looped flags for the channels
	for (i = 0; i < MAX_CHANNELS; i++)
	{
		if (mChannels[i])
		{
			mChannels[i]->mLoopedThisFrame = false;
		}
	}

	// Decode audio files
	gAudioDecodeMgrp->processQueue(max_decode_time);
	
	// Just call here every frame. It makes little sense to call elsewhere,
	// as it's throttled to one active preloading loading sound at a time anyhow
	startNextTransfer();

	updateInternetStream();
}