//==============================================
// MuseScore
//
// Shinobue Notation plugin for MuseScore Ver. 2.0
//
// Copyright (C)2010-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.Shinobue Notation" //
version: "2.0.03"
description: qsTr("Shinobue note names, fingering etc.")
pluginType: "dialog"
id: window
width:285 // menu window size
height:285
ExclusiveGroup { id: exclusiveGroupKey }
property var fileExist :true
property var seplines
property var shinobueLengthInit : 8
property var fontListInitNumber : 0
property var fontListInitName : "Shinobue"
property var fontSizeInit : 16
property var yPositionInit : 0
property var xPositionInit : 0
property var partListInit : 0
property var colorListInit : 0
property var fontName: [ "Shinobueb","ShinobueX","Doremi","Helvetica" ]
property var fontNameSel
// Item positions in menu window
property var itemX1 : 10
property var itemX2 : 150
property var itemY1 : 10
property var itemDY : 25
RowLayout { //====================== LENGTH
id: row0
x :itemX1
y :itemY1
Label {
font.pointSize: 14
text: "Shinobue (Hon)" // effect , no effect
}
}
RowLayout {
id: row0R
x : itemX2
y : itemY1
SpinBox {
id: valShinobueLength
implicitWidth: 55
decimals: 0
minimumValue: -10
maximumValue: 20
value: shinobueLengthInit
font.pointSize: 14
}
}
RowLayout { //====================== FONT
id: row1
x :itemX1
y :itemY1+itemDY*1
Label {
font.pointSize: 14
text: "Font"
}
}
RowLayout {
id: row1R
x :itemX2
y :itemY1+itemDY*1
ComboBox {
currentIndex: fontListInitNumber
model: ListModel {
id: fontList
property var key
ListElement { text: "Shinobue"; fName: 0 }
// ListElement { text: "# only"; fName: 1 }
// ListElement { text: "b only"; fName: 2 }
ListElement { text: " (Fukuhara)"; fName: 1 }
ListElement { text: "DoReMi (Katakana)"; fName:2 }
ListElement { text: "CDEFG"; fName: 3 }
}
width: 100
onCurrentIndexChanged: {
console.debug(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 (Tate) 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 (Yoko) 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()
applyToSelection()
my_file1.write(valShinobueLength.value+"\n"+fontList.key+"\n"+valFontSize.value+"\n"+valYPosition.value+"\n"+valXPosition.value+"\n"+partList.key+"\n"+colorList.key)
curScore.endCmd()
}
onRun: {
if( fileExist ) var fileContents = my_file1.read();
if( !fileExist ) var fileContents="8\n0\n13\n0\n0\n0\n0\n0";
//console.log("fileExist="+fileExist);
//console.log("fileContents="+fileContents);
seplines=fileContents.split("\n");
//console.log("seplines="+seplines);
shinobueLengthInit=Number(seplines[0] );
fontListInitNumber=Number(seplines[1]);
fontListInitName=fontName[Number(seplines[1])];
fontSizeInit=Number(seplines[2]);
yPositionInit=Number(seplines[3]);
xPositionInit=Number(seplines[4]);
partListInit=Number(seplines[5]);
colorListInit=Number(seplines[6]);
//console.log("on Run : fontListInitName="+fontListInitName);
if (typeof curScore === 'undefined')
Qt.quit();
} // end onRun
function applyToSelection() {
var cursor = curScore.newCursor();
var startStaff;
var endStaff;
var endTick;
var fullScore = false;
var shinobueLength = valShinobueLength.value;
// console.log(shinobueLength);
var yPos = valYPosition.value+10 ; // Y offset= +10
if(fontList.key==0) var xPos = valXPosition.value-0.7; // Shinobue
if(fontList.key==1) var xPos = valXPosition.value-0.7; // X Fukuhara
if(fontList.key==2) var xPos = valXPosition.value-0.8; // Do Re Mi
if(fontList.key==3) var xPos = valXPosition.value-0.7; // CDEFG
// if(fontList.key==4) var xPos = valXPosition.value-0.8; //
// if(fontList.key==5) var xPos = valXPosition.value-0.8; //
fontNameSel =fontName[ Number(fontList.key)];
//console.log("in apply fontNameSel="+fontNameSel);
var fontSize = valFontSize.value;
// console.log("Read from file="+fileContents);
var fontSizeTag="";
var fontFaceTag="";
var selPart=0;
// RGB color Black , Red , Blue , Green , Purple , Gray
var colorData= [ "#000000" ,"#FF0000" ,"#0000FF" ,"#00FF00" ,"#C007C0" ,"#888888" ];
var fontColor=colorData[colorList.key];
//console.log(fontName);
cursor.rewind(1); // rewind to start of selection
if (!cursor.segment) { // no selection
fullScore = true;
startStaff = 0; // start with 1st staff
endStaff = curScore.nstaves - 1; // and end with last
} else {
startStaff = cursor.staffIdx;
cursor.rewind(2); // rewind to end of selection
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 = voice;
cursor.staffIdx = staff;
if (fullScore) // no selection
cursor.rewind(0); // beginning of score
while (cursor.segment && (fullScore || cursor.tick < endTick)) {
if (cursor.element && cursor.element.type == Element.CHORD) {
var text = newElement(Element.STAFF_TEXT);
// ######################## GRACE #####################################
var graceChords = cursor.element.graceNotes;
for (var i = 0; i < graceChords.length; i++) {
var notes = graceChords[i].notes;
nameChord(notes, text, shinobueLength, fontName);
text.pos.x =xPos -2.3 * (graceChords.length - i); // X position of Grace note
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;
}
text.color= fontColor;
if(fontList.key==0) text.text= fontSizeTag + text.text;
else if(fontList.key==3) text.text= fontSizeTag + text.text;
else text.text= fontSizeTag + fontFaceTag + text.text;
cursor.add(text);
text = newElement(Element.STAFF_TEXT);
} // end graceChorde
//####################################################################
var notes = cursor.element.notes;
nameChord(notes, text,shinobueLength, fontName);
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;
}
text.color= fontColor;
text.pos.x= xPos;
if(fontList.key==0) text.text= fontSizeTag + text.text;
else if(fontList.key==3) text.text= fontSizeTag + text.text;
else text.text= fontSizeTag + fontFaceTag + text.text;
cursor.add(text);
} // end if CHORD
cursor.next();
} // end while segment
// } // end for voice
} // end for staff
Qt.quit();
} // end onRun
function nameChord (notes, text, shinobueLength, fontName) {
var fingerings = [ "A", "B", // Otsu RO Omeri, Otsu RO meri
"C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", // Otsu
"P", "Q", "R", "S", "T", "U", "V", "W", "X","Y", "Z", "a", // Kan
"b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n"] // Daikan
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" ]
// "Shinobueb","Shinobue#"
// space chracter is needed. "s"
var pitchFing;
for (var i = 0; i < notes.length; i++) {
var sep = "\n"; // ","; // change to "\n" if you want them vertically
if ( i > 0 ) text.text = sep + text.text;
if(fontNameSel=="Doremi") {
pitchFing=(notes[i].pitch +20 -shinobueLength) % 12 ;
} else if ( fontNameSel=="Helvetica" ) {
if(notes[i].tpc>=6 && notes[i].tpc<=12 ) { // b Flat
text.text=noteNameF[(notes[i].pitch % 12)] +text.text ;
} else if ( notes[i].tpc>=20 && notes[i].tpc<=26 ){ // # Sharp
text.text=qsTr(noteNameS[(notes[i].pitch % 12)]) +text.text ;
} else{
text.text=qsTr(noteNameF[(notes[i].pitch % 12)]) +text.text ;
}
} else pitchFing=notes[i].pitch-57 +8-shinobueLength;
// if(pitchFing<0) pitchFing=12+pitchFing;
if(pitchFing<0 || pitchFing>=fingerings.length) // out of range
text.text=" "+text.text;
else{
if(notes[i].tieBack == null && fontNameSel !="Helvetica") text.text=fingerings[pitchFing]+text.text ; // 0 == OtsuRO
if ( fontNameSel=="Shinobueb" ) {
if(notes[i].tpc>=6 && notes[i].tpc<=12 ) { // b Flat
text.text=""+text.text;
} else if ( notes[i].tpc>=20 && notes[i].tpc<=26 ){ // # Sharp
text.text=""+text.text;
} else{
text.text=""+text.text;
}
}
if(fontNameSel=="Doremi"){
if(notes[i].tpc>=6 && notes[i].tpc<=12 ) { // b Flat
text.text=""+text.text;
} else if ( notes[i].tpc>=20 && notes[i].tpc<=26 ){ // # Sharp
} else {
text.text=""+text.text;
}
pitchFing=(notes[i].pitch-57 +8-shinobueLength) % 12 ;
}
}
} // end for note
} // end function
FileIO {
id: my_file1
source: tempPath() + "/temp9999sb.txt"
// source: "/Users/tac/Documents/temp9999sb.txt"
onError: fileExist=false // console.log(msg)
}
} // end MuseScore