Esempio n. 1
0
    void mouseDrag (const MouseEvent& e) override
    {
        if (auto* m = owner.getModel())
        {
            if (isEnabled() && e.mouseWasDraggedSinceMouseDown() && ! isDragging)
            {
                SparseSet<int> rowsToDrag;

                if (owner.selectOnMouseDown || owner.isRowSelected (row))
                    rowsToDrag = owner.getSelectedRows();
                else
                    rowsToDrag.addRange (Range<int>::withStartAndLength (row, 1));

                if (rowsToDrag.size() > 0)
                {
                    auto dragDescription = m->getDragSourceDescription (rowsToDrag);

                    if (! (dragDescription.isVoid() || (dragDescription.isString() && dragDescription.toString().isEmpty())))
                    {
                        isDragging = true;
                        owner.startDragAndDrop (e, rowsToDrag, dragDescription, true);
                    }
                }
            }
        }

        if (! isDraggingToScroll)
            if (auto* vp = owner.getViewport())
                isDraggingToScroll = vp->isCurrentlyScrollingOnDrag();
    }
Esempio n. 2
0
std::string SceneComponent::getSelectedSceneName() {
    SparseSet< int > rows = listBox->getSelectedRows ();
    if( !rows.size() )
        return 0;
    int idx = rows[0];
    return sceneinfo[idx]->getSceneName();
}
void PluginListComponent::removeSelectedPlugins()
{
    const SparseSet<int> selected (table.getSelectedRows());

    for (int i = table.getNumRows(); --i >= 0;)
        if (selected.contains (i))
            removePluginItem (i);
}
void PluginListComponent::removeSelected()
{
    const SparseSet <int> selected (listBox.getSelectedRows());

    for (int i = list.getNumTypes(); --i >= 0;)
        if (selected.contains (i))
            removePluginItem (list, i);
}
Esempio n. 5
0
    //==============================================================================
    void syncSelectedItemsWithDeviceList (const ReferenceCountedArray<MidiDeviceListEntry>& midiDevices)
    {
        SparseSet<int> selectedRows;
        for (int i = 0; i < midiDevices.size(); ++i)
            if (midiDevices[i]->inDevice != nullptr || midiDevices[i]->outDevice != nullptr)
                selectedRows.addRange (Range<int> (i, i+1));

        lastSelectedItems = selectedRows;
        updateContent();
        setSelectedRows (selectedRows, dontSendNotification);
    }
void PluginListComponent::optionsMenuCallback (int result)
{
    switch (result)
    {
        case 1:     list.clear(); break;

        case 2:     list.sort (KnownPluginList::sortAlphabetically); break;
        case 3:     list.sort (KnownPluginList::sortByCategory); break;
        case 4:     list.sort (KnownPluginList::sortByManufacturer); break;

        case 5:
        {
            const SparseSet <int> selected (listBox.getSelectedRows());

            for (int i = list.getNumTypes(); --i >= 0;)
                if (selected.contains (i))
                    list.removeType (i);

            break;
        }

        case 6:
        {
            const PluginDescription* const desc = list.getType (listBox.getSelectedRow());

            if (desc != nullptr && File (desc->fileOrIdentifier).existsAsFile())
                File (desc->fileOrIdentifier).getParentDirectory().startAsProcess();

            break;
        }

        case 7:
            for (int i = list.getNumTypes(); --i >= 0;)
                if (! AudioPluginFormatManager::getInstance()->doesPluginStillExist (*list.getType (i)))
                    list.removeType (i);

            break;

        default:
            if (result != 0)
            {
                typeToScan = result - 10;
                startTimer (1);
            }

            break;
    }
}
Esempio n. 7
0
/// Return true if Reg aliases a register in Regs SparseSet.
static bool hasRegAlias(unsigned Reg, SparseSet<unsigned> &Regs,
                        const TargetRegisterInfo *TRI) {
  assert(!TargetRegisterInfo::isVirtualRegister(Reg) && "only for physregs");
  for (const uint16_t *Alias = TRI->getOverlaps(Reg); *Alias; ++Alias) {
    if (Regs.count(*Alias))
      return true;
  }
  return false;
}
Esempio n. 8
0
    void mouseDrag (const MouseEvent& e)
    {
        if (isEnabled() && owner.getModel() != nullptr && ! (e.mouseWasClicked() || isDragging))
        {
            const SparseSet<int> selectedRows (owner.getSelectedRows());

            if (selectedRows.size() > 0)
            {
                const var dragDescription (owner.getModel()->getDragSourceDescription (selectedRows));

                if (! (dragDescription.isVoid() || (dragDescription.isString() && dragDescription.toString().isEmpty())))
                {
                    isDragging = true;
                    owner.startDragAndDrop (e, dragDescription);
                }
            }
        }
    }
var RemoteDirectoryListBoxModel::getDragSourceDescription (const SparseSet<int> &currentlySelectedRows)
{
	if (currentlySelectedRows.size() > 0) {
        String path (curlSession->getRemotePath().upToLastOccurrenceOf ("/", true, false) + itemList[currentlySelectedRows[0]]);

		return path;
	}
	
	return String::empty;
}
Esempio n. 10
0
    //==============================================================================
    void selectedRowsChanged (int) override
    {
        SparseSet<int> newSelectedItems = getSelectedRows();
        if (newSelectedItems != lastSelectedItems)
        {
            for (int i = 0; i < lastSelectedItems.size(); ++i)
            {
                if (! newSelectedItems.contains (lastSelectedItems[i]))
                    parent.closeDevice (isInput, lastSelectedItems[i]);
            }

            for (int i = 0; i < newSelectedItems.size(); ++i)
            {
                if (! lastSelectedItems.contains (newSelectedItems[i]))
                    parent.openDevice (isInput, newSelectedItems[i]);
            }

            lastSelectedItems = newSelectedItems;
        }
    }
Esempio n. 11
0
    var getDragSourceDescription (const SparseSet<int>& selectedRows)
    {
        // for our drag desctription, we'll just make a list of the selected
        // row numbers - this will be picked up by the drag target and displayed in
        // its box.
        String desc;

        for (int i = 0; i < selectedRows.size(); ++i)
            desc << (selectedRows [i] + 1) << " ";

        return desc.trim();
    }
    void mouseDrag (const MouseEvent& e) override
    {
        if (isEnabled() && owner.getModel() != nullptr && ! (e.mouseWasClicked() || isDragging))
        {
            SparseSet<int> rowsToDrag;

            if (owner.selectOnMouseDown || owner.isRowSelected (row))
                rowsToDrag = owner.getSelectedRows();
            else
                rowsToDrag.addRange (Range<int>::withStartAndLength (row, 1));

            if (rowsToDrag.size() > 0)
            {
                const var dragDescription (owner.getModel()->getDragSourceDescription (rowsToDrag));

                if (! (dragDescription.isVoid() || (dragDescription.isString() && dragDescription.toString().isEmpty())))
                {
                    isDragging = true;
                    owner.startDragAndDrop (e, rowsToDrag, dragDescription, true);
                }
            }
        }
    }
Esempio n. 13
0
void Image::createSolidAreaMask (RectangleList& result, const float alphaThreshold) const
{
    if (hasAlphaChannel())
    {
        const uint8 threshold = (uint8) jlimit (0, 255, roundToInt (alphaThreshold * 255.0f));
        SparseSet<int> pixelsOnRow;

        const BitmapData srcData (*this, 0, 0, getWidth(), getHeight());

        for (int y = 0; y < srcData.height; ++y)
        {
            pixelsOnRow.clear();
            const uint8* lineData = srcData.getLinePointer (y);

            if (isARGB())
            {
                for (int x = 0; x < srcData.width; ++x)
                {
                    if (((const PixelARGB*) lineData)->getAlpha() >= threshold)
                        pixelsOnRow.addRange (Range<int> (x, x + 1));

                    lineData += srcData.pixelStride;
                }
            }
            else
            {
                for (int x = 0; x < srcData.width; ++x)
                {
                    if (*lineData >= threshold)
                        pixelsOnRow.addRange (Range<int> (x, x + 1));

                    lineData += srcData.pixelStride;
                }
            }

            for (int i = 0; i < pixelsOnRow.getNumRanges(); ++i)
            {
                const Range<int> range (pixelsOnRow.getRange (i));
                result.add (Rectangle<int> (range.getStart(), y, range.getLength(), 1));
            }

            result.consolidate();
        }
    }
    else
    {
        result.add (0, 0, getWidth(), getHeight());
    }
}
Esempio n. 14
0
void MappingsDialog::buttonClicked (Button* buttonThatWasClicked)
{
    //[UserbuttonClicked_Pre]
    //[/UserbuttonClicked_Pre]

    if (buttonThatWasClicked == addMidiButton)
    {
        //[UserButtonCode_addMidiButton] -- add your button handler code here..

		MidiMapping *mapping = new MidiMapping(midiManager,
											   pluginField->getFilterGraph(),
											   pluginNode->nodeId,
											   0,
											   0,
											   false,
											   0.0f,
											   1.0f);
		midiManager->registerMapping(0, mapping);
		mappings.add(mapping);
		pluginField->addMapping(mapping);
		mappingsList->updateContent();
		repaint();

        //[/UserButtonCode_addMidiButton]
    }
    else if (buttonThatWasClicked == addOscButton)
    {
        //[UserButtonCode_addOscButton] -- add your button handler code here..

		OscMapping *mapping = new OscMapping(oscManager,
											 pluginField->getFilterGraph(),
											 pluginNode->nodeId,
											 0,
											 "",
											 0);
		oscManager->registerMapping("", mapping);
		mappings.add(mapping);
		pluginField->addMapping(mapping);
		mappingsList->updateContent();
		repaint();

        //[/UserButtonCode_addOscButton]
    }
    else if (buttonThatWasClicked == deleteButton)
    {
        //[UserButtonCode_deleteButton] -- add your button handler code here..

		int i;
		Array<int> mappingsToDelete;
		const SparseSet<int> selectedRows = mappingsList->getSelectedRows();

		for(i=0;i<selectedRows.size();++i)
		{
			jassert(selectedRows[i] < mappings.size());

			mappingsToDelete.add(selectedRows[i]);
		}

		mappingsToDelete.sort(comparator);
		for(i=(mappingsToDelete.size()-1);i>=0;--i)
		{
			pluginField->removeMapping(mappings[mappingsToDelete[i]]);
			mappings.remove(mappingsToDelete[i]);
		}

		mappingsList->updateContent();

        //[/UserButtonCode_deleteButton]
    }
    else if (buttonThatWasClicked == overrideMidiButton)
    {
        //[UserButtonCode_overrideMidiButton] -- add your button handler code here..

		pluginField->enableMidiForNode(pluginNode,
									   overrideMidiButton->getToggleState());

        //[/UserButtonCode_overrideMidiButton]
    }

    //[UserbuttonClicked_Post]
    //[/UserbuttonClicked_Post]
}
Esempio n. 15
0
void MainContentComponent::buttonClicked (Button* buttonThatWasClicked)
{
    //[UserbuttonClicked_Pre]
    //[/UserbuttonClicked_Pre]

    if (buttonThatWasClicked == convButton)
    {
        //[UserButtonCode_convButton] -- add your button handler code here..
		const ScopedLock fl(soundListLock);

		setPlayheadUiEnabled(false);

		bool convValid = true;

		float q;
		float s;
		double nfft;
		{
			const ScopedLock pl(paramLock);
			q = qParam;
			s = sParam;
			nfft = static_cast<double>(nfftParam);
		}

		int fftInputLen = static_cast<int>(std::pow(2.0, nfft));
		int fftOutputLen = fftInputLen / 2 + 1;
		int numChannels = 1;

		unordered_set<int> includedSounds;
		int maxChannels = 0;
		float pSum = 0.0f;
		float rSum = 0.0f;
		for (const auto& iter : idToSound) {
			int id = iter.first;
			Sound* sound = iter.second.get();
			int numChannels = sound->getBufferNumChannels();
			if (sound->isIncluded() && numChannels > 0) {
				maxChannels = numChannels > maxChannels ? numChannels : maxChannels;
				includedSounds.emplace(id);
				pSum += static_cast<float>(sound->getPValue());
				rSum += static_cast<float>(sound->getRValue());
			}
		}
		float n = static_cast<float>(includedSounds.size());
		float pScale = n * q / pSum;
		float rScale = n * s / rSum;

		if (maxChannels == 0) {
			return;
		}

		kiss_fftr_state* fftInverseState = kiss_fftr_alloc(fftInputLen, 1, nullptr, nullptr);
		kiss_fft_cpx* CONV = static_cast<kiss_fft_cpx*>(calloc(fftOutputLen * maxChannels, sizeof(kiss_fft_cpx)));
		conv.setSize(maxChannels, fftInputLen);

		float max = -1.0f;

		// convolve
		for (int convChannel = 0; convChannel < maxChannels; ++convChannel) {
			kiss_fft_cpx* CONVCHANNEL = CONV + (convChannel * fftOutputLen);

			bool isFirstSound = true;
			for (const auto& id : includedSounds) {
				Sound* sound = idToSound[id].get();
				jassert(sound != nullptr);
				float p = pScale * static_cast<float>(sound->getPValue());
				float r = rScale * static_cast<float>(sound->getRValue());
				int soundNumChannels = sound->getBufferNumChannels();
				int soundNumSamples = sound->getBufferNumSamples();
				int soundChannel = convChannel >= soundNumChannels ? soundNumChannels - 1 : convChannel;
				const kiss_fft_cpx* SOUNDCHANNEL = sound->getSpectra(fftInputLen, soundChannel);

				for (int i = 0; i < fftOutputLen; ++i) {
					float xr = SOUNDCHANNEL[i].r;
					float xi = SOUNDCHANNEL[i].i;
					float xMag = sqrtf((xr * xr) + (xi * xi));
					float xPhs = atan2f(xi, xr);
					float convMag = powf(xMag, p);
					float convPhs = r * xPhs;
					float convr = convMag * cosf(convPhs);
					float convi = convMag * sinf(convPhs);

					if (std::isnan(convr) || std::isnan(convi)) {
						convValid = false;
					}

					if (isFirstSound) {
						CONVCHANNEL[i].r = convr;
						CONVCHANNEL[i].i = convi;
					}
					else {
						float a = CONVCHANNEL[i].r;
						float b = CONVCHANNEL[i].i;
						float c = convr;
						float d = convi;
						CONVCHANNEL[i].r = a * c - b * d;
						CONVCHANNEL[i].i = a * d + b * c;
					}
				}

				isFirstSound = false;
			}

			// ifft
			kiss_fftri(fftInverseState, CONVCHANNEL, conv.getWritePointer(convChannel));

			// check max
			float channelMax = conv.findMinMax(convChannel, 0, fftInputLen).getEnd();
			max = channelMax > max ? channelMax : max;
		}

		delete fftInverseState;
		delete CONV;

		// normalize
		conv.applyGain(1.0f / max);

		if (!convValid) {
			AlertWindow::showMessageBoxAsync(AlertWindow::WarningIcon, "Error", "Parameters produced NaN value.");
			return;
		}

		setPlayheadAudio(&conv);
        //[/UserButtonCode_convButton]
    }
    else if (buttonThatWasClicked == settingsButton)
    {
        //[UserButtonCode_settingsButton] -- add your button handler code here..
		AudioDeviceSelectorComponent audioSettingsComp(deviceManager,
			0, 256,
			0, 256,
			true, true, true, false);

		audioSettingsComp.setSize(500, 450);

		DialogWindow::LaunchOptions o;
		o.content.setNonOwned(&audioSettingsComp);
		o.dialogTitle = "Audio Settings";
		o.componentToCentreAround = this;
		o.dialogBackgroundColour = Colours::azure;
		o.escapeKeyTriggersCloseButton = true;
		o.useNativeTitleBar = false;
		o.resizable = false;

		o.runModal();

		ScopedPointer<XmlElement> audioState(deviceManager.createStateXml());

		getAppProperties().getUserSettings()->setValue("audioDeviceState", audioState);
		getAppProperties().getUserSettings()->saveIfNeeded();
        //[/UserButtonCode_settingsButton]
    }
    else if (buttonThatWasClicked == playButton)
    {
        //[UserButtonCode_playButton] -- add your button handler code here..
		const ScopedLock pal(playheadAudioLock);
		playheadState = PlayheadState::playing;
		playheadAudioSamplesCompleted = 0;
        //[/UserButtonCode_playButton]
    }
    else if (buttonThatWasClicked == loopButton)
    {
        //[UserButtonCode_loopButton] -- add your button handler code here..
		const ScopedLock pal(playheadAudioLock);
		playheadState = PlayheadState::looping;
        //[/UserButtonCode_loopButton]
    }
    else if (buttonThatWasClicked == stopButton)
    {
        //[UserButtonCode_stopButton] -- add your button handler code here..
		const ScopedLock pal(playheadAudioLock);
		playheadState = PlayheadState::stopped;
		playheadAudioSamplesCompleted = 0;
        //[/UserButtonCode_stopButton]
    }
    else if (buttonThatWasClicked == qDefaultButton)
    {
        //[UserButtonCode_qDefaultButton] -- add your button handler code here..
		qSlider->setValue(1.0);
        //[/UserButtonCode_qDefaultButton]
    }
    else if (buttonThatWasClicked == sDefaultButton)
    {
        //[UserButtonCode_sDefaultButton] -- add your button handler code here..
		sSlider->setValue(1.0);
        //[/UserButtonCode_sDefaultButton]
    }
    else if (buttonThatWasClicked == saveButton)
    {
        //[UserButtonCode_saveButton] -- add your button handler code here..
		const ScopedLock pal(playheadAudioLock);

		if (playheadAudio.getNumChannels() > 0 && playheadAudio.getNumSamples() > 0) {
			FileChooser fileChooser("Save as...", File::nonexistent, "*.wav", true);
			if (fileChooser.browseForFileToSave(true)) {
				File outputFile = fileChooser.getResult();
				outputFile.deleteFile();
				WavAudioFormat wavFormat;
				ScopedPointer<FileOutputStream> outputFileStream = outputFile.createOutputStream();
				ScopedPointer<AudioFormatWriter> writer = wavFormat.createWriterFor(outputFileStream, 44100.0, playheadAudio.getNumChannels(), 16, StringPairArray(), 0);
				writer->writeFromAudioSampleBuffer(playheadAudio, 0, playheadAudio.getNumSamples());
				outputFileStream.release();
			}
		}
        //[/UserButtonCode_saveButton]
    }
    else if (buttonThatWasClicked == inputRemoveButton)
    {
        //[UserButtonCode_inputRemoveButton] -- add your button handler code here..
		const ScopedLock fl(soundListLock);
		SparseSet<int> selectedRows = inputFileListComponent->getSelectedRows();
		for (int i = 0; i < selectedRows.size(); ++i) {
			int row = selectedRows[i];
			int id = inputFileListComponent->getIdForRow(row);
			const auto& iter = idToSound.find(id);
			jassert(iter != idToSound.end());
			idToSound.erase(iter);
		}
		if (selectedRows.size() > 0) {
			inputFilesChanged(dontSendNotification);
		}
        //[/UserButtonCode_inputRemoveButton]
    }
    else if (buttonThatWasClicked == inputAddButton)
    {
        //[UserButtonCode_inputAddButton] -- add your button handler code here..
		const ScopedLock fl(soundListLock);
		FileChooser fileChooser("Add sound...", File::nonexistent, "*.wav;*.aif;*.aiff;*.ogg", true);
		if (fileChooser.browseForMultipleFilesToOpen()) {
			Array<File> files = fileChooser.getResults();
			StringArray filePaths;
			for (int i = 0; i < files.size(); ++i) {
				filePaths.add(files[i].getFullPathName());
			}
			filesDropped(filePaths, -1, -1);
		}
        //[/UserButtonCode_inputAddButton]
    }

    //[UserbuttonClicked_Post]
    //[/UserbuttonClicked_Post]
}
Esempio n. 16
0
void CDPlayer::timerCallback()
{
    m_digitalDisplay.setText(Utils::formatSeconds(m_transportSource.getCurrentPosition()), sendNotification);

    int64 currentSample = m_source->getNextReadPosition();

    const Array<int>& offsets = m_reader->getTrackOffsets();
    // offsets[0] != 0 is possible, there might be a track before the first.
    // offsets.getLast() is not the start of the last track but the end sample of the CD.

    if (currentSample < offsets[0])
    {
        // We are before the first track.
        m_slider.setEnabled(false);
        m_slider.setValue(m_slider.getMinimum(), juce::dontSendNotification);
        m_currentTrack = -1;
        SparseSet<int> rows;
        m_tracksTable.setSelectedRows(rows, juce::dontSendNotification);
        return;
    }

    if (m_currentTrack == -1)
    {
        // We have now entered the first track.
        m_slider.setEnabled(true);
        m_slider.setRange(offsets[0], offsets[1]);
        // Possible loss of precision is acceptable for very large values because user can't select specific value that precise.
        m_slider.setValue(static_cast<double>(currentSample), juce::dontSendNotification);
        m_currentTrack = 0;
        m_pluginLoader.playlistEntrySelected(getName().toRawUTF8(), m_currentTrack);
        SparseSet<int> rows;
        rows.addRange(Range<int>(m_currentTrack, m_currentTrack + 1));
        m_tracksTable.setSelectedRows(rows, juce::dontSendNotification);
        return;
    }

    jassert(m_currentTrack + 1 < offsets.size());

    if (currentSample >= offsets[m_currentTrack] && currentSample < offsets[m_currentTrack + 1])
    {
        // We are still within the current track (usual case).
        // Possible loss of precision is acceptable for very large values because user can't select specific value that precise.
        m_slider.setValue(static_cast<double>(currentSample), juce::dontSendNotification);
        return;
    }

    // We are within another track.

    int64 firstSample = -1;
    int64 lastSample = -1;

    if (currentSample < offsets[m_currentTrack])
    {
        // We are before the curren track. Search backward to find the track our sample position now lies within.

        // Assume our current track is the immediately preceeding track.
        jassert(m_currentTrack - 1 >= 0);
        firstSample = -1;
        lastSample = offsets[m_currentTrack];

        for (int probeTrack = m_currentTrack - 1; probeTrack >= 0; --probeTrack)
        {
            if (currentSample >= offsets[probeTrack])
            {
                m_currentTrack = probeTrack;
                firstSample = offsets[probeTrack];
                break; // We are at the previous track.
            }

            lastSample = offsets[probeTrack];
        }

        m_pluginLoader.previousEntrySelected(getName().toRawUTF8());
        m_pluginLoader.playlistEntrySelected(getName().toRawUTF8(), m_currentTrack);
    }

    if (currentSample >= offsets[m_currentTrack + 1])
    {
        // We are after the curren track. Search forward to find the track our sample position now lies within.

        // Assume our current track is the immediately following track.
        jassert(m_currentTrack + 2 < offsets.size());
        firstSample = offsets[m_currentTrack + 1];
        lastSample = -1;

        for (int probeTrack = m_currentTrack + 2; probeTrack < offsets.size(); ++probeTrack)
        {
            if (offsets[probeTrack] > currentSample)
            {
                m_currentTrack = probeTrack - 1;
                lastSample = offsets[probeTrack];
                break; // We are at the next track.
            }

            firstSample = offsets[probeTrack];
        }

        m_pluginLoader.nextEntrySelected(getName().toRawUTF8());
        m_pluginLoader.playlistEntrySelected(getName().toRawUTF8(), m_currentTrack);
    }

    jassert(currentSample >= firstSample);
    jassert(currentSample < lastSample);

    // Possible loss of precision is acceptable for very large values because user can't select specific value that precise.
    m_slider.setRange(static_cast<double>(firstSample), static_cast<double>(lastSample));
    m_slider.setValue(static_cast<double>(currentSample), juce::dontSendNotification);
    SparseSet<int> rows;
    rows.addRange(Range<int>(m_currentTrack, m_currentTrack + 1));
    m_tracksTable.setSelectedRows(rows, juce::dontSendNotification);
    m_pluginLoader.positionChanged(getName().toRawUTF8(), m_transportSource.getCurrentPosition());
}
void PluginListComponent::buttonClicked (Button* b)
{
    if (optionsButton == b)
    {
        PopupMenu menu;
        menu.addItem (1, TRANS("Clear list"));
        menu.addItem (5, TRANS("Remove selected plugin from list"), listBox->getNumSelectedRows() > 0);
        menu.addItem (6, TRANS("Show folder containing selected plugin"), listBox->getNumSelectedRows() > 0);
        menu.addItem (7, TRANS("Remove any plugins whose files no longer exist"));
        menu.addSeparator();
        menu.addItem (2, TRANS("Sort alphabetically"));
        menu.addItem (3, TRANS("Sort by category"));
        menu.addItem (4, TRANS("Sort by manufacturer"));
        menu.addSeparator();

        for (int i = 0; i < AudioPluginFormatManager::getInstance()->getNumFormats(); ++i)
        {
            AudioPluginFormat* const format = AudioPluginFormatManager::getInstance()->getFormat (i);

            if (format->getDefaultLocationsToSearch().getNumPaths() > 0)
                menu.addItem (10 + i, "Scan for new or updated " + format->getName() + " plugins...");
        }

        const int r = menu.showAt (optionsButton);

        if (r == 1)
        {
            list.clear();
        }
        else if (r == 2)
        {
            list.sort (KnownPluginList::sortAlphabetically);
        }
        else if (r == 3)
        {
            list.sort (KnownPluginList::sortByCategory);
        }
        else if (r == 4)
        {
            list.sort (KnownPluginList::sortByManufacturer);
        }
        else if (r == 5)
        {
            const SparseSet <int> selected (listBox->getSelectedRows());

            for (int i = list.getNumTypes(); --i >= 0;)
                if (selected.contains (i))
                    list.removeType (i);
        }
        else if (r == 6)
        {
            const PluginDescription* const desc = list.getType (listBox->getSelectedRow());

            if (desc != 0)
            {
                if (File (desc->fileOrIdentifier).existsAsFile())
                    File (desc->fileOrIdentifier).getParentDirectory().startAsProcess();
            }
        }
        else if (r == 7)
        {
            for (int i = list.getNumTypes(); --i >= 0;)
            {
                if (! AudioPluginFormatManager::getInstance()->doesPluginStillExist (*list.getType (i)))
                {
                    list.removeType (i);
                }
            }
        }
        else if (r != 0)
        {
            typeToScan = r - 10;
            startTimer (1);
        }
    }
}