diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 9cfa7322f..ad476b607 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -1,7 +1,7 @@ ####################################### # CMAKE guidolib ####################################### -cmake_minimum_required(VERSION 3.4) +cmake_minimum_required(VERSION 3.5) project(guidolib) set (CMAKE_BUILD_TYPE Release) @@ -66,9 +66,9 @@ if(APPLE) set (IOS_DEPLOYMENT_TARGET 10.0) else () message (STATUS "Generates Mac OS project- Use -DIOS=yes to change.") - set (CMAKE_CXX_FLAGS -mmacosx-version-min=10.13) + set (CMAKE_CXX_FLAGS -mmacosx-version-min=12.00) # set (CMAKE_LDFLAGS -mmacosx-version-min=10.13) - set (CMAKE_OSX_DEPLOYMENT_TARGET 10.13) + set (CMAKE_OSX_DEPLOYMENT_TARGET 13.0) # set (MACOSX_DEPLOYMENT_TARGET 10.13) endif () endif() diff --git a/build/tools/CMakeLists.txt b/build/tools/CMakeLists.txt index 97787af40..ceb65953f 100644 --- a/build/tools/CMakeLists.txt +++ b/build/tools/CMakeLists.txt @@ -2,7 +2,7 @@ # CMAKE guidotools ####################################### project(guidotools) -cmake_minimum_required(VERSION 3.4) +cmake_minimum_required(VERSION 3.5) set (CMAKE_BUILD_TYPE Release) diff --git a/src/engine/graphic/GRMusic.cpp b/src/engine/graphic/GRMusic.cpp index f663d5707..2fbcffe10 100644 --- a/src/engine/graphic/GRMusic.cpp +++ b/src/engine/graphic/GRMusic.cpp @@ -266,7 +266,7 @@ void GRMusic::pagetrace(VGDevice & hdc) const GRSystem* sys = (*sysl)[j]; const StaffVector * staves = sys->getStaves(); if (staves) { - for (int i = staves->GetMinimum(); i <= staves->GetMaximum(); i++) { + for (int i = staves->GetMinimum(); i < staves->GetMaximum(); i++) { const GRStaff * staff = staves->Get(i); if (staff) { cerr << "staff --- " << i << endl; @@ -684,6 +684,28 @@ float GRMusic::getStaffSize(int staffNum) { return fStaffSizes[staffNum]; } +//------------------------------------------------------------------------------- +GRStaff* GRMusic::getStaff(int staffNum, TYPE_TIMEPOSITION at) +{ + for (auto p: mPages) { + for (auto s: *(p->getSystems())) { + const StaffVector * staves = s->getStaves(); + if (staves) { + int n = 1; + for (int i = staves->GetMinimum(); i <= staves->GetMaximum(); i++) { + const GRStaff * staff = staves->Get(i); + TYPE_TIMEPOSITION start = staff->getRelativeTimePosition(); + TYPE_TIMEPOSITION end = staff->getRelativeEndTimePosition(); + if ((n == staffNum) && (start <= at) && (end >= at) && (start != end)) + return staves->Get(i); + n++; + } + } + } + } + return nullptr; +} + //------------------------------------------------------------------------------- ARMusicalVoice* GRMusic::getARVoice (int n) { diff --git a/src/engine/graphic/GRMusic.h b/src/engine/graphic/GRMusic.h index bcb16827c..f7e5a76f0 100644 --- a/src/engine/graphic/GRMusic.h +++ b/src/engine/graphic/GRMusic.h @@ -114,6 +114,8 @@ class GRMusic : public GREvent void setStaffSize(int staffNum, float size); float getStaffSize(int staffNum); + + GRStaff* getStaff(int staffNum, TYPE_TIMEPOSITION date); std::vector getCollisions() const { return fCollisions.list(); } diff --git a/src/engine/graphic/GROctava.cpp b/src/engine/graphic/GROctava.cpp index edc40e743..a454810f0 100644 --- a/src/engine/graphic/GROctava.cpp +++ b/src/engine/graphic/GROctava.cpp @@ -65,6 +65,11 @@ GROctava::~GROctava() { } +void GROctava::accept (GRVisitor& visitor) { + visitor.visitStart (this); + visitor.visitEnd (this); +} + bool GROctava::DeleteStaff(GRStaff * grstaff) { delete mAssociated; // makes sure that associated notes are deleted before the GROctava diff --git a/src/engine/graphic/GROctava.h b/src/engine/graphic/GROctava.h index 38a799b12..dffc2cc07 100644 --- a/src/engine/graphic/GROctava.h +++ b/src/engine/graphic/GROctava.h @@ -21,6 +21,7 @@ #include "TagParameterString.h" #include "GRARNotationElement.h" #include "GRPositionTag.h" +#include "GRVisitor.h" class NVstring; class GRStaff; @@ -36,11 +37,13 @@ class GROctava : public GRARNotationElement, public GRPositionTag GROctava( GRStaff *, const NVstring & txt, const AROctava* ar, bool bassa ); virtual ~GROctava(); + virtual void accept (GRVisitor& visitor); virtual void tellPosition(GObject *caller, const NVPoint & ); virtual void OnDraw( VGDevice & hdc ) const; virtual void setColRef(const TagParameterString *tps); virtual bool DeleteStaff(GRStaff * grstaff); + virtual int getOctava() const { return fOctava; }; private: typedef struct segment { diff --git a/src/engine/graphic/GRStaff.cpp b/src/engine/graphic/GRStaff.cpp index 1e0fc0dbf..1125aa839 100644 --- a/src/engine/graphic/GRStaff.cpp +++ b/src/engine/graphic/GRStaff.cpp @@ -677,6 +677,7 @@ void GRStaff::accept (GRVisitor& visitor) GuidoPos pos = elts->GetHeadPosition(); while (pos) { GRNotationElement * e = elts->GetNext(pos); +cerr << "GRStaff::accept " << e << endl; e->accept (visitor); } visitor.visitEnd (this); @@ -902,12 +903,20 @@ float GRStaff::getKeyPosition(TYPE_PITCH pit, int numkeys) const /** \brief Returns the graphical y-position of a note. Idea: Each clef has a root-note (violin- - clef has G, base-clef has F) and a + clef has G, base-clef has F) and a corresponding staff line - */ float GRStaff::getNotePosition(TYPE_PITCH pit, TYPE_REGISTER oct) const { +//cerr << "GRStaff::getNotePosition " << pit << " " << oct << " state: " << mStaffState.basepit << " " << mStaffState.baseline << " " << mStaffState.baseoct << endl; + return getNotePosition(pit, oct, mStaffState.basepit, mStaffState.baseline, mStaffState.baseoct); +} + +// ---------------------------------------------------------------------------- +/** \brief Returns the graphical y-position of a note. +*/ +float GRStaff::getNotePosition(TYPE_PITCH pit, TYPE_REGISTER oct, int basePitch, int baseLine, int baseOct) const +{ // redundant correction of octave: already shifted when the GRNote is created // oct -= mStaffState.octava; // depends on current clef. @@ -915,18 +924,18 @@ float GRStaff::getNotePosition(TYPE_PITCH pit, TYPE_REGISTER oct) const float calc = 0; if (pit >= NOTE_C && pit <= NOTE_H) { - calc = (float)((mStaffState.basepit - pit ) * myHalfSpace + mStaffState.baseline * getStaffLSPACE() - - ((int)oct - mStaffState.baseoct) * (7 * myHalfSpace)); + calc = (float)((basePitch - pit ) * myHalfSpace + baseLine * getStaffLSPACE() - + ((int)oct - baseOct) * (7 * myHalfSpace)); } else if (pit>= NOTE_CIS && pit <= NOTE_DIS) { - calc = (float)((mStaffState.basepit - (pit - 7) )* myHalfSpace + mStaffState.baseline * getStaffLSPACE()- - ((int)oct - mStaffState.baseoct) * (7 * myHalfSpace)); + calc = (float)((basePitch - (pit - 7) )* myHalfSpace + baseLine * getStaffLSPACE()- + ((int)oct - baseOct) * (7 * myHalfSpace)); } else if (pit>= NOTE_FIS && pit <= NOTE_AIS) { - calc = (float)((mStaffState.basepit - (pit - 6) )* myHalfSpace + mStaffState.baseline * getStaffLSPACE() - - ((int)oct - mStaffState.baseoct) * (7 * myHalfSpace)); + calc = (float)((basePitch - (pit - 6) )* myHalfSpace + baseLine * getStaffLSPACE() - + ((int)oct - baseOct) * (7 * myHalfSpace)); } return calc; } diff --git a/src/engine/graphic/GRStaff.h b/src/engine/graphic/GRStaff.h index c048974ff..88cd72aed 100644 --- a/src/engine/graphic/GRStaff.h +++ b/src/engine/graphic/GRStaff.h @@ -208,6 +208,7 @@ class GRStaff : public GRCompositeNotationElement const ARMeter * getCurMeter() const { return mStaffState.curmeter; } virtual float getNotePosition(TYPE_PITCH pit, TYPE_REGISTER oct) const; + virtual float getNotePosition(TYPE_PITCH pit, TYPE_REGISTER oct, int basePitch, int baseLine, int baseOct) const; virtual GDirection getDefaultThroatDirection(TYPE_PITCH pit, TYPE_REGISTER oct) const; virtual int getNumHelplines(TYPE_PITCH pit, TYPE_REGISTER oct) const; virtual VGColor getNoteColor(TYPE_PITCH pit) const; diff --git a/src/engine/include/GUIDOEngine.h b/src/engine/include/GUIDOEngine.h index 30f6f078b..23b5eefe9 100644 --- a/src/engine/include/GUIDOEngine.h +++ b/src/engine/include/GUIDOEngine.h @@ -576,6 +576,18 @@ as by date. Page numbers start at 1. */ GUIDOAPI GuidoErrCode GuidoGetPageDate( CGRHandler inHandleGR, int pageNum, GuidoDate* date); + /** \brief Gives a pitch position on a staff. + + \param inHandleGR a Guido opaque handle to a GR structure. + \param staff a staff number (starts at 1). + \param pitch a midi pitch + \param date the target date + \param x on output: the x position + \param y on output: the y position + \return a Guido error code. + */ + GUIDOAPI GuidoErrCode GuidoGetPitchPos( CGRHandler inHandleGR, int staff, int pitch, GuidoDate date, float& x, float& y); + /** \brief Gives the current meter on a given date and voice. diff --git a/src/engine/lib/GUIDOEngine.cpp b/src/engine/lib/GUIDOEngine.cpp index 199110c29..2bc673960 100644 --- a/src/engine/lib/GUIDOEngine.cpp +++ b/src/engine/lib/GUIDOEngine.cpp @@ -67,6 +67,8 @@ using namespace std; #include "GRShowVisitor.h" #include "TagParametersMaps.h" +#include "GRPitchYVisitor.h" + //#include "GMNCodePrintVisitor.h" @@ -336,6 +338,16 @@ GUIDOAPI GuidoErrCode GuidoAR2GR( ARHandler ar, const GuidoLayoutSettings * sett GRHandler grh = CreateGr (ar, gARPageFormat, settings); if (!gr) return guidoErrMemory; *gr = grh; + + float x, y; + GuidoDate date; + date.num = 3; + date.denom = 1; + GuidoErrCode err = GuidoGetPitchPos (grh, 1, 60, date, x, y); + if (err != guidoNoErr) +cerr << "GuidoAR2GR GuidoGetPitchPos err " << err << endl; +else +cerr << "GuidoAR2GR GuidoGetPitchPos at " << date << " : " << x << " " << y << endl; return guidoNoErr; } @@ -617,6 +629,27 @@ GUIDOAPI GuidoErrCode GuidoGetPageDate( CGRHandler inHandleGR, int pageNum, Guid return result ? guidoNoErr : guidoErrBadParameter; } +// -------------------------------------------------------------------------- +// introduced in guido 1.71 [DF Nov 30 2023] +GUIDOAPI GuidoErrCode GuidoGetPitchPos( CGRHandler inHandleGR, int staffnum, int pitch, GuidoDate date, float& x, float& y) +{ + if ( ( !inHandleGR ) || ( !inHandleGR->grmusic ) ) + return guidoErrInvalidHandle; + + TYPE_TIMEPOSITION tp (date.num, date.denom); + GRStaff* staff = inHandleGR->grmusic->getStaff (staffnum, tp); + if (!staff) + return guidoErrBadParameter; + + GRPitchYVisitor v; + NVPoint p = v.getPitchPos (staff, pitch, tp); + if (!p.x) + return guidoErrBadParameter; + x = p.x; + y = p.y; + return guidoNoErr; +} + // -------------------------------------------------------------------------- // introduced in guido 1.63 [DF July 1 2016] GUIDOAPI GuidoErrCode GuidoGetMeterAt (CARHandler inHandleAR, int voicenum, const GuidoDate &date, GuidoMeter& meter) diff --git a/src/engine/operations/GRPitchYVisitor.cpp b/src/engine/operations/GRPitchYVisitor.cpp new file mode 100644 index 000000000..91d1a20cb --- /dev/null +++ b/src/engine/operations/GRPitchYVisitor.cpp @@ -0,0 +1,93 @@ +/* + GUIDO Library + Copyright (C) 2023 D. Fober + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#include + +#include "GRPitchYVisitor.h" + +#include "GuidoDefs.h" +#include "GRClef.h" +#include "GREmpty.h" +#include "GROctava.h" +#include "GREvent.h" +#include "GRSingleNote.h" +#include "GRSingleRest.h" +#include "GRStaff.h" + +using namespace std; + +//------------------------------------------------------------------------------- +NVPoint GRPitchYVisitor::getPitchPos (GRStaff* staff, int midipitch, TYPE_TIMEPOSITION date) +{ + fBasePitch = NOTE_G; + fBaseLine = 3; + fBaseOct = 1; + fOctava = 0; + fTargetDate = date; + fLastDate = -1; + fLastX = -1; + fDone = false; + staff->accept (*this); + NVPoint p; + if (fDone) { + // convert midi pitch in pitch class and octava + int oct = (midipitch / 12) - 4; + int pitch = midipitch % 12; + pitch = ((pitch < 5) ? (pitch / 2) : (pitch+1) / 2) + 2; +cerr << "GRPitchYVisitor::getPitchPos " << pitch << " " << oct << " date: " << date << endl; + float y = staff->getNotePosition ( pitch, oct, fBasePitch, fBaseLine, fBaseOct); + p.x = fLastX; + p.y = y; + } +cerr << " resultat : " << p << endl; + return p; +} + +//------------------------------------------------------------------------------- +void GRPitchYVisitor::visitStart (GRSingleNote* o) +{ + if (fDone) return; +cerr << "GRPitchYVisitor::visitStart GRSingleNote " << o << endl; + TYPE_TIMEPOSITION date = o->getRelativeTimePosition(); + if (date > fTargetDate) fDone = true; + else fLastX = o->getPosition().x; +} + +//------------------------------------------------------------------------------- +void GRPitchYVisitor::visitStart (GREmpty* o) +{ + if (fDone) return; +cerr << "GRPitchYVisitor::visitStart GREmpty " << o << endl; + TYPE_TIMEPOSITION date = o->getRelativeTimePosition(); + if (date > fTargetDate) fDone = true; + else fLastX = o->getPosition().x; +} + +//------------------------------------------------------------------------------- +void GRPitchYVisitor::visitStart (GRSingleRest* o) +{ + if (fDone) return; +cerr << "GRPitchYVisitor::visitStart GRSingleRest " << o << endl; + TYPE_TIMEPOSITION date = o->getRelativeTimePosition(); + if (date > fTargetDate) fDone = true; + else fLastX = o->getPosition().x; +} + +void GRPitchYVisitor::visitStart (GRClef* o) +{ + if (fDone) return; + fBasePitch = o->getBasePitch(); + fBaseOct = o->getBaseOct(); +} + +void GRPitchYVisitor::visitStart (GROctava* o) +{ + if (fDone) return; + fOctava = o->getOctava(); +} diff --git a/src/engine/operations/GRPitchYVisitor.h b/src/engine/operations/GRPitchYVisitor.h new file mode 100644 index 000000000..5c98e22ae --- /dev/null +++ b/src/engine/operations/GRPitchYVisitor.h @@ -0,0 +1,44 @@ +/* + GUIDO Library + Copyright (C) 2023 D. Fober + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#ifndef ___GRPitchYVisitor___ +#define ___GRPitchYVisitor___ + +#include "defines.h" +#include "GUIDOEngine.h" +#include "GRVisitor.h" +#include "NVPoint.h" + +class GRPitchYVisitor : public GRVisitor +{ + int fBasePitch; + int fBaseLine; + int fBaseOct; + int fOctava; + float fLastX; + TYPE_TIMEPOSITION fLastDate = 0; + TYPE_TIMEPOSITION fTargetDate = 0; + bool fDone = false; + + public: + GRPitchYVisitor() {} + virtual ~GRPitchYVisitor() {} + + NVPoint getPitchPos (GRStaff* staff, int pitch, TYPE_TIMEPOSITION date); + + virtual bool voiceMode () { return true; } + + virtual void visitStart (GRClef* o); + virtual void visitStart (GROctava* o); + virtual void visitStart (GRSingleNote* o); + virtual void visitStart (GRSingleRest* o); + virtual void visitStart (GREmpty* o); +}; + +#endif diff --git a/src/engine/operations/GRVisitor.h b/src/engine/operations/GRVisitor.h index 7503e2d6a..d7a87bcdc 100644 --- a/src/engine/operations/GRVisitor.h +++ b/src/engine/operations/GRVisitor.h @@ -25,6 +25,7 @@ class GRIntens; class GRKey; class GRMeter; class GRMusic; +class GROctava; class GRPage; class GRRange; class GRSingleNote; @@ -105,6 +106,9 @@ class GRVisitor virtual void visitStart (GRSingleRest* o) {} virtual void visitEnd (GRSingleRest* o) {} + + virtual void visitStart (GROctava* o) {} + virtual void visitEnd (GROctava* o) {} }; #endif