//==============================================================================
void LowLevelGraphicsPostScriptRenderer::writeImage (const Image& im,
                                                     const int sx, const int sy,
                                                     const int maxW, const int maxH) const
{
    out << "{<\n";

    const int w = jmin (maxW, im.getWidth());
    const int h = jmin (maxH, im.getHeight());

    int charsOnLine = 0;
    const Image::BitmapData srcData (im, 0, 0, w, h);
    Colour pixel;

    for (int y = h; --y >= 0;)
    {
        for (int x = 0; x < w; ++x)
        {
            const uint8* pixelData = srcData.getPixelPointer (x, y);

            if (x >= sx && y >= sy)
            {
                if (im.isARGB())
                {
                    PixelARGB p (*(const PixelARGB*) pixelData);
                    p.unpremultiply();
                    pixel = Colours::white.overlaidWith (Colour (p.getARGB()));
                }
                else if (im.isRGB())
                {
                    pixel = Colour (((const PixelRGB*) pixelData)->getARGB());
                }
                else
                {
                    pixel = Colour ((uint8) 0, (uint8) 0, (uint8) 0, *pixelData);
                }
            }
            else
            {
                pixel = Colours::transparentWhite;
            }

            const uint8 pixelValues[3] = { pixel.getRed(), pixel.getGreen(), pixel.getBlue() };

            out << String::toHexString (pixelValues, 3, 0);
            charsOnLine += 3;

            if (charsOnLine > 100)
            {
                out << '\n';
                charsOnLine = 0;
            }
        }
    }

    out << "\n>}\n";
}
Example #2
0
XYZColour const XYZColour::from (Colour const& sRGB)
{
  float r = sRGB.getRed   () / 255.f;
  float g = sRGB.getGreen () / 255.f;
  float b = sRGB.getBlue  () / 255.f;

  if (r > 0.04045f) r = 100.f * pow ((r + 0.055f) / 1.055f, 2.4f); else r = r / 12.92f;
  if (g > 0.04045f) g = 100.f * pow ((g + 0.055f) / 1.055f, 2.4f); else g = g / 12.92f;
  if (b > 0.04045f) b = 100.f * pow ((b + 0.055f) / 1.055f, 2.4f); else b = b / 12.92f;

  // D65
  float x = r * 0.4124f + g * 0.3576f + b * 0.1805f;
  float y = r * 0.2126f + g * 0.7152f + b * 0.0722f;
  float z = r * 0.0193f + g * 0.1192f + b * 0.9505f;

  return XYZColour (x, y, z, sRGB.getAlpha() / 255.f);
}
Example #3
0
void ProcessorList::saveStateToXml(XmlElement* xml)
{
    XmlElement* processorListState = xml->createNewChildElement("PROCESSORLIST");

    for (int i = 0; i < 5; i++)
    {
        XmlElement* colorState = processorListState->createNewChildElement("COLOR");

        int id;

        switch (i)
        {
            case 0:
                id = PROCESSOR_COLOR;
                break;
            case 1:
                id = SOURCE_COLOR;
                break;
            case 2:
                id = FILTER_COLOR;
                break;
            case 3:
                id = SINK_COLOR;
                break;
            case 4:
                id = UTILITY_COLOR;
                break;
            default:
                // do nothing
                ;
        }

        Colour c = findColour(id);

        colorState->setAttribute("ID", (int) id);
        colorState->setAttribute("R", (int) c.getRed());
        colorState->setAttribute("G", (int) c.getGreen());
        colorState->setAttribute("B", (int) c.getBlue());

    }
}
Example #4
0
bool JPEGImageFormat::writeImageToStream (const Image& image, OutputStream& out)
{
    using namespace jpeglibNamespace;
    using namespace JPEGHelpers;

    struct jpeg_compress_struct jpegCompStruct;
    jpeg_create_compress (&jpegCompStruct);

    struct jpeg_error_mgr jerr;
    setupSilentErrorHandler (jerr);
    jpegCompStruct.err = &jerr;

    JuceJpegDest dest;
    jpegCompStruct.dest = &dest;

    dest.output = &out;
    HeapBlock <char> tempBuffer (jpegBufferSize);
    dest.buffer = tempBuffer;
    dest.next_output_byte = (JOCTET*) dest.buffer;
    dest.free_in_buffer = jpegBufferSize;
    dest.init_destination = jpegWriteInit;
    dest.empty_output_buffer = jpegWriteFlush;
    dest.term_destination = jpegWriteTerminate;

    jpegCompStruct.image_width  = (JDIMENSION) image.getWidth();
    jpegCompStruct.image_height = (JDIMENSION) image.getHeight();
    jpegCompStruct.input_components = 3;
    jpegCompStruct.in_color_space = JCS_RGB;
    jpegCompStruct.write_JFIF_header = 1;

    jpegCompStruct.X_density = 72;
    jpegCompStruct.Y_density = 72;

    jpeg_set_defaults (&jpegCompStruct);

    jpegCompStruct.dct_method = JDCT_FLOAT;
    jpegCompStruct.optimize_coding = 1;

    if (quality < 0.0f)
        quality = 0.85f;

    jpeg_set_quality (&jpegCompStruct, jlimit (0, 100, roundToInt (quality * 100.0f)), TRUE);

    jpeg_start_compress (&jpegCompStruct, TRUE);

    const int strideBytes = (int) (jpegCompStruct.image_width * jpegCompStruct.input_components);

    JSAMPARRAY buffer = (*jpegCompStruct.mem->alloc_sarray) ((j_common_ptr) &jpegCompStruct,
                                                             JPOOL_IMAGE, (JDIMENSION) strideBytes, 1);

    const Image::BitmapData srcData (image, Image::BitmapData::readOnly);

    while (jpegCompStruct.next_scanline < jpegCompStruct.image_height)
    {
        uint8* dst = *buffer;

        if (srcData.pixelFormat == Image::RGB)
        {
            const uint8* src = srcData.getLinePointer ((int) jpegCompStruct.next_scanline);

            for (int i = srcData.width; --i >= 0;)
            {
                *dst++ = ((const PixelRGB*) src)->getRed();
                *dst++ = ((const PixelRGB*) src)->getGreen();
                *dst++ = ((const PixelRGB*) src)->getBlue();
                src += srcData.pixelStride;
            }
        }
        else
        {
            for (int x = 0; x < srcData.width; ++x)
            {
                const Colour pixel (srcData.getPixelColour (x, (int) jpegCompStruct.next_scanline));
                *dst++ = pixel.getRed();
                *dst++ = pixel.getGreen();
                *dst++ = pixel.getBlue();
            }
        }

        jpeg_write_scanlines (&jpegCompStruct, buffer, 1);
    }

    jpeg_finish_compress (&jpegCompStruct);
    jpeg_destroy_compress (&jpegCompStruct);

    return true;
}
Example #5
0
void
MidiMixerWindow::setupTabs()
{
    DeviceListConstIterator it;
    MidiDevice *dev = 0;
    InstrumentList instruments;
    InstrumentList::const_iterator iIt;
    int faderCount = 0, deviceCount = 1;

    if (m_tabFrame)
        delete m_tabFrame;

    // Setup m_tabFrame
    //

    QWidget *blackWidget = new QWidget(this);
    setCentralWidget(blackWidget);
    QVBoxLayout *centralLayout = new QVBoxLayout;
    blackWidget->setLayout(centralLayout);

    m_tabWidget = new QTabWidget;
    centralLayout->addWidget(m_tabWidget);

    connect(m_tabWidget, SIGNAL(currentChanged(QWidget *)),
            this, SLOT(slotCurrentTabChanged(QWidget *)));
    m_tabWidget->setTabPosition(QTabWidget::South);
    setWindowTitle(tr("MIDI Mixer"));
    setWindowIcon(IconLoader().loadPixmap("window-midimixer"));


    for (it = m_studio->begin(); it != m_studio->end(); ++it) {
        dev = dynamic_cast<MidiDevice*>(*it);

        if (dev) {
            // Get the control parameters that are on the IPB (and hence can
            // be shown here too).
            //
            ControlList controls = getIPBForMidiMixer(dev);

            instruments = dev->getPresentationInstruments();

            // Don't add a frame for empty devices
            //
            if (!instruments.size())
                continue;

            m_tabFrame = new QFrame(m_tabWidget);
            m_tabFrame->setContentsMargins(10, 10, 10, 10);

            // m_tabFrame->setContentsMargins(5, 5, 5, 5); ???
            QGridLayout *mainLayout = new QGridLayout(m_tabFrame);

            // MIDI Mixer label
            QLabel *label = new QLabel("", m_tabFrame);
            mainLayout->addWidget(label, 0, 0, 0, 16, Qt::AlignCenter);

            // control labels
            for (size_t i = 0; i < controls.size(); ++i) {
                label = new QLabel(QObject::tr(controls[i].getName().c_str()), m_tabFrame);
                mainLayout->addWidget(label, i + 1, 0, Qt::AlignCenter);
            }

            // meter label
            // (obsolete abandoned code deleted here)

            // volume label
            label = new QLabel(tr("Volume"), m_tabFrame);
            mainLayout->addWidget(label, controls.size() + 2, 0,
                                  Qt::AlignCenter);

            // instrument label
            label = new QLabel(tr("Instrument"), m_tabFrame);
            label->setFixedWidth(80); //!!! this should come from metrics
            mainLayout->addWidget(label, controls.size() + 3, 0,
                                  Qt::AlignLeft);

            int posCount = 1;
            int firstInstrument = -1;

            for (iIt = instruments.begin(); iIt != instruments.end(); ++iIt) {

                // Add new fader struct
                //
                m_faders.push_back(new FaderStruct());

                // Store the first ID
                //
                if (firstInstrument == -1)
                    firstInstrument = (*iIt)->getId();


                // Add the controls
                //
                for (size_t i = 0; i < controls.size(); ++i) {
                    QColor knobColour = QColor(Qt::white);

                    if (controls[i].getColourIndex() > 0) {
                        Colour c =
                            m_document->getComposition().getGeneralColourMap().
                            getColourByIndex(controls[i].getColourIndex());

                        knobColour = QColor(c.getRed(),
                                            c.getGreen(), c.getBlue());
                    }

                    Rotary *controller =
                        new Rotary(m_tabFrame,
                                   controls[i].getMin(),
                                   controls[i].getMax(),
                                   1.0,
                                   5.0,
                                   controls[i].getDefault(),
                                   20,
                                   Rotary::NoTicks,
                                   false,
                                   controls[i].getDefault() == 64); //!!! hacky

                    controller->setKnobColour(knobColour);

                    connect(controller, SIGNAL(valueChanged(float)),
                            this, SLOT(slotControllerChanged(float)));

                    mainLayout->addWidget(controller, i + 1, posCount,
                                          Qt::AlignCenter);

                    // Store the rotary
                    //
                    m_faders[faderCount]->m_controllerRotaries.push_back(
                        std::pair<MidiByte, Rotary*>
                        (controls[i].getControllerValue(), controller));
                }

                // VU meter
                //
                MidiMixerVUMeter *meter =
                    new MidiMixerVUMeter(m_tabFrame,
                                         VUMeter::FixedHeightVisiblePeakHold, 6, 30);
                mainLayout->addWidget(meter, controls.size() + 1,
                                      posCount, Qt::AlignCenter);
                m_faders[faderCount]->m_vuMeter = meter;

                // Volume fader
                //
                Fader *fader =
                    new Fader(0, 127, 100, 20, 80, m_tabFrame);
                mainLayout->addWidget(fader, controls.size() + 2,
                                      posCount, Qt::AlignCenter);
                m_faders[faderCount]->m_volumeFader = fader;

                // Label
                //
                QLabel *idLabel = new QLabel(QString("%1").
                                             arg((*iIt)->getId() - firstInstrument + 1),
                                             m_tabFrame);
                idLabel->setObjectName("idLabel");

                mainLayout->addWidget(idLabel, controls.size() + 3,
                                      posCount, Qt::AlignCenter);

                // store id in struct
                m_faders[faderCount]->m_id = (*iIt)->getId();

                // Connect them up
                //
                connect(fader, SIGNAL(faderChanged(float)),
                        this, SLOT(slotFaderLevelChanged(float)));

                // Update all the faders and controllers
                //
                slotUpdateInstrument((*iIt)->getId());

                // Increment counters
                //
                posCount++;
                faderCount++;
            }

            QString name = QString("%1 (%2)")
                           .arg(QObject::tr(dev->getName().c_str()))
                           .arg(deviceCount++);

            addTab(m_tabFrame, name);
        }
    }
}
void
ControlEditorDialog::slotUpdate(bool added)
{
    RG_DEBUG << "ControlEditorDialog::slotUpdate" << endl;

    MidiDevice *md =
        dynamic_cast<MidiDevice *>(m_studio->getDevice(m_device));
    if (!md)
        return ;

    ControlList::const_iterator it = md->beginControllers();
    ControlParameterItem *item;
    int i = 0;

    // Attempt to track last controller selected so we can reselect it
    int lastControllerId = -1;
    ControlParameterItem *lastItem = dynamic_cast<ControlParameterItem *>(m_treeWidget->currentItem());
    if (lastItem) {
        lastControllerId = lastItem->getId();
    }
    
    m_treeWidget->clear();

    for (; it != md->endControllers(); ++it) {
        Composition &comp = m_doc->getComposition();

        QString colour =
            strtoqstr(comp.getGeneralColourMap().getNameByIndex(it->getColourIndex()));

        if (colour == "")
            colour = tr("<default>");

        QString position = QString("%1").arg(it->getIPBPosition());
        if (position.toInt() == -1)
            position = tr("<not showing>");

        QString value;
        value.sprintf("%d (0x%x)", it->getControllerValue(),
                      it->getControllerValue());

        if (it->getType() == PitchBend::EventType) {
            item = new ControlParameterItem(
                                            i++,
                                            m_treeWidget,
                                            QStringList()
                                                << strtoqstr(it->getName())
                                                << strtoqstr(it->getType())
                                                << QString("-")
                                                << strtoqstr(it->getDescription())
                                                << QString("%1").arg(it->getMin())
                                                << QString("%1").arg(it->getMax())
                                                << QString("%1").arg(it->getDefault())
                                                << colour
                                                << position 
                                          );
        } else {
            item = new ControlParameterItem(
                            i++,
                            m_treeWidget,
                            QStringList()
                                << strtoqstr(it->getName())
                                << strtoqstr(it->getType())
                                << value
                                << strtoqstr(it->getDescription())
                                << QString("%1").arg(it->getMin())
                                << QString("%1").arg(it->getMax())
                                << QString("%1").arg(it->getDefault())
                                << colour
                                << position
                           );
        }

        if (item->getId() == lastControllerId) {
            m_treeWidget->setCurrentItem(item);
        }


        // create and set a colour pixmap
        //
        QPixmap colourPixmap(16, 16);
        Colour c = comp.getGeneralColourMap().getColourByIndex(it->getColourIndex());
        colourPixmap.fill(QColor(c.getRed(), c.getGreen(), c.getBlue()));
        
        item->setIcon(7, QIcon(colourPixmap));

        m_treeWidget->addTopLevelItem(item);
    }

    if(m_treeWidget->topLevelItemCount() == 0) {
        QTreeWidgetItem *item = new QTreeWidgetItem(m_treeWidget, QStringList(tr("<none>")));
        m_treeWidget->addTopLevelItem(item);

        m_treeWidget->setSelectionMode(QAbstractItemView::NoSelection);
    } else {
        m_treeWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
    }
    
    // This logic is kind of frigged up, and may be too fragile.  It assumes
    // that if you added an item, the last thing iterated through will be that
    // new item, so the value of the variable item will be the last thing
    // iterated through, and therefore the newest item you just added and want
    // to edit.
    //
    // I got substantially far along the way to making this quick and dirty hack
    // work before I thought it would be a lot cleaner to have the
    // AddControlParameterCommand itself launch the dialog and allow the user to
    // edit the parameters before ever adding it to the list at all.  That would
    // be a lot cleaner, but it would also require going against the flow of how
    // this logic always worked, so it would require a lot more thought to
    // achieve the same end result that way.  Instead, I just used this hack
    // overloaded slotUpdate() to tell it when a new controller was added, so we
    // could grab it here and launch the dialog on the generic blah we just added
    // to the list right before this slot got called with the optional bool set
    // true.
    //
    // (so much for verbose comments being helpful...  I wrote that not too long
    // ago, and reading it now, I have NO fscking idea what I was talking about)
    //
    if (added) {
        RG_DEBUG << "ControlEditorDialog: detected new item entered; launching editor" << endl;
        m_treeWidget->setCurrentItem(item);
        slotEdit(item, 0);
    }
}
void
MIDIInstrumentParameterPanel::setupControllers(MidiDevice *md)
{
    RG_DEBUG << "setupControllers()";

    if (!md)
        return;

    // To cut down on flicker, we avoid destroying and recreating
    // widgets as far as possible here.  If a label already exists,
    // we just set its text; if a rotary exists, we only replace it
    // if we actually need a different one.

    Composition &comp = m_doc->getComposition();

    ControlList list = md->getControlParameters();

    // Sort by IPB position.
    std::sort(list.begin(), list.end(),
              ControlParameter::ControlPositionCmp());

    int count = 0;
    RotaryInfoVector::iterator rotaryIter = m_rotaries.begin();

    // For each controller
    for (ControlList::iterator it = list.begin();
            it != list.end(); ++it) {
        if (it->getIPBPosition() == -1)
            continue;

        // Get the knob colour (even if it's default, because otherwise it turns
        // black instead of the default color from the map!  it was here the
        // whole time, this simple!)
        //
        const Colour c = comp.getGeneralColourMap().getColourByIndex(
                it->getColourIndex());
        const QColor knobColour = QColor(c.getRed(), c.getGreen(), c.getBlue());

        Rotary *rotary = 0;

        // If the Rotary widgets have already been created, update them.
        if (rotaryIter != m_rotaries.end()) {

            // Update the controller number that is associated with the
            // existing rotary widget.

            rotaryIter->controller = it->getControllerValue();

            // Update the properties of the existing rotary widget.

            rotary = rotaryIter->rotary;

            rotary->setMinimum(it->getMin());
            rotary->setMaximum(it->getMax());
            // If the default is 64, then this is most likely a "centered"
            // control which should show its distance from the 12 o'clock
            // position around the outside.
            rotary->setCentered((it->getDefault() == 64));
            rotary->setKnobColour(knobColour);

            // Update the controller name.
            rotaryIter->label->setText(QObject::tr(it->getName().c_str()));

            // Next Rotary widget
            ++rotaryIter;

        } else {  // Need to create the Rotary widget.

            // Create a horizontal box for the Rotary/Label pair.
            QWidget *hbox = new QWidget(m_rotaryFrame);
            QHBoxLayout *hboxLayout = new QHBoxLayout;
            hboxLayout->setSpacing(8);
            hboxLayout->setMargin(0);
            hbox->setLayout(hboxLayout);

            // Add a Rotary

            float pageStep = 5.0;
            if (it->getMax() - it->getMin() < 10)
                pageStep = 1.0;
            else if (it->getMax() - it->getMin() < 20)
                pageStep = 2.0;

            rotary = new Rotary(hbox,          // parent
                                it->getMin(),  // minimum
                                it->getMax(),  // maximum
                                1.0,           // step
                                pageStep,      // pageStep
                                it->getDefault(),  // initialPosition
                                20,                // size
                                Rotary::NoTicks,   // ticks
                                false,             // snapToTicks
                                (it->getDefault() == 64));  // centred, see setCentered() above
            rotary->setKnobColour(knobColour);
            hboxLayout->addWidget(rotary);

            // Add a label

            SqueezedLabel *label = new SqueezedLabel(QObject::tr(it->getName().c_str()), hbox);
            label->setFont(font());
            hboxLayout->addWidget(label);

            RG_DEBUG << "setupControllers(): Adding new widget at " << (count / 2) << "," << (count % 2);

            // Add the compound (Rotary and Label) widget to the grid.
            m_rotaryGrid->addWidget(hbox, count / 2, (count % 2) * 2, Qt::AlignLeft);
            hbox->show();

            // Add to the Rotary info list
            RotaryInfo ri;
            ri.rotary = rotary;
            ri.label = label;
            ri.controller = it->getControllerValue();
            m_rotaries.push_back(ri);

            // Connect for changes to the Rotary by the user.
            connect(rotary, SIGNAL(valueChanged(float)),
                    m_rotaryMapper, SLOT(map()));

            rotaryIter = m_rotaries.end();
        }

        // Add signal mapping
        //
        m_rotaryMapper->setMapping(rotary,
                                   int(it->getControllerValue()));

        ++count;
    }

    // If there are more rotary widgets than this instrument needs,
    // delete them.
    if (rotaryIter != m_rotaries.end()) {
        for (RotaryInfoVector::iterator it = rotaryIter; it != m_rotaries.end(); ++it) {
            // ??? Instead of deleting and recreating, we could hide the
            //     extras and bring them back when needed.
            delete it->rotary;
            delete it->label;
        }
        m_rotaries.resize(count);
    }
}
ControlParameterEditDialog::ControlParameterEditDialog(
    QWidget *parent,
    ControlParameter *control,
    RosegardenDocument *doc):
        QDialog(parent),
        m_doc(doc),
        m_control(control)
{
    m_dialogControl = *control; // copy in the ControlParameter

    setModal(true);
    setWindowTitle(tr("Edit Controller"));

    QGridLayout *metagrid = new QGridLayout;
    setLayout(metagrid);
    QWidget *vbox = new QWidget(this);
    QVBoxLayout *vboxLayout = new QVBoxLayout;
    metagrid->addWidget(vbox, 0, 0);


    QGroupBox *frame = new QGroupBox(tr("Controller Properties"), vbox);
    vboxLayout->addWidget(frame);
    vbox->setLayout(vboxLayout);
    frame->setContentsMargins(10, 10, 10, 10);
    QGridLayout *layout = new QGridLayout(frame);
    layout->setSpacing(5);

    layout->addWidget(new QLabel(tr("Name:"), frame), 0, 0);
    m_nameEdit = new LineEdit(frame);

    layout->addWidget(m_nameEdit, 0, 1, 1, 2);

    layout->addWidget(new QLabel(tr("Type:"), frame), 1, 0);
    m_typeCombo = new QComboBox(frame);

    // spacing hack will stretch the whole grid layout, so combos don't get
    // scrunched up:
    m_typeCombo->setMinimumContentsLength(20);

    layout->addWidget(m_typeCombo, 1, 1, 1, 2);

    layout->addWidget(new QLabel(tr("Description:"), frame), 2, 0);
    m_description = new LineEdit(frame);
    layout->addWidget(m_description, 2, 1, 1, 2);

    // hex value alongside decimal value
    m_hexValue = new QLabel(frame);
    layout->addWidget(m_hexValue, 3, 1);

    layout->addWidget(new QLabel(tr("Controller number:"), frame), 3, 0);
    m_controllerBox = new QSpinBox(frame);
    layout->addWidget(m_controllerBox, 3, 2);

    layout->addWidget(new QLabel(tr("Minimum value:"), frame), 4, 0);
    m_minBox = new QSpinBox(frame);
    layout->addWidget(m_minBox, 4, 1, 1, 2);

    layout->addWidget(new QLabel(tr("Maximum value:"), frame), 5, 0);
    m_maxBox = new QSpinBox(frame);
    layout->addWidget(m_maxBox, 5, 1, 1, 2);

    layout->addWidget(new QLabel(tr("Default value:"), frame), 6, 0);
    m_defaultBox = new QSpinBox(frame);
    layout->addWidget(m_defaultBox, 6, 1, 1, 2);

    layout->addWidget(new QLabel(tr("Color:"), frame), 7, 0);
    m_colourCombo = new QComboBox(frame);
    layout->addWidget(m_colourCombo, 7, 1, 1, 2);

    layout->addWidget(new QLabel(tr("Instrument Parameter Box position:"), frame), 8, 0);
    m_ipbPosition = new QComboBox(frame);
    layout->addWidget(m_ipbPosition, 8, 1, 1, 2);

    frame->setLayout(layout);

    connect(m_nameEdit, SIGNAL(textChanged(const QString&)),
            SLOT(slotNameChanged(const QString&)));

    connect(m_typeCombo, SIGNAL(activated(int)),
            SLOT(slotTypeChanged(int)));

    connect(m_description, SIGNAL(textChanged(const QString&)),
            SLOT(slotDescriptionChanged(const QString &)));

    connect(m_controllerBox, SIGNAL(valueChanged(int)),
            SLOT(slotControllerChanged(int)));

    connect(m_minBox, SIGNAL(valueChanged(int)),
            SLOT(slotMinChanged(int)));

    connect(m_maxBox, SIGNAL(valueChanged(int)),
            SLOT(slotMaxChanged(int)));

    connect(m_defaultBox, SIGNAL(valueChanged(int)),
            SLOT(slotDefaultChanged(int)));

    connect(m_colourCombo, SIGNAL(activated(int)),
            SLOT(slotColourChanged(int)));

    connect(m_ipbPosition, SIGNAL(activated(int)),
            SLOT(slotIPBPositionChanged(int)));

    //m_nameEdit->selectAll();
    //m_description->selectAll();

    // set limits
    m_controllerBox->setMinimum(0);
    m_controllerBox->setMaximum(127);

    m_minBox->setMinimum(INT_MIN);
    m_minBox->setMaximum(INT_MAX);

    m_maxBox->setMinimum(INT_MIN);
    m_maxBox->setMaximum(INT_MAX);

    m_defaultBox->setMinimum(INT_MIN);
    m_defaultBox->setMaximum(INT_MAX);

    // populate combos
    m_typeCombo->addItem(strtoqstr(Controller::EventType));
    m_typeCombo->addItem(strtoqstr(PitchBend::EventType));
    /*
    m_typeCombo->addItem(strtoqstr(KeyPressure::EventType));
    m_typeCombo->addItem(strtoqstr(ChannelPressure::EventType));
    */

    // Populate colour combo
    //
    //
    ColourMap &colourMap = m_doc->getComposition().getGeneralColourMap();
    RCMap::const_iterator it;
    QPixmap colourPixmap(16, 16);

    for (it = colourMap.begin(); it != colourMap.end(); ++it) {
        Colour c = it->second.first;
        colourPixmap.fill(QColor(c.getRed(), c.getGreen(), c.getBlue()));
        m_colourCombo->addItem(colourPixmap, strtoqstr(it->second.second));
    }

    // Populate IPB position combo
    //
    m_ipbPosition->addItem(tr("<not showing>"));

    // I couldn't find a constant for the maximum possible controller slots.
    // This seems to be it.  It used to be 32.  I upped it to 1024 because the
    // IPB is in a scrollable widget now, and that seems like a really
    // comfortable amount of headroom without being totally nuts like MAX_INT
    for (unsigned int i = 0; i < 1024; i++)
        m_ipbPosition->addItem(QString("%1").arg(i));

    if (m_control->getType() == Controller::EventType)
        m_typeCombo->setCurrentIndex(0);
    else if (m_control->getType() == PitchBend::EventType)
        m_typeCombo->setCurrentIndex(1);
    /*
    else if (m_control->getType() == KeyPressure::EventType)
        m_typeCombo->setCurrentIndex(2);
    else if (m_control->getType() == ChannelPressure::EventType)
        m_typeCombo->setCurrentIndex(3);
        */

    populate();
    QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
    metagrid->addWidget(buttonBox, 1, 0);
    metagrid->setRowStretch(0, 10);
    connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
    connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
}