bool NoteTrack::HandleXMLTag(const wxChar *tag, const wxChar **attrs) { if (!wxStrcmp(tag, wxT("notetrack"))) { while (*attrs) { const wxChar *attr = *attrs++; const wxChar *value = *attrs++; if (!value) break; const wxString strValue = value; long nValue; double dblValue; if (!wxStrcmp(attr, wxT("name")) && XMLValueChecker::IsGoodString(strValue)) mName = strValue; else if (!wxStrcmp(attr, wxT("offset")) && XMLValueChecker::IsGoodString(strValue) && Internat::CompatibleToDouble(strValue, &dblValue)) SetOffset(dblValue); else if (!wxStrcmp(attr, wxT("visiblechannels"))) { if (!XMLValueChecker::IsGoodInt(strValue) || !strValue.ToLong(&nValue) || !XMLValueChecker::IsValidVisibleChannels(nValue)) return false; mVisibleChannels = nValue; } else if (!wxStrcmp(attr, wxT("height")) && XMLValueChecker::IsGoodInt(strValue) && strValue.ToLong(&nValue)) mHeight = nValue; else if (!wxStrcmp(attr, wxT("minimized")) && XMLValueChecker::IsGoodInt(strValue) && strValue.ToLong(&nValue)) mMinimized = (nValue != 0); else if (!wxStrcmp(attr, wxT("isSelected")) && XMLValueChecker::IsGoodInt(strValue) && strValue.ToLong(&nValue)) this->SetSelected(nValue != 0); #ifdef EXPERIMENTAL_MIDI_OUT else if (!wxStrcmp(attr, wxT("velocity")) && XMLValueChecker::IsGoodString(strValue) && Internat::CompatibleToDouble(strValue, &dblValue)) mGain = (float) dblValue; #endif else if (!wxStrcmp(attr, wxT("bottomnote")) && XMLValueChecker::IsGoodInt(strValue) && strValue.ToLong(&nValue)) SetBottomNote(nValue); else if (!wxStrcmp(attr, wxT("data"))) { std::string s(strValue.mb_str(wxConvUTF8)); std::istringstream data(s); mSeq = new Alg_seq(data, false); } } // while return true; } return false; }
// Zoom the note track, centering the pitch at centerY, // amount is 1 for zoom in, and -1 for zoom out void NoteTrack::Zoom(int centerY, int amount) { // Construct track rectangle to map pitch to screen coordinates // Only y and height are needed: wxRect trackRect(0, GetY(), 1, GetHeight()); PrepareIPitchToY(trackRect); int centerPitch = YToIPitch(centerY); // zoom out by changing the pitch height -- a small integer mPitchHeight += amount; if (mPitchHeight <= 0) mPitchHeight = 1; PrepareIPitchToY(trackRect); // update because mPitchHeight changed int newCenterPitch = YToIPitch(GetY() + GetHeight() / 2); // center the pitch that the user clicked on SetBottomNote(mBottomNote + (centerPitch - newCenterPitch)); }
Track::Holder NoteTrack::Duplicate() const { auto duplicate = std::make_unique<NoteTrack>(mDirManager); duplicate->Init(*this); // Duplicate on NoteTrack moves data from mSeq to mSerializationBuffer // and from mSerializationBuffer to mSeq on alternate calls. Duplicate // to the undo stack and Duplicate back to the project should result // in serialized blobs on the undo stack and traversable data in the // project object. if (mSeq) { SonifyBeginSerialize(); assert(!mSerializationBuffer); // serialize from this to duplicate's mSerializationBuffer mSeq->serialize((void**)&duplicate->mSerializationBuffer, &duplicate->mSerializationLength); SonifyEndSerialize(); } else if (mSerializationBuffer) { SonifyBeginUnserialize(); assert(!mSeq); Alg_track_ptr alg_track = Alg_seq::unserialize(mSerializationBuffer, mSerializationLength); assert(alg_track->get_type() == 's'); duplicate->mSeq = (Alg_seq_ptr) alg_track; SonifyEndUnserialize(); } else assert(false); // bug if neither mSeq nor mSerializationBuffer // copy some other fields here duplicate->SetBottomNote(mBottomNote); duplicate->SetPitchHeight(mPitchHeight); duplicate->mLastMidiPosition = mLastMidiPosition; duplicate->mVisibleChannels = mVisibleChannels; duplicate->SetOffset(GetOffset()); #ifdef EXPERIMENTAL_MIDI_OUT duplicate->SetGain(GetGain()); #endif return std::move(duplicate); }
void NoteTrack::VScroll(int start, int end) { int ph = GetPitchHeight(); int delta = ((end - start) + ph / 2) / ph; SetBottomNote(mStartBottomNote + delta); }