예제 #1
0
void
MidiMixerWindow::slotFaderLevelChanged(float value)
{
    const QObject *s = sender();

    for (FaderVector::const_iterator it = m_faders.begin();
            it != m_faders.end(); ++it) {
        if ((*it)->m_volumeFader == s) {
            Instrument *instr = m_studio->
                                getInstrumentById((*it)->m_id);

            if (instr) {

                instr->setControllerValue(MIDI_CONTROLLER_VOLUME, MidiByte(value));

                if (instr->hasFixedChannel())
                {
                    // send out to external controllers as well if the
                    // affected instrument is on a fixed channel.
                    
                    //!!! really want some notification of whether we have any!
                    int tabIndex = m_tabWidget->currentIndex();
                    if (tabIndex < 0)
                        tabIndex = 0;
                    int i = 0;
                    for (DeviceList::const_iterator dit = m_studio->begin();
                         dit != m_studio->end(); ++dit) {
                        RG_DEBUG << "slotFaderLevelChanged: i = " << i << ", tabIndex " << tabIndex << endl;
                        if (!dynamic_cast<MidiDevice*>(*dit))
                            continue;
                        if (i != tabIndex) {
                            ++i;
                            continue;
                        }
                        RG_DEBUG << "slotFaderLevelChanged: device id = " << instr->getDevice()->getId() << ", visible device id " << (*dit)->getId() << endl;
                        if (instr->getDevice()->getId() == (*dit)->getId()) {
                            RG_DEBUG << "slotFaderLevelChanged: sending control device mapped event for channel " << instr->getNaturalChannel() << endl;

                            MappedEvent mE((*it)->m_id,
                                           MappedEvent::MidiController,
                                           MIDI_CONTROLLER_VOLUME,
                                           MidiByte(value));

                            mE.setRecordedChannel(instr->getNaturalChannel());
                            mE.setRecordedDevice(Device::CONTROL_DEVICE);
                            StudioControl::sendMappedEvent(mE);
                        }
                        break;
                    }
                }
            }

            emit instrumentParametersChanged((*it)->m_id);
            return ;
        }
    }
}
예제 #2
0
// Release the channel that thru MIDI events played on.
// @author Tom Breton (Tehom)
void
TrackInfo::releaseThruChannel(Studio &studio)
{
    if (!m_hasThruChannel) {
        return;
    }

    Instrument *instrument =
        studio.getInstrumentById(m_instrumentId);

    if (instrument && !m_useFixedChannel) {

        Device* device = instrument->getDevice();
        Q_CHECK_PTR(device);
        AllocateChannels *allocator = device->getAllocator();

        // Device is a channel-managing device (Midi), so release the
        // channel.
        if (allocator)
        {
            allocator->releaseThruChannel(m_thruChannel);
        }
    }
    // If we recently deleted a device, we may get a NULL instrument.
    // In that case, we can't actively release it but we don't need
    // to, we can just mark it released.
    else { /* if (!instrument || m_useFixedChannel) */ }

    m_thruChannel = -1;
    // Channel wants no setup if we somehow encounter it in this
    // state.
    m_isThruChannelReady = true;
    m_hasThruChannel = false;
}
예제 #3
0
MappedInstrument::MappedInstrument(const Instrument &instr):
        m_type(instr.getType()),
        m_id(instr.getId()),
        m_name(instr.getName()),
        m_device((instr.getDevice())->getId()),
        m_audioChannels(instr.getAudioChannels())
{}
예제 #4
0
// Allocate a channel for thru MIDI events to play on.
// @author Tom Breton (Tehom)
void
TrackInfo::allocateThruChannel(Studio &studio)
{
    Instrument *instrument =
        studio.getInstrumentById(m_instrumentId);

    // If we have deleted a device, we may get a NULL instrument.  In
    // that case, we can't do much.
    if (!instrument) {
        return;
    }

    // This value of fixity holds until releaseThruChannel is called.
    m_useFixedChannel = instrument->hasFixedChannel();

    if (m_useFixedChannel) {
        m_thruChannel = instrument->getNaturalChannel();
        m_hasThruChannel = true;
        m_isThruChannelReady = true;
        return;
    }

    Device* device = instrument->getDevice();
    Q_CHECK_PTR(device);
    AllocateChannels *allocator = device->getAllocator();

#ifdef DEBUG_CONTROL_BLOCK
    RG_DEBUG << "TrackInfo::allocateThruChannel() "
             << (allocator ?
                 "got an allocator" :
                 "didn't get an allocator")
             << endl;
#endif

    // Device is not a channel-managing device, so instrument's
    // natural channel is correct and requires no further setup.
    if (!allocator)
    {
        m_thruChannel = instrument->getNaturalChannel();
        m_isThruChannelReady = true;
        m_hasThruChannel = true;
        return;
    }

    // Get a suitable channel.
    m_thruChannel = allocator->allocateThruChannel(*instrument);

#ifdef DEBUG_CONTROL_BLOCK
    RG_DEBUG << "TrackInfo::allocateThruChannel() got channel"
             << (int)m_thruChannel
             << endl;
#endif

    // Right now the channel is probably playing the wrong program.
    m_isThruChannelReady = false;
    m_hasThruChannel = true;
}
예제 #5
0
void
ControlRulerWidget::setSegments(RosegardenDocument *document, std::vector<Segment *> segments)
{
    m_document = document;
//    m_segments = segments;

//    connect(m_document, SIGNAL(pointerPositionChanged(timeT)),
//            this, SLOT(slotPointerPositionChanged(timeT)));

    Composition &comp = document->getComposition();

    Track *track =
        comp.getTrackById(segments[0]->getTrack());

    Instrument *instr = document->getStudio().
        getInstrumentById(track->getInstrument());

    if (instr) {
        Device *device = instr->getDevice();

        // Cast to a Controllable if possible, otherwise leave c NULL.
        Controllable *c =
            dynamic_cast<MidiDevice *>(device);
        if (!c)
            { c = dynamic_cast<SoftSynthDevice *>(device); }

        if (c) {
            m_controlList = &(c->getControlParameters());
        }
    }

    SegmentSelection selection;
    selection.insert(segments.begin(), segments.end());

    delete m_scale;

    setRulerScale(new SegmentsRulerScale(&m_document->getComposition(),
            selection,
            0,
            Note(Note::Shortest).getDuration() / 2.0));
    
    // This is single segment code
    setSegment(segments[0]);
}
예제 #6
0
// Make the channel ready to play on.  Send the program, etc.
// @author Tom Breton (Tehom)
void
TrackInfo::makeChannelReady(Studio &studio)
{
#ifdef DEBUG_CONTROL_BLOCK
    RG_DEBUG << "TrackInfo::makeChannelReady()"
             << endl;
#endif
    Instrument *instrument =
        studio.getInstrumentById(m_instrumentId);

    // If we have deleted a device, we may get a NULL instrument.  In
    // that case, we can't do much.
    if (!instrument) {
        return;
    }

    // We can get non-Midi instruments here.  There's nothing to do
    // for them.  For fixed, sendChannelSetup is slightly wrong, but
    // could be adapted and parameterized by trackId.
    if ((instrument->getType() == Instrument::Midi)
            && !m_useFixedChannel) {
        // Re-acquire channel.  It may change if instrument's program
        // became percussion or became non-percussion.
        Device* device = instrument->getDevice();
        Q_CHECK_PTR(device);
        AllocateChannels *allocator = device->getAllocator();
        if (allocator) {
            m_thruChannel =
                allocator->reallocateThruChannel(*instrument, m_thruChannel);
            // If somehow we got here without having a channel, we
            // have one now.
            m_hasThruChannel = true;
#ifdef DEBUG_CONTROL_BLOCK
            RG_DEBUG << "TrackInfo::makeChannelReady() now has channel"
                     << m_hasThruChannel
                     << endl;
#endif
        }
        // This is how Midi instrument readies a fixed channel.
        StudioControl::sendChannelSetup(instrument, m_thruChannel);
    }
    m_isThruChannelReady = true;
}
void
ModifyDeviceMappingCommand::execute()
{
    Composition::trackcontainer &tracks =
        m_composition->getTracks();
    Composition::trackcontainer::iterator it = tracks.begin();
    Instrument *instr = 0;
    int index = 0;

    for (; it != tracks.end(); ++it) {
        instr = m_studio->getInstrumentById(it->second->getInstrument());
        if (!instr || !instr->getDevice())
            continue;

        if (instr->getDevice()->getId() == m_fromDevice) {
            // if source and target are MIDI
            if (m_studio->getDevice(m_fromDevice)->getType() ==
                    Device::Midi &&
                    m_studio->getDevice(m_toDevice)->getType() ==
                    Device::Midi) {
                // Try to match channels on the target device
                //
                MidiByte channel = instr->getNaturalChannel();

                InstrumentList destList = m_studio->
                                          getDevice(m_toDevice)->getPresentationInstruments();

                InstrumentList::iterator dIt = destList.begin();

                for (; dIt != destList.end(); ++dIt) {
                    if ((*dIt)->getNaturalChannel() == channel) {
                        break;
                    }
                }

                // Failure to match anything and there's no Instruments
                // at all in the destination.  Skip to next source Instrument.
                //
                if (dIt == destList.end() || destList.size() == 0)
                    continue;


                RG_DEBUG << " Track " << it->first
                << ", setting Instrument to "
                << (*dIt)->getId() << endl;

                // store "to" and "from" values
                //
                m_mapping.push_back(
                    std::pair < TrackId,
                    InstrumentId >
                    (it->first,
                     instr->getId()));

                it->second->setInstrument((*dIt)->getId());
            } else // audio is involved in the mapping - use indexes
            {
                // assign by index numbers
                InstrumentList destList = m_studio->
                                          getDevice(m_toDevice)->getPresentationInstruments();

                // skip if we can't match
                //
                if (index > (int)(destList.size() - 1))
                    continue;

                m_mapping.push_back(
                    std::pair < TrackId,
                    InstrumentId >
                    (it->first,
                     instr->getId()));

                it->second->setInstrument(destList[index]->getId());
            }

            index++;
        }
    }

}
예제 #8
0
void
MidiMixerWindow::slotControllerChanged(float value)
{
    const QObject *s = sender();
    size_t i = 0, j = 0;

    for (i = 0; i < m_faders.size(); ++i) {
        for (j = 0; j < m_faders[i]->m_controllerRotaries.size(); ++j) {
            if (m_faders[i]->m_controllerRotaries[j].second == s)
                break;
        }

        // break out on match
        if (j != m_faders[i]->m_controllerRotaries.size())
            break;
    }

    // Don't do anything if we've not matched and got solid values
    // for i and j
    //
    if (i == m_faders.size() || j == m_faders[i]->m_controllerRotaries.size())
        return ;

    //RG_DEBUG << "MidiMixerWindow::slotControllerChanged - found a controller"
    //<< endl;

    Instrument *instr = m_studio->getInstrumentById(
                            m_faders[i]->m_id);

    if (instr) {

        //RG_DEBUG << "MidiMixerWindow::slotControllerChanged - "
        //<< "got instrument to change" << endl;

        instr->setControllerValue(m_faders[i]->
                                  m_controllerRotaries[j].first,
                                  MidiByte(value));

        if (instr->hasFixedChannel()) {
            int tabIndex = m_tabWidget->currentIndex();
            if (tabIndex < 0)
                tabIndex = 0;
            int k = 0;
            for (DeviceList::const_iterator dit = m_studio->begin();
                 dit != m_studio->end(); ++dit) {
                RG_DEBUG << "slotControllerChanged: k = " << k << ", tabIndex " << tabIndex << endl;
                if (!dynamic_cast<MidiDevice*>(*dit))
                    continue;
                if (k != tabIndex) {
                    ++k;
                    continue;
                }
                RG_DEBUG << "slotControllerChanged: device id = " << instr->getDevice()->getId() << ", visible device id " << (*dit)->getId() << endl;
                if (instr->getDevice()->getId() == (*dit)->getId()) {
                    RG_DEBUG << "slotControllerChanged: sending control device mapped event for channel " << instr->getNaturalChannel() << endl;
                    // send out to external controllers as well.
                    //!!! really want some notification of whether we have any!
                    MappedEvent mE(m_faders[i]->m_id,
                                   MappedEvent::MidiController,
                                   m_faders[i]->m_controllerRotaries[j].first,
                                   MidiByte(value));
                    mE.setRecordedChannel(instr->getNaturalChannel());
                    mE.setRecordedDevice(Device::CONTROL_DEVICE);
                    StudioControl::sendMappedEvent(mE);
                }
            }
        }
        emit instrumentParametersChanged(m_faders[i]->m_id);
    }
}
예제 #9
0
void
TrackParameterBox::updateWidgets2()
{
    Track *track = getTrack();
    if (!track)
        return;

    Instrument *instrument = m_doc->getStudio().getInstrumentFor(track);
    if (!instrument)
        return;

    // *** Track Label

    QString trackName = strtoqstr(track->getLabel());
    if (trackName.isEmpty())
        trackName = tr("<untitled>");
    else
        trackName.truncate(20);

    const int trackNum = track->getPosition() + 1;

    m_trackLabel->setText(tr("[ Track %1 - %2 ]").arg(trackNum).arg(trackName));

    // *** Playback parameters

    // Device
    updatePlaybackDevice(instrument->getDevice()->getId());

    // Instrument
    updateInstrument(instrument);

    // Archive
    m_archive->setChecked(track->isArchived());

    // If the current Instrument is an Audio Instrument...
    if (instrument->getInstrumentType() == Instrument::Audio) {

        // Hide irrelevant portions.

        m_recordingFiltersFrame->setVisible(false);
        m_staffExportOptionsFrame->setVisible(false);

        // In the Create segments with... frame, only the color combo is
        // useful for an Audio track.
        m_presetLabel->setVisible(false);
        m_preset->setVisible(false);
        m_load->setVisible(false);
        m_clefLabel->setVisible(false);
        m_clef->setVisible(false);
        m_transposeLabel->setVisible(false);
        m_transpose->setVisible(false);
        m_pitchLabel->setVisible(false);
        m_lowestLabel->setVisible(false);
        m_lowest->setVisible(false);
        m_highestLabel->setVisible(false);
        m_highest->setVisible(false);

    } else {  // MIDI or soft synth

        // Show everything.

        m_recordingFiltersFrame->setVisible(true);
        m_staffExportOptionsFrame->setVisible(true);

        // Create segments with... frame
        m_presetLabel->setVisible(true);
        m_preset->setVisible(true);
        m_load->setVisible(true);
        m_clefLabel->setVisible(true);
        m_clef->setVisible(true);
        m_transposeLabel->setVisible(true);
        m_transpose->setVisible(true);
        m_pitchLabel->setVisible(true);
        m_lowestLabel->setVisible(true);
        m_lowest->setVisible(true);
        m_highestLabel->setVisible(true);
        m_highest->setVisible(true);
    }

    // *** Recording filters

    // Device
    updateRecordingDevice(track->getMidiInputDevice());

    // Channel
    m_recordingChannel->setCurrentIndex((int)track->getMidiInputChannel() + 1);

    // Thru Routing
    m_thruRouting->setCurrentIndex((int)track->getThruRouting());

    // *** Staff export options

    // Notation size
    m_notationSize->setCurrentIndex(track->getStaffSize());

    // Bracket type
    m_bracketType->setCurrentIndex(track->getStaffBracket());

    // *** Create segments with

    // Preset (Label)
    m_preset->setText(strtoqstr(track->getPresetLabel()));

    // Clef
    m_clef->setCurrentIndex(track->getClef());

    // Transpose
    m_transpose->setCurrentIndex(
            m_transpose->findText(QString("%1").arg(track->getTranspose())));

    // Pitch Lowest

    QSettings settings;
    settings.beginGroup(GeneralOptionsConfigGroup);
    const int octaveBase = settings.value("midipitchoctave", -2).toInt() ;
    settings.endGroup();

    const bool includeOctave = false;

    const Pitch lowest(track->getLowestPlayable(), Accidentals::NoAccidental);

    // NOTE: this now uses a new, overloaded version of Pitch::getAsString()
    // that explicitly works with the key of C major, and does not allow the
    // calling code to specify how the accidentals should be written out.
    //
    // Separate the note letter from the octave to avoid undue burden on
    // translators having to retranslate the same thing but for a number
    // difference
    QString tmp = QObject::tr(lowest.getAsString(includeOctave, octaveBase).c_str(), "note name");
    tmp += tr(" %1").arg(lowest.getOctave(octaveBase));
    m_lowest->setText(tmp);

    // Pitch Highest

    const Pitch highest(track->getHighestPlayable(), Accidentals::NoAccidental);

    tmp = QObject::tr(highest.getAsString(includeOctave, octaveBase).c_str(), "note name");
    tmp += tr(" %1").arg(highest.getOctave(octaveBase));
    m_highest->setText(tmp);

    // Color
    // Note: We only update the combobox contents if there is an actual
    //       change to the document's colors.  See slotDocColoursChanged().
    m_color->setCurrentIndex(track->getColor());
}
예제 #10
0
// ??? Break this stuff off into an InstrumentPopup class.  This class is too
//     big.
void
TrackButtons::populateInstrumentPopup(Instrument *thisTrackInstr, QMenu* instrumentPopup)
{
    // pixmaps for icons to show connection states as variously colored boxes
    // ??? Factor out the icon-related stuff to make this routine clearer.
    //     getIcon(Instrument *) would be ideal, but might not be easy.
    //     getIcon(Device *) would also be needed.
    static QPixmap connectedPixmap, unconnectedPixmap,
                   connectedUsedPixmap, unconnectedUsedPixmap,
                   connectedSelectedPixmap, unconnectedSelectedPixmap;

    static bool havePixmaps = false;
        
    if (!havePixmaps) {

        IconLoader il;
        
        connectedPixmap = il.loadPixmap("connected");
        connectedUsedPixmap = il.loadPixmap("connected-used");
        connectedSelectedPixmap = il.loadPixmap("connected-selected");
        unconnectedPixmap = il.loadPixmap("unconnected");
        unconnectedUsedPixmap = il.loadPixmap("unconnected-used");
        unconnectedSelectedPixmap = il.loadPixmap("unconnected-selected");

        havePixmaps = true;
    }

    Composition &comp = m_doc->getComposition();

    // clear the popup
    instrumentPopup->clear();

    QMenu *currentSubMenu = 0;

    // position index
    int count = 0;

    int currentDevId = -1;

    // Get the list
    Studio &studio = m_doc->getStudio();
    InstrumentList list = studio.getPresentationInstruments();

    // For each instrument
    for (InstrumentList::iterator it = list.begin(); it != list.end(); ++it) {

        if (!(*it)) continue; // sanity check

        // get the Localized instrument name, with the string hackery performed
        // in Instrument
        QString iname((*it)->getLocalizedPresentationName());

        // translate the program name
        //
        // Note we are converting the string from std to Q back to std then to
        // C.  This is obviously ridiculous, but the fact that we have programName
        // here at all makes me think it exists as some kind of necessary hack
        // to coax tr() into behaving nicely.  I decided to change it as little
        // as possible to get it to compile, and not refactor this down to the
        // simplest way to call tr() on a C string.
        QString programName(strtoqstr((*it)->getProgramName()));
        programName = QObject::tr(programName.toStdString().c_str());

        Device *device = (*it)->getDevice();
        DeviceId devId = device->getId();
        bool connectedIcon = false;

        // Determine the proper program name and whether it is connected

        if ((*it)->getType() == Instrument::SoftSynth) {
            programName = "";
            AudioPluginInstance *plugin =
                    (*it)->getPlugin(Instrument::SYNTH_PLUGIN_POSITION);
            if (plugin) {
                // we don't translate any plugin program names or other texts
                programName = strtoqstr(plugin->getDisplayName());
                connectedIcon = (plugin->getIdentifier() != "");
            }
        } else if ((*it)->getType() == Instrument::Audio) {
            connectedIcon = true;
        } else {
            QString conn = RosegardenSequencer::getInstance()->
                    getConnection(devId);
            connectedIcon = (conn != "");
        }

        // These two are for selecting the correct icon to display.
        bool instrUsedByMe = false;
        bool instrUsedByAnyone = false;

        if (thisTrackInstr && thisTrackInstr->getId() == (*it)->getId()) {
            instrUsedByMe = true;
            instrUsedByAnyone = true;
        }

        // If we have switched to a new device, we'll create a new submenu
        if (devId != (DeviceId)(currentDevId)) {

            currentDevId = int(devId);

            // For selecting the correct icon to display.
            bool deviceUsedByAnyone = false;

            if (instrUsedByMe)
                deviceUsedByAnyone = true;
            else {
                for (Composition::trackcontainer::iterator tit =
                         comp.getTracks().begin();
                     tit != comp.getTracks().end(); ++tit) {

                    if (tit->second->getInstrument() == (*it)->getId()) {
                        instrUsedByAnyone = true;
                        deviceUsedByAnyone = true;
                        break;
                    }

                    Instrument *instr =
                        studio.getInstrumentById(tit->second->getInstrument());
                    if (instr && (instr->getDevice()->getId() == devId)) {
                        deviceUsedByAnyone = true;
                    }
                }
            }

            QIcon icon
                (connectedIcon ?
                 (deviceUsedByAnyone ?
                  connectedUsedPixmap : connectedPixmap) :
                 (deviceUsedByAnyone ?
                  unconnectedUsedPixmap : unconnectedPixmap));

            // Create a submenu for this device
            QMenu *subMenu = new QMenu(instrumentPopup);
            subMenu->setMouseTracking(true);
            subMenu->setIcon(icon);
            // Not needed so long as AA_DontShowIconsInMenus is false.
            //subMenu->menuAction()->setIconVisibleInMenu(true);

            // Menu title
            QString deviceName = QObject::tr(device->getName().c_str());
            subMenu->setTitle(deviceName);

            // QObject name
            subMenu->setObjectName(deviceName);

            // Add the submenu to the popup menu
            instrumentPopup->addMenu(subMenu);

            // Connect the submenu to slotInstrumentSelected()
            connect(subMenu, SIGNAL(triggered(QAction*)),
                    this, SLOT(slotInstrumentSelected(QAction*)));

            currentSubMenu = subMenu;

        } else if (!instrUsedByMe) {