Esempio n. 1
0
MatrixResizer::FollowMode
MatrixResizer::handleMouseMove(const MatrixMouseEvent *e)
{
    if (!e) return NoFollow;

    setBasicContextHelp();

    if (!m_currentElement || !m_currentViewSegment) return NoFollow;

    if (getSnapGrid()->getSnapSetting() != SnapGrid::NoSnap) {
        setContextHelp(tr("Hold Shift to avoid snapping to beat grid"));
    } else {
        clearContextHelp();
    }

    // snap in the closest direction
    timeT snapTime = e->snappedLeftTime;
    if (e->snappedRightTime - e->time < e->time - e->snappedLeftTime) {
        snapTime = e->snappedRightTime;
    }

    timeT newDuration = snapTime - m_currentElement->getViewAbsoluteTime();
    timeT durationDiff = newDuration - m_currentElement->getViewDuration();

    EventSelection* selection = m_scene->getSelection();
    if (!selection || selection->getAddedEvents() == 0) return NoFollow;

    EventSelection::eventcontainer::iterator it =
        selection->getSegmentEvents().begin();

    for (; it != selection->getSegmentEvents().end(); ++it) {

        MatrixElement *element = 0;
        ViewElementList::iterator vi = m_currentViewSegment->findEvent(*it);
        if (vi != m_currentViewSegment->getViewElementList()->end()) {
            element = static_cast<MatrixElement *>(*vi);
        }
        if (!element) continue;

        timeT t = element->getViewAbsoluteTime();
        timeT d = element->getViewDuration();
        
        d = d + durationDiff;
        if (d < 0) {
            t = t + d;
            d = -d;
        } else if (d == 0) {
            d = getSnapGrid()->getSnapTime(t);
        }

        element->reconfigure(t, d);
//            m_currentStaff->positionElement(element);
//        }
    }

//    m_mParentView->canvas()->update();
    return FollowHorizontal;
}
void 
SegmentTransposeCommand::processSegment(Segment &segment, bool changeKey, int steps, int semitones, bool transposeSegmentBack)
{
    MacroCommand * macroCommand = this;

    // TODO delete it somewhere.
    EventSelection * wholeSegment = new EventSelection(segment, segment.getStartTime(), segment.getEndMarkerTime());
    macroCommand->addCommand(new TransposeCommand
        (semitones, steps, *wholeSegment));
    
    // Key insertion can do transposition, but a C4 to D becomes a D4, while
    //  a C4 to G becomes a G3. Because we let the user specify an explicit number
    //  of octaves to move the notes up/down, we add the keys without transposing
    //  and handle the transposition seperately:
    if (changeKey)
    {
        Rosegarden::Key initialKey = segment.getKeyAtTime(segment.getStartTime());
        Rosegarden::Key newInitialKey = initialKey.transpose(semitones, steps);

        EventSelection::eventcontainer::iterator i;
        //std::list<KeyInsertionCommand*> commands;

        for (i = wholeSegment->getSegmentEvents().begin();
            i != wholeSegment->getSegmentEvents().end(); ++i) {
                // transpose key
                if ((*i)->isa(Rosegarden::Key::EventType)) {
                    Rosegarden::Key trKey = (Rosegarden::Key (**i)).transpose(semitones, steps); 
                    //commands.push_front
                    macroCommand->addCommand
                        (new KeyInsertionCommand
                         (segment,
                           (*i)->getAbsoluteTime(),
                           trKey,
                          false,
                          false,
                          false,
			  true));
                    }
            }
        std::list<KeyInsertionCommand*>::iterator ci;
        //for (ci=commands.begin(); ci!=commands.end(); ci++)
        //{
        //    commandHistory->addCommand(*ci);
        //}
            
        KeyInsertionCommand *firstKeyCommand = new KeyInsertionCommand
             (segment,
              segment.getStartTime(),
              newInitialKey,
              false,
              false,
              false,
	      true);
        //commandHistory->addCommand(firstKeyCommand);
        macroCommand->addCommand(firstKeyCommand);
    }
        
    if (transposeSegmentBack)
    {
        // Transpose segment in opposite direction
        int newTranspose = segment.getTranspose() - semitones;
        macroCommand->addCommand(new SegmentChangeTransposeCommand(newTranspose, &segment));
    }
}
Esempio n. 3
0
void
MatrixMover::handleLeftButtonPress(const MatrixMouseEvent *e)
{
    MATRIX_DEBUG << "MatrixMover::handleLeftButtonPress() : snapped time = " << e->snappedLeftTime << ", el = " << e->element << endl;

    if (!e->element) return;

    // Check the scene's current segment (apparently not necessarily the same
    // segment referred to by the scene's current view segment) for this event;
    // return if not found, indicating that this event is from some other,
    // non-active segment.
    //
    // I think notation just makes whatever segment active when you click an
    // event outside the active segment, and I think that's what this code
    // attempted to do too.  I couldn't get that to work at all.  This is better
    // than being able to click on non-active elements to create new events by
    // accident, and will probably fly.  Especially since the multi-segment
    // matrix is new, and we're defining the terms of how it works.
    Segment *segment = m_scene->getCurrentSegment();
    if (!segment) return;
    bool found = false;
    for (Segment::iterator i = segment->begin(); i != segment->end(); ++i) {
        if ((*i) == e->element->event()) found = true;
    }

    if (!found) {
        MATRIX_DEBUG << "Clicked element not owned by active segment.  Returning..." << endl;
        return;
    }

    m_currentViewSegment = e->viewSegment;

    m_currentElement = e->element;
    m_clickSnappedLeftTime = e->snappedLeftTime;

    m_quickCopy = (e->modifiers & Qt::ControlModifier);

    if (!m_duplicateElements.empty()) {
        for (size_t i = 0; i < m_duplicateElements.size(); ++i) {
            delete m_duplicateElements[i]->event();
            delete m_duplicateElements[i];
        }
        m_duplicateElements.clear();
    }

    // Add this element and allow movement
    //
    EventSelection* selection = m_scene->getSelection();
    Event *event = m_currentElement->event();

    if (selection) {
        EventSelection *newSelection;
        
        if ((e->modifiers & Qt::ShiftModifier) ||
            selection->contains(event)) {
            newSelection = new EventSelection(*selection);
        } else {
            newSelection = new EventSelection(m_currentViewSegment->getSegment());
        }
        
        // if the selection already contains the event, remove it from the
        // selection if shift is pressed
        if (selection->contains(event)) {
            if (e->modifiers & Qt::ShiftModifier) {
                newSelection->removeEvent(event);
            }
        } else {
            newSelection->addEvent(event);
        }
        m_scene->setSelection(newSelection, true);
        selection = newSelection;
    } else {
        m_scene->setSingleSelectedEvent(m_currentViewSegment,
                                        m_currentElement, true);
    }
    
    long velocity = m_widget->getCurrentVelocity();
    event->get<Int>(BaseProperties::VELOCITY, velocity);

    long pitchOffset = m_currentViewSegment->getSegment().getTranspose();

    long pitch = 60;
    event->get<Int>(BaseProperties::PITCH, pitch);

    // We used to m_scene->playNote() here, but the new concert pitch matrix was
    // playing chords the first time I clicked a note.  Investigation with
    // KMidiMon revealed two notes firing nearly simultaneously, and with
    // segments of 0 transpose, they were simply identical to each other.  One
    // of them came from here, and this was the one sounding at the wrong pitch
    // in transposed segments.  I've simply removed it with no apparent ill side
    // effects, and a problem solved super cheap.

    m_lastPlayedPitch = pitch;

    if (m_quickCopy && selection) {
        for (EventSelection::eventcontainer::iterator i =
                 selection->getSegmentEvents().begin();
             i != selection->getSegmentEvents().end(); ++i) {

            MatrixElement *duplicate = new MatrixElement
                (m_scene, new Event(**i),
                 m_widget->isDrumMode(), pitchOffset);

            m_duplicateElements.push_back(duplicate);
        }
    }
}
Esempio n. 4
0
void
MatrixMover::handleMouseRelease(const MatrixMouseEvent *e)
{
    if (!e) return;

    MATRIX_DEBUG << "MatrixMover::handleMouseRelease() - newPitch = "
                 << e->pitch << endl;

    if (!m_currentElement || !m_currentViewSegment) return;

    timeT newTime = m_currentElement->getViewAbsoluteTime() +
        (e->snappedLeftTime - m_clickSnappedLeftTime);
    int newPitch = e->pitch;

    if (newPitch > 127) newPitch = 127;
    if (newPitch < 0) newPitch = 0;

    // get a basic pitch difference calculation comparing the current element's
    // pitch to the pitch the mouse was released at (see note in
    // handleMouseMove)
    using BaseProperties::PITCH;
    timeT diffTime = newTime - m_currentElement->getViewAbsoluteTime();
    int diffPitch = 0;
    if (m_currentElement->event()->has(PITCH)) {
        diffPitch = newPitch - m_currentElement->event()->get<Int>(PITCH);
    }

    EventSelection* selection = m_scene->getSelection();

    // factor in transpose to adjust the height calculation
    long pitchOffset = selection->getSegment().getTranspose();
    diffPitch += (pitchOffset * -1);

    if ((diffTime == 0 && diffPitch == 0) || selection->getAddedEvents() == 0) {
        for (size_t i = 0; i < m_duplicateElements.size(); ++i) {
            delete m_duplicateElements[i]->event();
            delete m_duplicateElements[i];
        }
        m_duplicateElements.clear();
        m_currentElement = 0;
        return;
    }

    if (newPitch != m_lastPlayedPitch) {
        long velocity = m_widget->getCurrentVelocity();
        m_currentElement->event()->get<Int>(BaseProperties::VELOCITY, velocity);
        m_scene->playNote(m_currentViewSegment->getSegment(), newPitch + (pitchOffset * -1), velocity);
        m_lastPlayedPitch = newPitch;
    }

    QString commandLabel;
    if (m_quickCopy) {
        if (selection->getAddedEvents() < 2) {
            commandLabel = tr("Copy and Move Event");
        } else {
            commandLabel = tr("Copy and Move Events");
        }
    } else {
        if (selection->getAddedEvents() < 2) {
            commandLabel = tr("Move Event");
        } else {
            commandLabel = tr("Move Events");
        }
    }

    MacroCommand *macro = new MacroCommand(commandLabel);

    EventSelection::eventcontainer::iterator it =
        selection->getSegmentEvents().begin();

    Segment &segment = m_currentViewSegment->getSegment();

    EventSelection *newSelection = new EventSelection(segment);

    timeT normalizeStart = selection->getStartTime();
    timeT normalizeEnd = selection->getEndTime();

    if (m_quickCopy) {
        for (size_t i = 0; i < m_duplicateElements.size(); ++i) {
            timeT time = m_duplicateElements[i]->getViewAbsoluteTime();
            timeT endTime = time + m_duplicateElements[i]->getViewDuration();
            if (time < normalizeStart) normalizeStart = time;
            if (endTime > normalizeEnd) normalizeEnd = endTime;
            macro->addCommand(new MatrixInsertionCommand
                              (segment, time, endTime, 
                               m_duplicateElements[i]->event()));
            delete m_duplicateElements[i]->event();
            delete m_duplicateElements[i];
        }
        m_duplicateElements.clear();
        m_quickCopy = false;
    }
        
    for (; it != selection->getSegmentEvents().end(); ++it) {

        timeT newTime = (*it)->getAbsoluteTime() + diffTime;

        int newPitch = 60;
        if ((*it)->has(PITCH)) {
            newPitch = (*it)->get<Int>(PITCH) + diffPitch;
        }

        Event *newEvent = 0;

        if (newTime < segment.getStartTime()) {
            newTime = segment.getStartTime();
        }

        if (newTime + (*it)->getDuration() >= segment.getEndMarkerTime()) {
            timeT limit = getSnapGrid()->snapTime
                (segment.getEndMarkerTime() - 1, SnapGrid::SnapLeft);
            if (newTime > limit) newTime = limit;
            timeT newDuration = std::min
                ((*it)->getDuration(), segment.getEndMarkerTime() - newTime);
            newEvent = new Event(**it, newTime, newDuration);
        } else {
            newEvent = new Event(**it, newTime);
        }

        newEvent->set<Int>(BaseProperties::PITCH, newPitch);

        macro->addCommand(new MatrixModifyCommand(segment,
                                                  (*it),
                                                  newEvent,
                                                  true,
                                                  false));
        newSelection->addEvent(newEvent);
    }

    normalizeStart = std::min(normalizeStart, newSelection->getStartTime());
    normalizeEnd = std::max(normalizeEnd, newSelection->getEndTime());
    
    macro->addCommand(new NormalizeRestsCommand(segment,
                                                normalizeStart,
                                                normalizeEnd));
    
    m_scene->setSelection(0, false);
    CommandHistory::getInstance()->addCommand(macro);
    m_scene->setSelection(newSelection, false);

//    m_mParentView->canvas()->update();
    m_currentElement = 0;

    setBasicContextHelp();
}
Esempio n. 5
0
MatrixTool::FollowMode
MatrixMover::handleMouseMove(const MatrixMouseEvent *e)
{
    if (!e) return NoFollow;

    MATRIX_DEBUG << "MatrixMover::handleMouseMove() snapped time = "
                 << e->snappedLeftTime << endl;

    setBasicContextHelp(e->modifiers & Qt::ControlModifier);

    if (!m_currentElement || !m_currentViewSegment) return NoFollow;

    if (getSnapGrid()->getSnapSetting() != SnapGrid::NoSnap) {
        setContextHelp(tr("Hold Shift to avoid snapping to beat grid"));
    } else {
        clearContextHelp();
    }

    timeT newTime = m_currentElement->getViewAbsoluteTime() +
        (e->snappedLeftTime - m_clickSnappedLeftTime);
    int newPitch = e->pitch;

    emit hoveredOverNoteChanged(newPitch, true, newTime);

    // get a basic pitch difference calculation comparing the current element's
    // pitch to the clicked pitch (this does not take the transpose factor into
    // account, so in a -9 segment, the initial result winds up being 9
    // semitones too low)
    using BaseProperties::PITCH;
    int diffPitch = 0;
    if (m_currentElement->event()->has(PITCH)) {
        diffPitch = newPitch - m_currentElement->event()->get<Int>(PITCH);
    }
    
    EventSelection* selection = m_scene->getSelection();

    // factor in transpose to adjust the height calculation
    long pitchOffset = selection->getSegment().getTranspose();
    diffPitch += (pitchOffset * -1);

    for (EventSelection::eventcontainer::iterator it =
             selection->getSegmentEvents().begin();
         it != selection->getSegmentEvents().end(); ++it) {

        MatrixElement *element = 0;
        ViewElementList::iterator vi = m_currentViewSegment->findEvent(*it);
        if (vi != m_currentViewSegment->getViewElementList()->end()) {
            element = static_cast<MatrixElement *>(*vi);
        }
        if (!element) continue;

        timeT diffTime = element->getViewAbsoluteTime() -
            m_currentElement->getViewAbsoluteTime();

        int epitch = 0;
        if (element->event()->has(PITCH)) {
            epitch = element->event()->get<Int>(PITCH);
        }

        element->reconfigure(newTime + diffTime,
                             element->getViewDuration(),
                             epitch + diffPitch);
                             
        element->setSelected(true);
            
    }

    if (newPitch != m_lastPlayedPitch) {
        long velocity = m_widget->getCurrentVelocity();
        m_currentElement->event()->get<Int>(BaseProperties::VELOCITY, velocity);
        m_scene->playNote(m_currentViewSegment->getSegment(), newPitch + (pitchOffset * -1), velocity);
        m_lastPlayedPitch = newPitch;
    }

    return FollowMode(FollowHorizontal | FollowVertical);
}
Esempio n. 6
0
void
MatrixResizer::handleMouseRelease(const MatrixMouseEvent *e)
{
    if (!e || !m_currentElement || !m_currentViewSegment) return;

    // snap in the closest direction
    timeT snapTime = e->snappedLeftTime;
    if (e->snappedRightTime - e->time < e->time - e->snappedLeftTime) {
        snapTime = e->snappedRightTime;
    }

    timeT newDuration = snapTime - m_currentElement->getViewAbsoluteTime();
    timeT durationDiff = newDuration - m_currentElement->getViewDuration();

    EventSelection *selection = m_scene->getSelection();
    if (!selection || selection->getAddedEvents() == 0) return;

    QString commandLabel = tr("Resize Event");
    if (selection->getAddedEvents() > 1) commandLabel = tr("Resize Events");

    MacroCommand *macro = new MacroCommand(commandLabel);

    EventSelection::eventcontainer::iterator it =
        selection->getSegmentEvents().begin();

    Segment &segment = m_currentViewSegment->getSegment();

    EventSelection *newSelection = new EventSelection(segment);

    timeT normalizeStart = selection->getStartTime();
    timeT normalizeEnd = selection->getEndTime();

    for (; it != selection->getSegmentEvents().end(); ++it) {

        timeT t = (*it)->getAbsoluteTime();
        timeT d = (*it)->getDuration();

        MATRIX_DEBUG << "MatrixResizer::handleMouseRelease - "
                     << "Time = " << t
                     << ", Duration = " << d << endl;

        d = d + durationDiff;
        if (d < 0) {
            t = t + d;
            d = -d;
        } else if (d == 0) {
            d = getSnapGrid()->getSnapTime(t);
        }

        if (t + d > segment.getEndMarkerTime()) {
            d = segment.getEndMarkerTime() - t;
            if (d <= 0) {
                d = segment.getEndMarkerTime();
                t = d - getSnapGrid()->getSnapTime(t);
            }
        }

        Event *newEvent = new Event(**it, t, d);

        macro->addCommand(new MatrixModifyCommand(segment,
                                                  *it,
                                                  newEvent,
                                                  false,
                                                  false));

        newSelection->addEvent(newEvent);
    }

    normalizeStart = std::min(normalizeStart, newSelection->getStartTime());
    normalizeEnd = std::max(normalizeEnd, newSelection->getEndTime());

    macro->addCommand(new NormalizeRestsCommand(segment,
                                                normalizeStart,
                                                normalizeEnd));

    m_scene->setSelection(0, false);
    CommandHistory::getInstance()->addCommand(macro);
    m_scene->setSelection(newSelection, false);

//    m_mParentView->update();
    m_currentElement = 0;
    setBasicContextHelp();
}