void MupExporter::writeClefAndKey(std::ofstream &str, TrackId trackNo) { Composition *c = m_composition; for (Composition::iterator i = c->begin(); i != c->end(); ++i) { if ((*i)->getTrack() == trackNo) { Clef clef((*i)->getClefAtTime((*i)->getStartTime())); Rosegarden::Key key((*i)->getKeyAtTime((*i)->getStartTime())); str << "staff " << trackNo + 1 << "\n"; if (clef.getClefType() == Clef::Treble) { str << "\tclef=treble\n"; } else if (clef.getClefType() == Clef::Alto) { str << "\tclef=alto\n"; } else if (clef.getClefType() == Clef::Tenor) { str << "\tclef=tenor\n"; } else if (clef.getClefType() == Clef::Bass) { str << "\tclef=bass\n"; } str << "\tkey=" << key.getAccidentalCount() << (key.isSharp() ? "#" : "&") << (key.isMinor() ? "minor" : "major") << std::endl; m_clefKeyMap[trackNo] = ClefKeyPair(clef, key); return ; } } }
QStringList ProjectPackager::getAudioFiles() { QStringList list; // get the Composition from the document, so we can iterate through it Composition *comp = &m_doc->getComposition(); // We don't particularly care about tracks here, so just iterate through the // entire Composition to find the audio segments and get the associated // file IDs from which to obtain a list of actual files. This could // conceivably pick up audio segments that are residing on MIDI tracks and // wouldn't otherwise be functional, but the important thing is to never // miss a single file that has any chance of being worth preserving. for (Composition::iterator i = comp->begin(); i != comp->end(); ++i) { if ((*i)->getType() == Segment::Audio) { AudioFileManager *manager = &m_doc->getAudioFileManager(); unsigned int id = (*i)->getAudioFileId(); AudioFile *file = manager->getAudioFile(id); // some polite sanity checking to avoid possible crashes if (!file) continue; list << file->getFilename(); } } // QStringList::removeDuplicates() would have been easy, but it's only in Qt // 4.5.0 and up. So here's the algorithm from Qt 4.5.0, courtesy of (and // originally Copyright 2009) Nokia QStringList *that = &list; int n = that->size(); int j = 0; QSet<QString> seen; seen.reserve(n); for (int i = 0; i < n; ++i) { const QString &s = that->at(i); if (seen.contains(s)) continue; seen.insert(s); if (j != i) (*that)[j] = s; ++j; } if (n != j) that->erase(that->begin() + j, that->end()); // return n - j; return list; }
bool MupExporter::write() { Composition *c = m_composition; std::ofstream str(m_fileName.c_str(), std::ios::out); if (!str) { std::cerr << "MupExporter::write() - can't write file " << m_fileName << std::endl; return false; } str << "score\n"; str << "\tstaffs=" << c->getNbTracks() << "\n"; int ts = c->getTimeSignatureCount(); std::pair<timeT, TimeSignature> tspair; if (ts > 0) tspair = c->getTimeSignatureChange(0); str << "\ttime=" << tspair.second.getNumerator() << "/" << tspair.second.getDenominator() << "\n"; for (int barNo = -1; barNo < c->getNbBars(); ++barNo) { for (TrackId trackNo = c->getMinTrackId(); trackNo <= c->getMaxTrackId(); ++trackNo) { if (barNo < 0) { writeClefAndKey(str, trackNo); continue; } if (barNo == 0 && trackNo == 0) { str << "\nmusic\n"; } str << "\t" << trackNo + 1 << ":"; Segment *s = 0; timeT barStart = c->getBarStart(barNo); timeT barEnd = c->getBarEnd(barNo); for (Composition::iterator ci = c->begin(); ci != c->end(); ++ci) { if ((*ci)->getTrack() == trackNo && (*ci)->getStartTime() < barEnd && (*ci)->getEndMarkerTime() > barStart) { s = *ci; break; } } TimeSignature timeSig(c->getTimeSignatureAt(barStart)); if (!s) { // write empty bar writeInventedRests(str, timeSig, 0, barEnd - barStart); continue; } if (s->getStartTime() > barStart) { writeInventedRests(str, timeSig, 0, s->getStartTime() - barStart); } // Mup insists that every bar has the correct duration, and won't // recover if one goes wrong. Keep careful tabs on this: it means // that for example we have to round chord durations down where // the next chord starts too soon //!!! we _really_ can't cope with time sig changes yet! timeT writtenDuration = writeBar(str, c, s, barStart, barEnd, timeSig, trackNo); if (writtenDuration < timeSig.getBarDuration()) { RG_DEBUG << "writtenDuration: " << writtenDuration << ", bar duration " << timeSig.getBarDuration() << endl; writeInventedRests(str, timeSig, writtenDuration, timeSig.getBarDuration() - writtenDuration); } else if (writtenDuration > timeSig.getBarDuration()) { std::cerr << "WARNING: overfull bar in Mup export: duration " << writtenDuration << " into bar of duration " << timeSig.getBarDuration() << std::endl; //!!! warn user } str << "\n"; } if (barNo >= 0) str << "bar" << std::endl; } str << "\n" << std::endl; str.close(); return true; }