1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 2 3 /* 4 Rosegarden 5 A MIDI and audio sequencer and musical notation editor. 6 Copyright 2000-2021 the Rosegarden development team. 7 8 Other copyrights also apply to some parts of this work. Please 9 see the AUTHORS file and individual file headers for details. 10 11 This program is free software; you can redistribute it and/or 12 modify it under the terms of the GNU General Public License as 13 published by the Free Software Foundation; either version 2 of the 14 License, or (at your option) any later version. See the file 15 COPYING included with this distribution for more information. 16 */ 17 18 #include "Chord.h" 19 #include "base/Event.h" 20 #include "misc/Strings.h" 21 22 #include <QString> 23 #include <QRegularExpression> 24 25 namespace Rosegarden 26 { 27 28 namespace Guitar 29 { 30 const std::string Chord::EventType = "guitarchord"; 31 const short Chord::EventSubOrdering = -60; 32 33 static const PropertyName RootPropertyName = "root"; 34 static const PropertyName ExtPropertyName = "ext"; 35 static const PropertyName FingeringPropertyName = "fingering"; 36 37 Chord::Chord() 38 : m_isUserChord(false) 39 { 40 } 41 42 Chord::Chord(const QString& root, const QString& ext) 43 : m_root(root), 44 m_ext(ext), 45 m_isUserChord(false) 46 { 47 if (m_ext.isEmpty()) 48 m_ext = QString(); 49 } 50 51 Chord::Chord(const Event& e) 52 : m_isUserChord(false) 53 { 54 std::string f; 55 bool ok; 56 57 ok = e.get<String>(RootPropertyName, f); 58 if (ok) 59 m_root = strtoqstr(f); 60 61 ok = e.get<String>(ExtPropertyName, f); 62 if (ok) { 63 if (f.length() == 0) 64 m_ext = QString(); 65 else 66 m_ext = strtoqstr(f); 67 } 68 69 ok = e.get<String>(FingeringPropertyName, f); 70 if (ok) { 71 QString qf(strtoqstr(f)); 72 QString errString; 73 74 Fingering fingering = Fingering::parseFingering(qf, errString); 75 setFingering(fingering); 76 } 77 } 78 79 Event* Chord::getAsEvent(timeT absoluteTime) const 80 { 81 Event *e = new Event(EventType, absoluteTime, 0, EventSubOrdering); 82 e->set<String>(RootPropertyName, qstrtostr(m_root)); 83 e->set<String>(ExtPropertyName, qstrtostr(m_ext)); 84 e->set<String>(FingeringPropertyName, getFingering().toString()); 85 return e; 86 } 87 88 bool Chord::hasAltBass() const 89 { 90 static const QRegularExpression ALT_BASS_REGEXP("/[A-G]"); 91 return m_ext.contains(ALT_BASS_REGEXP); 92 } 93 94 bool operator<(const Chord& a, const Chord& b) 95 { 96 if (a.m_root != b.m_root) { 97 return a.m_root < b.m_root; 98 } else if (a.m_ext != b.m_ext) { 99 if (a.m_ext.isEmpty()) // chords with no ext need to be stored first 100 return true; 101 if (b.m_ext.isEmpty()) 102 return false; 103 return a.m_ext < b.m_ext; 104 } else { 105 return a.m_fingering < b.m_fingering; 106 } 107 108 } 109 110 } 111 112 ROSEGARDENPRIVATE_EXPORT QDebug &operator<<(QDebug &dbg, const Rosegarden::Guitar::Chord &c) 113 { 114 dbg << "Chord root = " << c.getRoot() << ", ext = '" << c.getExt() << "'"; 115 116 // for(unsigned int i = 0; i < c.getNbFingerings(); ++i) { 117 // dbg << "\nFingering " << i << " : " << c.getFingering(i).toString().c_str(); 118 // } 119 120 Rosegarden::Guitar::Fingering f = c.getFingering(); 121 122 dbg << ", fingering : "; 123 124 for(unsigned int j = 0; j < 6; ++j) { 125 int pos = f[j]; 126 if (pos >= 0) 127 dbg << pos << ' '; 128 else 129 dbg << "x "; 130 } 131 return dbg; 132 } 133 134 } 135