Logo Search packages:      
Sourcecode: rosegarden version File versions

matrixcommands.cpp

// -*- c-basic-offset: 4 -*-

/*
    Rosegarden-4
    A sequencer and musical notation editor.

    This program is Copyright 2000-2006
        Guillaume Laurent   <glaurent@telegraph-road.org>,
        Chris Cannam        <cannam@all-day-breakfast.com>,
        Richard Bown        <bownie@bownie.com>

    The moral right of the authors to claim authorship of this work
    has been asserted.

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2 of the
    License, or (at your option) any later version.  See the file
    COPYING included with this distribution for more information.
*/

#include "matrixcommands.h"
#include "BaseProperties.h"
#include "SegmentMatrixHelper.h"
#include "Segment.h"
#include "Composition.h"

#include <klocale.h>
#include "rosestrings.h"
#include "rosedebug.h"

using Rosegarden::Event;
using Rosegarden::Note;
using Rosegarden::timeT;
using Rosegarden::Segment;
using Rosegarden::Int;
using namespace Rosegarden::BaseProperties;

MatrixInsertionCommand::MatrixInsertionCommand(Segment &segment,
                                               timeT time,
                                               timeT endTime,
                                               Event *event) :
    BasicCommand(i18n("Insert Note"), segment, time, endTime),
    m_event(new Event(*event,
                      std::min(time, endTime),
                      (time < endTime) ? endTime - time : time - endTime))
{
    // nothing
}

MatrixInsertionCommand::~MatrixInsertionCommand()
{
    delete m_event;
    // don't want to delete m_lastInsertedEvent, it's just an alias
}

void MatrixInsertionCommand::modifySegment()
{
    MATRIX_DEBUG << "MatrixInsertionCommand::modifySegment()\n";

    if (!m_event->has(VELOCITY)) {
      m_event->set<Int>(VELOCITY, 100);
    }

    Rosegarden::SegmentMatrixHelper helper(getSegment());
    m_lastInsertedEvent = new Event(*m_event);
    helper.insertNote(m_lastInsertedEvent);
}

MatrixPercussionInsertionCommand::MatrixPercussionInsertionCommand(Segment &segment,
                                                   timeT time,
                                                   Event *event) :
    BasicCommand(i18n("Insert Percussion Note"), segment,
             getEffectiveStartTime(segment, time, *event),
             getEndTime(segment, time, *event)),
    m_event(0),
    m_time(time)
{
    timeT endTime = getEndTime(segment, time, *event);
    m_event = new Event(*event, time, endTime - time);
}

MatrixPercussionInsertionCommand::~MatrixPercussionInsertionCommand()
{
    delete m_event;
    // don't want to delete m_lastInsertedEvent, it's just an alias
}

void MatrixPercussionInsertionCommand::modifySegment()
{
    MATRIX_DEBUG << "MatrixPercussionInsertionCommand::modifySegment()\n";

    if (!m_event->has(VELOCITY)) {
      m_event->set<Int>(VELOCITY, 100);
    }

    Segment &s = getSegment();

    Segment::iterator i = s.findTime(m_time);

    int pitch = 0;
    if (m_event->has(PITCH)) {
      pitch = m_event->get<Int>(PITCH);
    }

    while (i != s.begin()) {

      --i;

      if ((*i)->getAbsoluteTime() < m_time &&
          (*i)->isa(Note::EventType)) {

          if ((*i)->has(PITCH) &&
            (*i)->get<Int>(PITCH) == pitch) {

            if ((*i)->getAbsoluteTime() + (*i)->getDuration() > m_time) {
                Rosegarden::Event *newPrevious = new Rosegarden::Event
                  (**i, (*i)->getAbsoluteTime(), m_time - (*i)->getAbsoluteTime());
                s.erase(i);
                i = s.insert(newPrevious);
            } else {
                break;
            }
          }
      }
    }

    Rosegarden::SegmentMatrixHelper helper(s);
    m_lastInsertedEvent = new Event(*m_event);
    helper.insertNote(m_lastInsertedEvent);
}

timeT
MatrixPercussionInsertionCommand::getEffectiveStartTime(Segment &segment,
                                          timeT time,
                                          Rosegarden::Event &event)
{
    Rosegarden::timeT startTime = time;

    int pitch = 0;
    if (event.has(PITCH)) {
      pitch = event.get<Int>(PITCH);
    }

    Segment::iterator i = segment.findTime(time);
    while (i != segment.begin()) {
      --i;

      if ((*i)->has(PITCH) &&
          (*i)->get<Int>(PITCH) == pitch) {

          if ((*i)->getAbsoluteTime() < time &&
            (*i)->isa(Note::EventType)) {
            if ((*i)->getAbsoluteTime() + (*i)->getDuration() > time) {
                startTime = (*i)->getAbsoluteTime();
            } else {
                break;
            }
          }
      }
    }

    return startTime;
}

timeT
MatrixPercussionInsertionCommand::getEndTime(Segment &segment,
                                   Rosegarden::timeT time,
                                   Rosegarden::Event &event)
{
    Rosegarden::timeT endTime =
      time + Rosegarden::Note(Rosegarden::Note::Semibreve,
                        0).getDuration();
    Rosegarden::timeT barEndTime = segment.getBarEndForTime(time);
    Rosegarden::timeT segmentEndTime = segment.getEndMarkerTime();

    if (barEndTime > endTime) endTime = barEndTime;
    if (endTime > segmentEndTime) endTime = segmentEndTime;

    int pitch = 0;
    if (event.has(PITCH)) {
      pitch = event.get<Int>(PITCH);
    }

    for (Segment::iterator i = segment.findTime(time);
       segment.isBeforeEndMarker(i); ++i) {

      if ((*i)->has(PITCH) &&
          (*i)->get<Int>(PITCH) == pitch) {

          if ((*i)->getAbsoluteTime() > time &&
            (*i)->isa(Rosegarden::Note::EventType)) {
            endTime = (*i)->getAbsoluteTime();
          }
      }
    }

    Rosegarden::Composition *comp = segment.getComposition();
    std::pair<Rosegarden::timeT, Rosegarden::timeT> barRange =
      comp->getBarRangeForTime(time);
    Rosegarden::timeT barDuration = barRange.second - barRange.first;

    
    if (endTime > time + barDuration) {
      endTime = time + barDuration;
    }

    return endTime;
}



MatrixEraseCommand::MatrixEraseCommand(Segment &segment,
                                       Event *event) :
    BasicCommand(i18n("Erase Note"),
                 segment,
             event->getAbsoluteTime(),
             event->getAbsoluteTime() + event->getDuration(),
             true),
    m_event(event),
    m_relayoutEndTime(getEndTime())
{
    // nothing
}

timeT MatrixEraseCommand::getRelayoutEndTime()
{
    return m_relayoutEndTime;
}

void MatrixEraseCommand::modifySegment()
{
    Rosegarden::SegmentMatrixHelper helper(getSegment());

    std::string eventType = m_event->getType();

    if (eventType == Note::EventType) {

      helper.deleteNote(m_event, false);

    }
}

MatrixModifyCommand::MatrixModifyCommand(Segment &segment,
                                         Rosegarden::Event *oldEvent,
                                         Rosegarden::Event *newEvent,
                                         bool isMove,
                               bool normalize):
      BasicCommand((isMove ? i18n("Move Note") : i18n("Modify Note")),
                   segment,
                   std::min(newEvent->getAbsoluteTime(),
                            oldEvent->getAbsoluteTime()), 
                   std::max(oldEvent->getAbsoluteTime() +
                            oldEvent->getDuration(), 
                            newEvent->getAbsoluteTime() +
                            newEvent->getDuration()),
                   true),
      m_normalize(normalize),
      m_oldEvent(oldEvent),
      m_newEvent(newEvent)
{
}

void MatrixModifyCommand::modifySegment()
{
    std::string eventType = m_oldEvent->getType();

    if (eventType == Note::EventType) {

      timeT normalizeStart = std::min(m_newEvent->getAbsoluteTime(),
                              m_oldEvent->getAbsoluteTime());

      timeT normalizeEnd = std::max(m_newEvent->getAbsoluteTime() +
                              m_newEvent->getDuration(),
                              m_oldEvent->getAbsoluteTime() +
                              m_oldEvent->getDuration());

        Segment &segment(getSegment());
        segment.insert(m_newEvent);
        segment.eraseSingle(m_oldEvent);

      if (m_normalize) {
          segment.normalizeRests(normalizeStart, normalizeEnd);
      }
    }
}

Generated by  Doxygen 1.6.0   Back to index