File size: 5,254 Bytes
af6912c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/*
 * Tablature Plugins
 * tablature are defined dynamically and registered inside abcjs
 * by calling abcTablatures.register(plugin) 
 * where plugin represents a plugin instance 
 * 
 */

// This is the only entry point to the tablatures. It is called both after parsing a tune and just before engraving

var TabString = require('./instruments/tab-string');

/* extend the table below when adding a new instrument plugin */

// Existing tab classes 
var pluginTab = {
	'violin': { name: 'StringTab', defaultTuning: ['G,', 'D', 'A', 'e'], isTabBig: false, tabSymbolOffset: 0 },
	'fiddle': { name: 'StringTab', defaultTuning: ['G,', 'D', 'A', 'e'], isTabBig: false, tabSymbolOffset: 0 },
	'mandolin': { name: 'StringTab', defaultTuning: ['G,', 'D', 'A', 'e'], isTabBig: false, tabSymbolOffset: 0 },
	'guitar': { name: 'StringTab', defaultTuning: ['E,', 'A,', 'D', 'G', 'B', 'e'], isTabBig: true, tabSymbolOffset: 0 },
	'fiveString': { name: 'StringTab', defaultTuning: ['C,', 'G,', 'D', 'A', 'e'], isTabBig: false, tabSymbolOffset: -.95 },
};

var abcTablatures = {

	inited: false,
	plugins: {},


	/**
	 * to be called once per plugin for registration 
	 * @param {*} plugin 
	 */
	register: function (plugin) {
		var name = plugin.name;
		var tablature = plugin.tablature;
		this.plugins[name] = tablature;
	},

	setError: function (tune, msg) {
		if (tune.warnings) {
			tune.warning.push(msg);
		} else {
			tune.warnings = [msg];
		}
	},

	/**
	 * handle params for current processed score
	 * @param {*} tune current tune 
	 * @param {*} tuneNumber number in tune list
	 * @param {*} params params to be processed for tablature
	 * @return prepared tablatures plugin instances for current tune
	 */
	preparePlugins: function (tune, tuneNumber, params) {
		// Called after parsing a tune and before engraving it
		if (!this.inited) {
			// TODO-PER: I don't think this is needed - the plugin array can be hard coded, right?
			this.register(new TabString());
			this.inited = true;
		}
		var returned = null;
		var nbPlugins = 0;
		if (params.tablature) {
			// validate requested plugins 
			var tabs = params.tablature;
			returned = [];
			for (var ii = 0; ii < tabs.length; ii++) {
				var args = tabs[ii];
				var instrument = args['instrument'];
				if (instrument == null) {
					this.setError(tune, "tablature 'instrument' is missing");
					return returned;
				}
				var tabName = pluginTab[instrument];
				var plugin = null;
				if (tabName) {
					plugin = this.plugins[tabName.name];
				}
				if (plugin) {
					if (params.visualTranspose != 0) {
						// populate transposition request to tabs
						args.visualTranspose = params.visualTranspose;
					}
					args.abcSrc = params.tablature.abcSrc;
					var pluginInstance = {
						classz: plugin,
						tuneNumber: tuneNumber,
						params: args,
						instance: null,
						tabType: tabName,
					};
					// proceed with tab plugin  init 
					// plugin.init(tune, tuneNumber, args, ii);
					returned.push(pluginInstance);
					nbPlugins++;
				} else if (instrument === '') {
					// create a placeholder - there is no tab for this staff
					returned.push(null)
				} else {
					// unknown tab plugin 
					//this.emit_error('Undefined tablature plugin: ' + tabName)
					this.setError(tune, 'Undefined tablature plugin: ' + instrument);
					return returned;
				}
			}
		}
		return returned;
	},

	/**
	 * Call requested plugin
	 * @param {*} renderer 
	 * @param {*} abcTune 
	 */
	layoutTablatures: function layoutTablatures(renderer, abcTune) {
		var tabs = abcTune.tablatures;

		// chack tabs request for each staffs
		var staffLineCount = 0;

		// Clear the suppression flag
		if (tabs && (tabs.length > 0)) {
			var nTabs = tabs.length;
			for (var kk = 0; kk < nTabs; ++kk) {
				if (tabs[kk] && tabs[kk].params.firstStaffOnly) {
					tabs[kk].params.suppress = false;
				}
			}
		}

		for (var ii = 0; ii < abcTune.lines.length; ii++) {
			var line = abcTune.lines[ii];

			if (line.staff) {
				staffLineCount++;
			}

			// MAE 27Nov2023
			// If tab param "firstStaffOnly", remove the tab label after the first staff
			if (staffLineCount > 1) {
				if (tabs && (tabs.length > 0)) {
					var nTabs = tabs.length;
					for (var kk = 0; kk < nTabs; ++kk) {
						if (tabs[kk].params.firstStaffOnly) {
							// Set the staff draw suppression flag
							tabs[kk].params.suppress = true;
						}
					}
				}
			}

			var curStaff = line.staff;
			if (curStaff) {
				var maxStaves = curStaff.length
				for (var jj = 0; jj < curStaff.length; jj++) {

					if (tabs[jj] && jj < maxStaves) {
						// tablature requested for staff
						var tabPlugin = tabs[jj];
						if (tabPlugin.instance == null) {
							//console.log("β˜…β˜…β˜…β˜… Tab Init line: " + ii + " staff: " + jj)
							tabPlugin.instance = new tabPlugin.classz();
							// plugin.init(tune, tuneNumber, args, ii);
							// call initer first
							tabPlugin.instance.init(abcTune,
								tabPlugin.tuneNumber,
								tabPlugin.params,
								tabPlugin.tabType
							);
						}
						// render next
						//console.log("β˜…β˜…β˜…β˜… Tab Render line: " + ii + " staff: " + jj)
						tabPlugin.instance.render(renderer, line, jj);
					}
				}
			}
		}
	},

};


module.exports = abcTablatures;