Logo Search packages:      
Sourcecode: rosegarden version File versions

Clipboard.cpp

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

/*
    Rosegarden
    A sequencer and musical notation editor.

    This program is Copyright 2000-2007
        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 "Clipboard.h"
#include "Selection.h"

namespace Rosegarden
{

Clipboard::Clipboard() :
    m_partial(false),
    m_haveTimeSigSelection(false),
    m_haveTempoSelection(false),
    m_nominalStart(0),
    m_nominalEnd(0)
{
    // nothing
}

Clipboard::Clipboard(const Clipboard &c) :
    m_partial(false)
{
    copyFrom(&c);
}

Clipboard &
Clipboard::operator=(const Clipboard &c)
{
    copyFrom(&c);
    return *this;
}

Clipboard::~Clipboard()
{
    clear();
}

void
00057 Clipboard::clear()
{
    for (iterator i = begin(); i != end(); ++i) {
      delete *i;
    }
    m_segments.clear();
    clearTimeSignatureSelection();
    clearTempoSelection();
    clearNominalRange();
    m_partial = false;
}

bool
00070 Clipboard::isEmpty() const
{
    return (m_segments.size() == 0 &&
          !m_haveTimeSigSelection &&
          !m_haveTempoSelection &&
          m_nominalStart == m_nominalEnd);
}

bool
00079 Clipboard::isSingleSegment() const
{
    return (m_segments.size() == 1 &&
          !m_haveTimeSigSelection &&
          !m_haveTempoSelection);
}

Segment *
00087 Clipboard::getSingleSegment() const
{
    if (isSingleSegment()) return *begin();
    else return 0;
}

bool
00094 Clipboard::isPartial() const
{
    return m_partial;
}

Segment *
00100 Clipboard::newSegment()
{
    Segment *s = new Segment();
    m_segments.insert(s);
    // don't change m_partial
    return s;
}

Segment *
00109 Clipboard::newSegment(const Segment *copyFrom)
{
    Segment *s = new Segment(*copyFrom);
    m_segments.insert(s);
    // don't change m_partial
    return s;
}

void
00118 Clipboard::newSegment(const Segment *copyFrom, timeT from, timeT to,
                  bool expandRepeats)
{
    // create with copy ctor so as to inherit track, instrument etc
    Segment *s = new Segment(*copyFrom);

    if (from <= s->getStartTime() && to >= s->getEndMarkerTime()) {
      m_segments.insert(s);
      s->setEndTime(s->getEndMarkerTime());
      // don't change m_partial
      return;
    }

    timeT segStart = copyFrom->getStartTime();
    timeT segEnd = copyFrom->getEndMarkerTime();
    timeT segDuration = segEnd - segStart;
    
    int firstRepeat = 0;
    int lastRepeat = 0;

    if (!copyFrom->isRepeating() || segDuration <= 0) {
      expandRepeats = false;
    }

    if (expandRepeats) {
      firstRepeat = (from - segStart) / segDuration;
      lastRepeat = (to - segStart) / segDuration;
      to = std::min(to, copyFrom->getRepeatEndTime());
    }

    s->setRepeating(false);
    
    if (s->getType() == Segment::Audio) {
      
      Composition *c = copyFrom->getComposition();

      for (int repeat = firstRepeat; repeat <= lastRepeat; ++repeat) {

          timeT wrappedFrom = segStart;
          timeT wrappedTo = segEnd;

          if (!expandRepeats) {
            wrappedFrom = from;
            wrappedTo = to;
          } else {
            if (repeat == firstRepeat) {
                wrappedFrom = segStart + (from - segStart) % segDuration;
            }
            if (repeat == lastRepeat) {
                wrappedTo = segStart + (to - segStart) % segDuration;
            }
          }

          if (wrappedFrom > segStart) {
            if (c) {
                s->setAudioStartTime
                  (s->getAudioStartTime() +
                   c->getRealTimeDifference(segStart + repeat * segDuration,
                                      from));
            }
            s->setStartTime(from);
          } else {
            s->setStartTime(segStart + repeat * segDuration);
          }

          if (wrappedTo < segEnd) {
            s->setEndMarkerTime(to);
            if (c) {
                s->setAudioEndTime
                  (s->getAudioStartTime() +
                   c->getRealTimeDifference(segStart + repeat * segDuration,
                                      to));
            }
          } else {
            s->setEndMarkerTime(segStart + (repeat + 1) * segDuration);
          }

          m_segments.insert(s);
          if (repeat < lastRepeat) {
            s = new Segment(*copyFrom);
            s->setRepeating(false);
          }
      }

      m_partial = true;
      return;
    }

    s->erase(s->begin(), s->end());

    for (int repeat = firstRepeat; repeat <= lastRepeat; ++repeat) {

      Segment::const_iterator ifrom = copyFrom->begin();
      Segment::const_iterator ito = copyFrom->end();

      if (!expandRepeats) {
          ifrom = copyFrom->findTime(from);
          ito = copyFrom->findTime(to);
      } else {
          if (repeat == firstRepeat) {
            ifrom = copyFrom->findTime
                (segStart + (from - segStart) % segDuration);
          }
          if (repeat == lastRepeat) {
            ito = copyFrom->findTime
                (segStart + (to - segStart) % segDuration);
          }
      }

      for (Segment::const_iterator i = ifrom;
           i != ito && copyFrom->isBeforeEndMarker(i); ++i) {

          timeT absTime = (*i)->getAbsoluteTime() + repeat * segDuration;
          timeT duration = (*i)->getDuration();

          Event *e = (*i)->copyMoving(repeat * segDuration);

          if (absTime + duration <= to) {

            s->insert(e);

          } else {

            s->insert(new Event(*e,
                            e->getAbsoluteTime(),
                            duration,
                            e->getSubOrdering(),
                            e->getNotationAbsoluteTime(),
                            e->getNotationDuration()));
            delete e;
          }
      }
    }

    // need to call getEndMarkerTime() on copyFrom, not on s, because
    // its return value may depend on the composition it's in
    if (copyFrom->getEndMarkerTime() > to) {
      s->setEndMarkerTime(to);
    }

    m_segments.insert(s);
    m_partial = true;
    return;
}

Segment *
00264 Clipboard::newSegment(const EventSelection *copyFrom)
{
    // create with copy ctor so as to inherit track, instrument etc
    Segment *s = new Segment(copyFrom->getSegment());
    s->erase(s->begin(), s->end());

    const EventSelection::eventcontainer &events(copyFrom->getSegmentEvents());
    for (EventSelection::eventcontainer::const_iterator i = events.begin();
       i != events.end(); ++i) {
      s->insert(new Event(**i));
    }

    m_segments.insert(s);
    m_partial = true;
    return s;
}

void
00282 Clipboard::setTimeSignatureSelection(const TimeSignatureSelection &ts)
{
    m_timeSigSelection = ts;
    m_haveTimeSigSelection = true;
}

void
00289 Clipboard::clearTimeSignatureSelection()
{
    m_timeSigSelection = TimeSignatureSelection();
    m_haveTimeSigSelection = false;
}

const TimeSignatureSelection &
00296 Clipboard::getTimeSignatureSelection() const
{
    return m_timeSigSelection;
}
 
void
00302 Clipboard::setTempoSelection(const TempoSelection &ts)
{
    m_tempoSelection = ts;
    m_haveTempoSelection = true;
}

void
00309 Clipboard::clearTempoSelection()
{
    m_tempoSelection = TempoSelection();
    m_haveTempoSelection = false;
}

const TempoSelection &
00316 Clipboard::getTempoSelection() const
{
    return m_tempoSelection;
}
    
void
00322 Clipboard::copyFrom(const Clipboard *c)
{
    if (c == this) return;
    clear();

    for (Clipboard::const_iterator i = c->begin(); i != c->end(); ++i) {
      newSegment(*i);
    }

    m_partial = c->m_partial;

    m_timeSigSelection = c->m_timeSigSelection;
    m_haveTimeSigSelection = c->m_haveTimeSigSelection;

    m_tempoSelection = c->m_tempoSelection;
    m_haveTempoSelection = c->m_haveTempoSelection;
    
    m_nominalStart = c->m_nominalStart;
    m_nominalEnd = c->m_nominalEnd;
}

timeT
00344 Clipboard::getBaseTime() const
{
    if (hasNominalRange()) {
      return m_nominalStart;
    }

    timeT t = 0;

    for (iterator i = begin(); i != end(); ++i) {
      if (i == begin() || (*i)->getStartTime() < t) {
          t = (*i)->getStartTime();
      }
    }

    if (m_haveTimeSigSelection && !m_timeSigSelection.empty()) {
      if (m_timeSigSelection.begin()->first < t) {
          t = m_timeSigSelection.begin()->first;
      }
    }

    if (m_haveTempoSelection && !m_tempoSelection.empty()) {
      if (m_tempoSelection.begin()->first < t) {
          t = m_tempoSelection.begin()->first;
      }
    }
    
    return t;
}

void
00374 Clipboard::setNominalRange(timeT start, timeT end)
{
    m_nominalStart = start;
    m_nominalEnd = end;
}

void
Clipboard::getNominalRange(timeT &start, timeT &end)
{
    start = m_nominalStart;
    end = m_nominalEnd;
}

}

Generated by  Doxygen 1.6.0   Back to index