//==============================================
// MuseScore
//
// Quena Notation plugin for MuseScore Ver. 2.0
//
// Copyright (C)2012-2015 Hiroshi Tachibana
//
//
// 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 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
//==============================================
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Layouts 1.1
import MuseScore 1.0
import FileIO 1.0
MuseScore {
menuPath: "Plugins.Quena Fingerings"
version: "2.0.02"
description: qsTr("Quena fingerings, Note names")
pluginType: "dialog"
id: window
width:285 // menu window size
height:285
ExclusiveGroup { id: exclusiveGroupKey }
property var fileExist :true
property var seplines
property var quenaLengthListInit : 12
property var fontListInit : 0
property var fontSizeInit : 16
property var yPositionInit : 0
property var xPositionInit : 0
property var partListInit : 0
property var colorListInit : 0
property var itemX1 : 10
property var itemX2 : 150
property var itemY1 : 10
property var itemDY : 25
RowLayout { //====================== Length
id: row0
x :itemX1
y :itemY1+itemDY*0
Label {
font.pointSize: 14
text: "Quena type"
}
}
RowLayout {
id: row0R
x :itemX2
y :itemY1+itemDY*0
ComboBox {
currentIndex: quenaLengthListInit
model: ListModel {
id: quenaLengthList
property var key
ListElement { text: "High G5"; fName: -12 }
ListElement { text: "High F#5"; fName: -11 }
ListElement { text: "High F5"; fName: -10 }
ListElement { text: "High E5"; fName: -9 }
ListElement { text: "High D#5"; fName: -8 }
ListElement { text: "High D5"; fName: -7 }
ListElement { text: "C#5"; fName: -6 }
ListElement { text: "C5"; fName: -5 }
ListElement { text: "B4"; fName: -4 }
ListElement { text: "A#4"; fName: -3 }
ListElement { text: "A4"; fName: -2 }
ListElement { text: "G#4"; fName: -1 }
ListElement { text: "G4 ====="; fName: 0 }
ListElement { text: "F#4"; fName: 1 }
ListElement { text: "F4"; fName: 2 }
ListElement { text: "E4"; fName: 3 }
ListElement { text: "D#4"; fName: 4 }
ListElement { text: "D4"; fName: 5 }
ListElement { text: "Low C#4 Low"; fName: 6 }
ListElement { text: "Low C4 Low"; fName: 7 }
ListElement { text: "Low B3 Low"; fName: 8 }
ListElement { text: "Low A#3 Low"; fName: 9 }
ListElement { text: "Low A3 Low"; fName: 10 }
ListElement { text: "Low G#3 Low"; fName: 11 }
ListElement { text: "Low G3 Low"; fName: 12 }
}
width: 100
onCurrentIndexChanged: {
// console.debug(quenaLengthList.get(currentIndex).text + ", " + quenaLengthList.get(currentIndex).fName)
// console.debug(", " + quenaLengthList.get(currentIndex).fName)
quenaLengthList.key = quenaLengthList.get(currentIndex).fName
}
} // end ComboBox
}
RowLayout { //====================== Font type, Fingering or Note name
id: row1
x :itemX1
y :itemY1+itemDY*1
Label {
font.pointSize: 14
text: "Display"
}
}
RowLayout {
id: row1R
x :itemX2
y :itemY1+itemDY*1
ComboBox {
currentIndex: fontListInit
model: ListModel {
id: fontList
property var key
ListElement { text: "DoReMi+Fingering"; fName:1 }
ListElement { text: "CDE+Fingering"; fName:2 }
ListElement { text: "Fingering"; fName:3 }
ListElement { text: "DoReMi"; fName:4 }
ListElement { text: "CDEFG"; fName:5 }
}
width: 100
onCurrentIndexChanged: {
console.debug("fontList "+fontList.get(currentIndex).text + ", " + fontList.get(currentIndex).fName)
fontList.key = fontList.get(currentIndex).fName
}
} // end ComboBox
}
RowLayout { //====================== FONT SIZE
id: row2
x :itemX1
y :itemY1+itemDY*2+5
Label {
font.pointSize: 14
text: "Font Size"
}
}
RowLayout {
id: row2R
x :itemX2
y :itemY1+itemDY*2+5
SpinBox {
id: valFontSize
implicitWidth: 55
decimals: 0
minimumValue: 4
maximumValue: 36
value: fontSizeInit
font.pointSize: 14
}
}
RowLayout { //====================== Y POSITION
id: row3
x :itemX1
y :itemY1+itemDY*3+5
Label {
font.pointSize: 14
text: "Y Position"
}
}
RowLayout {
id: row3R
x :itemX2
y :itemY1+itemDY*3+5
SpinBox {
id: valYPosition
implicitWidth: 55
decimals: 0
minimumValue: -20
maximumValue: 30
value: yPositionInit
font.pointSize: 14
}
}
RowLayout { //====================== X POSITION
id: row4
x :itemX1
y :itemY1+itemDY*4+40
Label {
font.pointSize: 14
text: "X Position"
}
}
RowLayout {
id: row4R
x :itemX2
y :itemY1+itemDY*4+40
SpinBox {
id: valXPosition
implicitWidth: 55
decimals: 1
minimumValue: -5
maximumValue: 5
value: xPositionInit
stepSize: 0.1
font.pointSize: 14
}
}
RowLayout { //====================== PART
id: row5
x :itemX1
y :itemY1+itemDY*5+40
Label {
font.pointSize: 14
text: "Part"
}
}
RowLayout {
id: row5R
x :itemX2
y :itemY1+itemDY*5+40
ComboBox {
currentIndex: partListInit
model: ListModel {
id: partList
property var key
ListElement { text: "Part 1"; pName: 0 }
ListElement { text: "Part 2"; pName: 1 }
ListElement { text: "Part 3"; pName: 2 }
ListElement { text: "Part 4"; pName: 3 }
}
width: 60
onCurrentIndexChanged: {
//console.debug(partList.get(currentIndex).text + ", " + partList.get(currentIndex).pName)
partList.key = partList.get(currentIndex).pName
}
} // end ComboBox
}
RowLayout { //====================== COLOR
id: row6
x :itemX1
y :itemY1+itemDY*6+40
Label {
font.pointSize: 14
text: "Color"
}
}
RowLayout {
id: row6R
x :itemX2
y :itemY1+itemDY*6+40
ComboBox {
currentIndex: colorListInit
model: ListModel {
id: colorList
property var key
ListElement { text: "Black"; cName: 0 }
ListElement { text: "Red"; cName: 1 }
ListElement { text: "Blue"; cName: 2 }
ListElement { text: "Green"; cName: 3 }
ListElement { text: "Purple"; cName: 4 }
ListElement { text: "Gray"; cName: 5 }
}
width: 60
onCurrentIndexChanged: {
//console.debug(colorList.get(currentIndex).text + ", " + colorList.get(currentIndex).cName)
colorList.key = colorList.get(currentIndex).cName
}
} // end ComboBox
}
RowLayout { //====================== CANCEL / OK
id: row7
x : 150
y : 250
Button {
id: closeButton
text: "Cancel"
onClicked: { Qt.quit() }
}
Button {
id: okButton
text: "Ok"
onClicked: {
apply()
Qt.quit()
}
}
}
function apply() {
curScore.startCmd()
var cursor = curScore.newCursor();
var startStaff;
var endStaff;
var endTick;
var fullScore = false;
var quenaLength = Number(quenaLengthList.key);
//console.log("QuenaLength="+quenaLength);
var fingerings = [ "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", //
"Q", "R", "S", "T", "U", "V", "W", "X","Y", "Z", "a", "b", "c", "d", //
"e", "f", "g", "h", "i", "j", "k"] // 1-37 // 3オクターブのG ソまで, "l", "m", "n", "o", "p", "q", "r"] // 1- 44 (0-43) length=44
var noteNameS = [ "C","C#","D","D#","E","F","F#","G","G#","A","A#","B" ]
var noteNameF = [ "C","Db","D","Eb","E","F","Gb","G","Ab","A","Bb","B" ]
//console.log("fingerings.length="+fingerings.length);
// RGB color Black , Red , Blue , Green , Purple , Gray
var colorData= [ "#000000" ,"#FF0000" ,"#0000FF" ,"#00D000" ,"#C007C0" ,"#888888" ];
var fontColor=colorData[colorList.key];
//console.log(fontName);
// var fontSizeTag="";
var fontFaceTag ="";
var fontFaceTagS="";
var fontFaceTagF="";
var fontFaceTagE="";
var selPart=0;
cursor.rewind(1); // 選択範囲の最初に移動
if (!cursor.segment) { // 選択がない場合
fullScore = true;
startStaff = 0; // 最初
endStaff = curScore.nstaves - 1; // 終わり
} else {
startStaff = cursor.staffIdx;
cursor.rewind(2); // 選択範囲の最後
if (cursor.tick == 0) {
endTick = curScore.lastSegment.tick + 1;
} else {
endTick = cursor.tick;
}
endStaff = cursor.staffIdx;
}
//console.log("Part: "+partList.key);
//console.log(startStaff + " - " + endStaff + " - " + endTick);
for (var staff = startStaff; staff <= endStaff; staff++) { // 対象となった音符の最初から最後まで
// for (var voice = 0; voice < 4; voice++) {
// var voice=partList.key; // 声部の指定
cursor.rewind(1); // beginning of selection
cursor.voice = partList.key; // 声部の指定
cursor.staffIdx = staff;
if (fullScore) cursor.rewind(0); // 選択範囲がない場合は先頭から
while (cursor.segment && (fullScore || cursor.tick < endTick)) {
if (cursor.element && cursor.element.type == Element.CHORD) {
var text = newElement(Element.STAFF_TEXT); // 指使い表示用
var text2 = newElement(Element.STAFF_TEXT); // ドレミ、CDE用
// ######################## GRACE #####################################
//####################################################################
var notes = cursor.element.notes;
var pitchFing;
var fontSizeTag;
for (var i = 0; i < notes.length; i++) { // 和音の場合のループ
// for (var i = 0; i < 1;i++) { // 和音の場合は、一番下の音のみ
if(notes[i].tieBack == null ) { // タイの後ろ側の音譜でない場合
if(fontList.key==3) { // 指使いのみの表示-------------------------------------
pitchFing=notes[i].pitch-55+quenaLength;
if(pitchFing<0 || pitchFing>=fingerings.length) {
// text.text=" "+text.text; // 演奏可能な音域外の場合
} else{
text.text = fingerings[pitchFing]+text.text ;
text.color = fontColor;
text.pos.x = valXPosition.value;
text.pos.y = valYPosition.value+12;
fontSizeTag="";
text.text = fontSizeTag + fontFaceTag + text.text;
}
if(i == notes.length-1) cursor.add(text); // if文としないと、MuseScoreがクラッシュする。
//console.log("text.text="+text.text)
} else if(fontList.key==2) { // 指使いとCDE ---------------------------------
pitchFing=notes[i].pitch-55+quenaLength;
if(pitchFing<0 || pitchFing>=fingerings.length) { // 演奏可能な音域外の場合は半角スペース
// text.text=" "+text.text;
// text2.text=" "+text.text;
} else{ // 演奏可能な音内の場合
// 運指
text.text = fingerings[pitchFing]+text.text ; // 運指の文字コードを与える
text.color = fontColor; // 運指の色を与える
text.pos.x = valXPosition.value; // 運指のX方向位置を与える
text.pos.y = valYPosition.value+15; // 運指のY方向位置を与える
fontSizeTag=""; // 運指図の場合、文字サイズを拡大
text.text = fontSizeTag + fontFaceTag + text.text; // 文字サイズと運指用フォント名を与える
// CDE
if(notes[i].tpc>=6 && notes[i].tpc<=12 ) { // プロパティーtpcで判定、 flat ♭の場合
text2.text=noteNameF[(notes[i].pitch % 12)] +text2.text; // ♭場合の英語音名を与える
} else if ( notes[i].tpc>=20 && notes[i].tpc<=26 ){ // sharp ♯の場合
text2.text=qsTr(noteNameS[(notes[i].pitch % 12)]) +text2.text ; // ♯場合の英語音名を与える
} else{ // ♯♭でない場合は、♯♭どちらのフォントでもよい
text2.text=qsTr(noteNameF[(notes[i].pitch % 12)]) +text2.text;
}
text2.color= fontColor; // 英語音名の色を与える
text2.pos.x= valXPosition.value; // 英語音名のX方向位置を与える
text2.pos.y = valYPosition.value+12; // 英語音名のY方向位置を与える
fontSizeTag="";
text2.text= fontSizeTag + fontFaceTagE + text2.text; // 文字サイズと英語音名用フォント名を与える
}
if(i == notes.length-1) cursor.add(text); // 運指を表示する
if(i == notes.length-1) cursor.add(text2); // CDEを表示する
//console.log("text.text="+text.text)
//console.log("text2.text="+text2.text)
} else if(fontList.key==1) { // 指使いとドレミDoReMi---------------------------
pitchFing=notes[i].pitch-55+quenaLength;
if(pitchFing<0 || pitchFing>=fingerings.length) { // 演奏可能な音域外の場合
// text.text=" "+text.text;
// text2.text=" "+text.text;
} else{ // 演奏可能な音内の場合
// 運指
text.text = fingerings[pitchFing]+text.text ;
text.color = fontColor;
text.pos.x = valXPosition.value;
text.pos.y = valYPosition.value+15;
fontSizeTag="";
text.text = fontSizeTag +fontFaceTag+ text.text;
// ドレミ
// pitchFing=(notes[i].pitch +quenaLength) % 12 ; //移動ドに対応する場合
pitchFing=(notes[i].pitch ) % 12 ;
text2.text=fingerings[pitchFing]+text2.text ;
fontSizeTag="";
if(notes[i].tpc>=6 && notes[i].tpc<=12 ) { // Flat ドレミ♭
text2.text= fontSizeTag + fontFaceTagF + text2.text;
} else if ( notes[i].tpc>=20 && notes[i].tpc<=26 ){ // Sharp ドレミ♯
text2.text= fontSizeTag + fontFaceTagS + text2.text;
} else {
text2.text= fontSizeTag + fontFaceTagS + text2.text;
}
text2.color = fontColor;
text2.pos.x = valXPosition.value;
text2.pos.y = valYPosition.value+12;
//console.log("text.text="+text.text)
//console.log("text2.text="+text2.text)
}
if(i == notes.length-1) cursor.add(text);
if(i == notes.length-1) cursor.add(text2);
} else if(fontList.key==5) { // CDEのみ----------------------------------
if ( i > 0 ) text2.text = "\n"+ text2.text; // 和音の場合は、順次改行して縦に表示する。
if(notes[i].tpc>=6 && notes[i].tpc<=12 ) { // flat ♭の場合
text2.text=noteNameF[(notes[i].pitch % 12)] +text2.text; // ♭場合の英語音名を与える
} else if ( notes[i].tpc>=20 && notes[i].tpc<=26 ){ // sharp ♯の場合
text2.text=qsTr(noteNameS[(notes[i].pitch % 12)]) +text2.text ;
} else{
text2.text=qsTr(noteNameF[(notes[i].pitch % 12)]) +text2.text ;
}
text2.color= fontColor;
text2.pos.x= valXPosition.value;
text2.pos.y = valYPosition.value+12;
fontSizeTag="";
text2.text= fontSizeTag + fontFaceTagE + text2.text;
if(i == notes.length-1) cursor.add(text2);
//console.log("text2.text="+text2.text)
} else if(fontList.key==4) { // DoReMiのみ-------------------------------
if ( i > 0 ) text2.text = "\n"+ text2.text; // 和音の場合は、順次改行して縦に表示する。
// pitchFing=(notes[i].pitch +quenaLength) % 12 ;
pitchFing=(notes[i].pitch) % 12 ;
text2.text=fingerings[pitchFing]+text2.text ;
fontSizeTag=""; // 英語音名より少し小さめとする。
if(notes[i].tpc>=6 && notes[i].tpc<=12 ) { // Flat ドレミ♭
text2.text= fontSizeTag + fontFaceTagF + text2.text;
} else if ( notes[i].tpc>=20 && notes[i].tpc<=26 ) { // Sharp ドレミ♯
text2.text= fontSizeTag + fontFaceTagS + text2.text;
} else {
text2.text= fontSizeTag + fontFaceTagS + text2.text;
}
text2.color = fontColor;
text2.pos.x = valXPosition.value;
text2.pos.y = valYPosition.value+12;
if(i == notes.length-1) cursor.add(text2);
//console.log("text2.text="+text2.text)
}
} // end != Tie
/*
switch (voice) {
case 0: text.pos.y = yPos; break;
case 1: text.pos.y = yPos+2; break;
case 2: text.pos.y = yPos+4; break;
case 3: text.pos.y = yPos+6; break;
}
*/
} // end for note i 和音
} // end if CHORD
cursor.next(); // 次の音符へ移動する
} // end while segment
} // end for staff
// Qt.quit();
curScore.endCmd()
// write to file
/// my_file1.write(quenaLengthList.key+"\n"+fontList.key+"\n"+valFontSize.value+"\n"+valYPosition.value+"\n"+valXPosition.value+"\n"+partList.key+"\n"+colorList.key)
//console.log("quenaLengthList.key="+quenaLengthList.key)
Qt.quit();
} // end apply
onRun: {
/*/
if( fileExist ) var fileContents = my_file1.read();
if( !fileExist ) var fileContents="12\n0\n16\n0\n0\n0\n0\n0";
console.log("fileExist="+fileExist);
//console.log("fileContents="+fileContents);
seplines=fileContents.split("\n");
quenaLengthListInit=Number(seplines[0]);
fontListInit=Number(seplines[1]);
fontSizeInit=Number(seplines[2]);
yPositionInit=Number(seplines[3]);
xPositionInit=Number(seplines[4]);
partListInit=Number(seplines[5]);
colorListInit=Number(seplines[6]);
/*/
if (typeof curScore === 'undefined') Qt.quit();
// Qt.quit();
} // end onRun
FileIO {
id: my_file1
/// source: tempPath() + "/temp9999q.txt"
/// source: "/Users/tac201403/Documents/temp9999q.txt"
/// source: "/Users/tac/Documents/temp9999q.txt"
onError: fileExist=false // console.log(msg)
}
} // end MuseScore