author | Dan Fuhry <dan@enanocms.org> |
Sat, 15 Sep 2012 13:18:13 -0400 | |
changeset 6 | 07ceb3e35e25 |
parent 5 | c36fbf04faac |
child 7 | 3a98ce7762a0 |
permissions | -rw-r--r-- |
0 | 1 |
<?php |
2 |
||
3 |
/**!info** |
|
4 |
{ |
|
5 |
"Plugin Name" : "Halftone", |
|
6 |
"Plugin URI" : "http://enanocms.org/plugin/halftone", |
|
7 |
"Description" : "Allows semantic input and transposition of chord sheets.", |
|
8 |
"Author" : "Dan Fuhry", |
|
9 |
"Version" : "0.1", |
|
10 |
"Author URI" : "http://enanocms.org/", |
|
11 |
"Version list" : ['0.1'] |
|
12 |
} |
|
13 |
**!*/ |
|
14 |
||
15 |
$plugins->attachHook('render_wikiformat_posttemplates', 'halftone_process_tags($text);'); |
|
3
c3150cee8dd9
Added support for the "transpose" tag which forces a song to be transposed.
Dan Fuhry <dan@enanocms.org>
parents:
2
diff
changeset
|
16 |
$plugins->attachHook('html_attribute_whitelist', '$whitelist["halftone"] = array("title", "transpose");'); |
0 | 17 |
$plugins->attachHook('session_started', 'register_special_page(\'HalftoneRender\', \'Halftone AJAX render handler\', false);'); |
6
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
18 |
$plugins->attachHook('render_getpage_norender', 'halftone_set_keys_from_tpl_vars($text);'); |
0 | 19 |
|
20 |
define('KEY_C', 0); |
|
21 |
define('KEY_D', 2); |
|
22 |
define('KEY_E', 4); |
|
23 |
define('KEY_F', 5); |
|
24 |
define('KEY_G', 7); |
|
25 |
define('KEY_A', 9); |
|
26 |
define('KEY_B', 11); |
|
27 |
define('KEY_C_SHARP', 1); |
|
28 |
define('KEY_E_FLAT', 3); |
|
29 |
define('KEY_F_SHARP', 6); |
|
30 |
define('KEY_G_SHARP', 8); |
|
31 |
define('KEY_B_FLAT', 10); |
|
32 |
||
33 |
define('ACC_FLAT', -1); |
|
34 |
define('ACC_SHARP', 1); |
|
35 |
||
36 |
$circle_of_fifths = array(KEY_C, KEY_G, KEY_D, KEY_A, KEY_E, KEY_B, KEY_F_SHARP, KEY_C_SHARP, KEY_G_SHARP, KEY_E_FLAT, KEY_B_FLAT, KEY_F); |
|
37 |
$accidentals = array( |
|
38 |
KEY_C => ACC_FLAT, |
|
39 |
KEY_G => ACC_SHARP, |
|
40 |
KEY_D => ACC_SHARP, |
|
41 |
KEY_A => ACC_SHARP, |
|
42 |
KEY_E => ACC_SHARP, |
|
43 |
KEY_B => ACC_SHARP, |
|
44 |
KEY_F_SHARP => ACC_SHARP, |
|
45 |
KEY_C_SHARP => ACC_SHARP, |
|
46 |
KEY_G_SHARP => ACC_FLAT, |
|
47 |
KEY_E_FLAT => ACC_FLAT, |
|
48 |
KEY_B_FLAT => ACC_FLAT, |
|
49 |
KEY_F => ACC_FLAT |
|
50 |
); |
|
51 |
||
52 |
function get_consonants($root_key) |
|
53 |
{ |
|
54 |
global $circle_of_fifths; |
|
55 |
$first = $root_key; |
|
56 |
$key = array_search($root_key, $circle_of_fifths); |
|
57 |
$fourth = $circle_of_fifths[(($key - 1) + count($circle_of_fifths)) % count($circle_of_fifths)]; |
|
58 |
$fifth = $circle_of_fifths[($key + 1) % count($circle_of_fifths)]; |
|
59 |
||
60 |
$minor1 = $circle_of_fifths[($key + 2) % count($circle_of_fifths)]; |
|
61 |
$minor2 = $circle_of_fifths[($key + 3) % count($circle_of_fifths)]; |
|
62 |
$minor3 = $circle_of_fifths[($key + 4) % count($circle_of_fifths)]; |
|
63 |
||
64 |
$result = array( |
|
65 |
'first' => $first, |
|
66 |
'fourth' => $fourth, |
|
67 |
'fifth' => $fifth, |
|
68 |
'minors' => array($minor1, $minor2, $minor3) |
|
69 |
); |
|
70 |
return $result; |
|
71 |
} |
|
72 |
||
73 |
function get_sharp($chord) |
|
74 |
{ |
|
75 |
return key_to_name(name_to_key($chord), ACC_SHARP); |
|
76 |
} |
|
77 |
||
78 |
function detect_key($chord_list) |
|
79 |
{ |
|
80 |
$majors = array(); |
|
81 |
$minors = array(); |
|
82 |
$sharp_or_flat = ACC_SHARP; |
|
4
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
83 |
// sus4 chords are also a great indicator since they are almost always |
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
84 |
// used exclusively on the fifth |
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
85 |
$have_sus4 = false; |
0 | 86 |
// index which chords are used in the song |
87 |
foreach ( $chord_list as $chord ) |
|
88 |
{ |
|
89 |
// discard bass note |
|
90 |
list($chord) = explode('/', $chord); |
|
5
c36fbf04faac
Added "!" trick to give hints to the key detection algorithm. It's all Chris Tomlin's fault.
Dan Fuhry <dan@enanocms.org>
parents:
4
diff
changeset
|
91 |
// skip chord if it has a "!" |
c36fbf04faac
Added "!" trick to give hints to the key detection algorithm. It's all Chris Tomlin's fault.
Dan Fuhry <dan@enanocms.org>
parents:
4
diff
changeset
|
92 |
if ( $chord{0} == '!' ) |
c36fbf04faac
Added "!" trick to give hints to the key detection algorithm. It's all Chris Tomlin's fault.
Dan Fuhry <dan@enanocms.org>
parents:
4
diff
changeset
|
93 |
{ |
c36fbf04faac
Added "!" trick to give hints to the key detection algorithm. It's all Chris Tomlin's fault.
Dan Fuhry <dan@enanocms.org>
parents:
4
diff
changeset
|
94 |
continue; |
c36fbf04faac
Added "!" trick to give hints to the key detection algorithm. It's all Chris Tomlin's fault.
Dan Fuhry <dan@enanocms.org>
parents:
4
diff
changeset
|
95 |
} |
c36fbf04faac
Added "!" trick to give hints to the key detection algorithm. It's all Chris Tomlin's fault.
Dan Fuhry <dan@enanocms.org>
parents:
4
diff
changeset
|
96 |
|
0 | 97 |
$match = array(); |
4
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
98 |
preg_match('/((?:[Mm]?7?|2|5|6|add9|sus4|[Mm]aj[79]|dim|aug)?)$/', $chord, $match); |
0 | 99 |
if ( !empty($match[1]) ) |
4
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
100 |
{ |
0 | 101 |
$chord = str_replace_once($match[1], '', $chord); |
4
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
102 |
if ( $match[1] === 'sus4' ) |
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
103 |
$have_sus4 = $chord; |
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
104 |
} |
0 | 105 |
$sharp_or_flat = get_sharp($chord) == $chord ? ACC_SHARP : ACC_FLAT; |
106 |
$chord = get_sharp($chord); |
|
107 |
if ( $match[1] == 'm' || $match[1] == 'm7' ) |
|
108 |
{ |
|
109 |
// minor chord |
|
110 |
if ( !isset($minors[$chord]) ) |
|
111 |
$minors[$chord] = 0; |
|
112 |
$minors[$chord]++; |
|
113 |
} |
|
114 |
else |
|
115 |
{ |
|
116 |
// major chord |
|
117 |
if ( !isset($majors[$chord]) ) |
|
118 |
$majors[$chord] = 0; |
|
119 |
$majors[$chord]++; |
|
120 |
} |
|
121 |
} |
|
4
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
122 |
/* |
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
123 |
// remove very low scorers |
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
124 |
foreach ( $majors as $key => $count ) |
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
125 |
{ |
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
126 |
if ( $count < 1 ) |
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
127 |
unset($majors[$key]); |
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
128 |
} |
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
129 |
*/ |
0 | 130 |
// now we go through each of the detected major chords, calculate its consonants, and determine how many of its consonants are present in the song. |
131 |
$scores = array(); |
|
132 |
foreach ( $majors as $key => $count ) |
|
133 |
{ |
|
134 |
$scores[$key] = 0; |
|
135 |
$consonants = get_consonants(name_to_key($key)); |
|
136 |
if ( isset($majors[key_to_name($consonants['fourth'])]) ) |
|
137 |
$scores[$key] += 2; |
|
138 |
if ( isset($majors[key_to_name($consonants['fifth'])]) ) |
|
4
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
139 |
$scores[$key] += $have_sus4 === key_to_name($consonants['fifth']) ? 4 : 2; |
0 | 140 |
if ( isset($majors[key_to_name($consonants['minors'][0])]) ) |
141 |
$scores[$key] += 1; |
|
142 |
if ( isset($majors[key_to_name($consonants['minors'][1])]) ) |
|
143 |
$scores[$key] += 2; |
|
144 |
if ( isset($majors[key_to_name($consonants['minors'][2])]) ) |
|
145 |
$scores[$key] += 1; |
|
146 |
} |
|
147 |
$winner_val = -1; |
|
148 |
$winner_key = ''; |
|
149 |
foreach ( $scores as $key => $score ) |
|
150 |
{ |
|
151 |
if ( $score > $winner_val ) |
|
152 |
{ |
|
153 |
$winner_val = $score; |
|
154 |
$winner_key = $key; |
|
155 |
} |
|
156 |
} |
|
157 |
$winner_key = key_to_name(name_to_key($winner_key), $sharp_or_flat); |
|
158 |
return $winner_key; |
|
159 |
} |
|
160 |
||
161 |
function key_to_name($root_key, $accidental = ACC_SHARP) |
|
162 |
{ |
|
163 |
switch($root_key) |
|
164 |
{ |
|
165 |
case KEY_C: |
|
166 |
return 'C'; |
|
167 |
case KEY_D: |
|
168 |
return 'D'; |
|
169 |
case KEY_E: |
|
170 |
return 'E'; |
|
171 |
case KEY_F: |
|
172 |
return 'F'; |
|
173 |
case KEY_G: |
|
174 |
return 'G'; |
|
175 |
case KEY_A: |
|
176 |
return 'A'; |
|
177 |
case KEY_B: |
|
178 |
return 'B'; |
|
179 |
case KEY_C_SHARP: |
|
180 |
return $accidental == ACC_FLAT ? 'Db' : 'C#'; |
|
181 |
case KEY_E_FLAT: |
|
182 |
return $accidental == ACC_FLAT ? 'Eb' : 'D#'; |
|
183 |
case KEY_F_SHARP: |
|
184 |
return $accidental == ACC_FLAT ? 'Gb' : 'F#'; |
|
185 |
case KEY_G_SHARP: |
|
186 |
return $accidental == ACC_FLAT ? 'Ab' : 'G#'; |
|
187 |
case KEY_B_FLAT: |
|
188 |
return $accidental == ACC_FLAT ? 'Bb' : 'A#'; |
|
189 |
default: |
|
190 |
return false; |
|
191 |
} |
|
192 |
} |
|
193 |
||
194 |
function name_to_key($name) |
|
195 |
{ |
|
196 |
switch($name) |
|
197 |
{ |
|
198 |
case 'C': return KEY_C; |
|
199 |
case 'D': return KEY_D; |
|
200 |
case 'E': return KEY_E; |
|
201 |
case 'F': return KEY_F; |
|
202 |
case 'G': return KEY_G; |
|
203 |
case 'A': return KEY_A; |
|
204 |
case 'B': return KEY_B; |
|
205 |
case 'C#': case 'Db': return KEY_C_SHARP; |
|
206 |
case 'D#': case 'Eb': return KEY_E_FLAT; |
|
207 |
case 'F#': case 'Gb': return KEY_F_SHARP; |
|
208 |
case 'G#': case 'Ab': return KEY_G_SHARP; |
|
209 |
case 'A#': case 'Bb': return KEY_B_FLAT; |
|
210 |
default: return false; |
|
211 |
} |
|
212 |
} |
|
213 |
||
214 |
function prettify_accidentals($chord) |
|
215 |
{ |
|
216 |
if ( count(explode('/', $chord)) > 1 ) |
|
217 |
{ |
|
218 |
list($upper, $lower) = explode('/', $chord); |
|
219 |
return prettify_accidentals($upper) . '/' . prettify_accidentals($lower); |
|
220 |
} |
|
221 |
||
222 |
if ( strlen($chord) < 2 ) |
|
223 |
return $chord; |
|
224 |
||
225 |
if ( $chord{1} == 'b' ) |
|
226 |
{ |
|
227 |
$chord = $chord{0} . '♭' . substr($chord, 2); |
|
228 |
} |
|
229 |
else if ( $chord{1} == '#' ) |
|
230 |
{ |
|
231 |
$chord = $chord{0} . '♯' . substr($chord, 2); |
|
232 |
} |
|
5
c36fbf04faac
Added "!" trick to give hints to the key detection algorithm. It's all Chris Tomlin's fault.
Dan Fuhry <dan@enanocms.org>
parents:
4
diff
changeset
|
233 |
return ltrim($chord, '!'); |
0 | 234 |
} |
235 |
||
236 |
function transpose_chord($chord, $increment, $accidental = false) |
|
237 |
{ |
|
238 |
global $circle_of_fifths; |
|
239 |
||
240 |
if ( count(explode('/', $chord)) > 1 ) |
|
241 |
{ |
|
242 |
list($upper, $lower) = explode('/', $chord); |
|
243 |
return transpose_chord($upper, $increment, $accidental) . '/' . transpose_chord($lower, $increment, $accidental); |
|
244 |
} |
|
245 |
// shave off any wacky things we're doing to the chord (minor, seventh, etc.) |
|
5
c36fbf04faac
Added "!" trick to give hints to the key detection algorithm. It's all Chris Tomlin's fault.
Dan Fuhry <dan@enanocms.org>
parents:
4
diff
changeset
|
246 |
$prechord = ''; |
c36fbf04faac
Added "!" trick to give hints to the key detection algorithm. It's all Chris Tomlin's fault.
Dan Fuhry <dan@enanocms.org>
parents:
4
diff
changeset
|
247 |
if ( $chord{0} == '!' ) |
c36fbf04faac
Added "!" trick to give hints to the key detection algorithm. It's all Chris Tomlin's fault.
Dan Fuhry <dan@enanocms.org>
parents:
4
diff
changeset
|
248 |
{ |
c36fbf04faac
Added "!" trick to give hints to the key detection algorithm. It's all Chris Tomlin's fault.
Dan Fuhry <dan@enanocms.org>
parents:
4
diff
changeset
|
249 |
$prechord = '!'; |
c36fbf04faac
Added "!" trick to give hints to the key detection algorithm. It's all Chris Tomlin's fault.
Dan Fuhry <dan@enanocms.org>
parents:
4
diff
changeset
|
250 |
$chord = substr($chord, 1); |
c36fbf04faac
Added "!" trick to give hints to the key detection algorithm. It's all Chris Tomlin's fault.
Dan Fuhry <dan@enanocms.org>
parents:
4
diff
changeset
|
251 |
} |
4
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
252 |
preg_match('/((?:[Mm]?7?|2|5|6|add9|sus4|[Mm]aj[79]|dim|aug)?)$/', $chord, $match); |
0 | 253 |
// find base chord |
254 |
if ( !empty($match[1]) ) |
|
255 |
$chord = str_replace($match[1], '', $chord); |
|
256 |
// what's our accidental? allow it to be specified, and autodetect if it isn't |
|
257 |
if ( !$accidental ) |
|
258 |
$accidental = strstr($chord, '#') ? ACC_SHARP : ACC_FLAT; |
|
259 |
// convert to numeric value |
|
260 |
$key = name_to_key($chord); |
|
261 |
if ( $key === false ) |
|
262 |
// should never happen |
|
263 |
return "[TRANSPOSITION FAILED: " . $chord . $match[1] . "]"; |
|
264 |
// transpose |
|
265 |
$key = (($key + $increment) + count($circle_of_fifths)) % count($circle_of_fifths); |
|
266 |
// return result |
|
267 |
$kname = key_to_name($key, $accidental); |
|
268 |
if ( !$kname ) |
|
269 |
// again, should never happen |
|
270 |
return "[TRANSPOSITION FAILED: " . $chord . $match[1] . " + $increment (->$key)]"; |
|
5
c36fbf04faac
Added "!" trick to give hints to the key detection algorithm. It's all Chris Tomlin's fault.
Dan Fuhry <dan@enanocms.org>
parents:
4
diff
changeset
|
271 |
$result = $prechord . $kname . $match[1]; |
0 | 272 |
// echo "$chord{$match[1]} + $increment = $result<br />"; |
273 |
return $result; |
|
274 |
} |
|
275 |
||
6
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
276 |
function halftone_set_keys_from_tpl_vars(&$text) |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
277 |
{ |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
278 |
global $db, $session, $paths, $template, $plugins; // Common objects |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
279 |
|
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
280 |
// did they specify a key? |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
281 |
if ( !isset($template->tpl_strings['key']) ) |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
282 |
{ |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
283 |
return false; |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
284 |
} |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
285 |
|
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
286 |
// is the key valid? |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
287 |
if ( !is_string(key_to_name($template->tpl_strings['key'])) ) |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
288 |
{ |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
289 |
return false; |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
290 |
} |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
291 |
|
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
292 |
if ( preg_match_all('/<halftone(.*?)>(.+?)<\/halftone>/s', $text, $matches) ) |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
293 |
{ |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
294 |
foreach ( $matches[0] as $i => $whole_match ) |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
295 |
{ |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
296 |
$attribs = decodeTagAttributes($matches[1][$i]); |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
297 |
$attribs['transpose'] = $template->tpl_strings['key']; |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
298 |
|
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
299 |
// re-encode tag attributes |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
300 |
$attribs_encoded = ''; |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
301 |
foreach ( $attribs as $k => $v ) |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
302 |
{ |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
303 |
$attribs_encoded .= sprintf(" %s=\"%s\"", $k, htmlspecialchars($v)); |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
304 |
} |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
305 |
|
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
306 |
$new_match = str_replace_once('<halftone', "<halftone{$attribs_encoded}", str_replace_once($matches[1][$i], '', $whole_match)); |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
307 |
$text = str_replace_once($whole_match, $new_match, $text); |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
308 |
} |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
309 |
} |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
310 |
} |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
311 |
|
0 | 312 |
function halftone_process_tags(&$text) |
313 |
{ |
|
3
c3150cee8dd9
Added support for the "transpose" tag which forces a song to be transposed.
Dan Fuhry <dan@enanocms.org>
parents:
2
diff
changeset
|
314 |
global $circle_of_fifths; |
c3150cee8dd9
Added support for the "transpose" tag which forces a song to be transposed.
Dan Fuhry <dan@enanocms.org>
parents:
2
diff
changeset
|
315 |
|
0 | 316 |
static $css_added = false; |
317 |
if ( !$css_added ) |
|
318 |
{ |
|
319 |
global $template; |
|
320 |
$template->preload_js(array('jquery', 'jquery-ui')); |
|
321 |
$template->add_header(' |
|
322 |
<style type="text/css"> |
|
1
87dfd1a261bd
Several minor CSS changes to allow better integration with a theme designed for stage use and printing
Dan Fuhry <dan@enanocms.org>
parents:
0
diff
changeset
|
323 |
div.halftone { |
0 | 324 |
page-break-before: always; |
325 |
} |
|
326 |
span.halftone-line { |
|
327 |
display: block; |
|
328 |
padding-top: 10pt; |
|
329 |
position: relative; /* allows the absolute positioning in chords to work */ |
|
330 |
} |
|
331 |
span.halftone-chord { |
|
332 |
position: absolute; |
|
333 |
top: 0pt; |
|
334 |
color: rgb(27, 104, 184); |
|
335 |
} |
|
4
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
336 |
span.halftone-line.labeled span.halftone-chord { |
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
337 |
position: static; |
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
338 |
} |
0 | 339 |
span.halftone-chord.sequential { |
340 |
padding-left: 20pt; |
|
341 |
} |
|
342 |
div.halftone-key-select { |
|
343 |
float: right; |
|
344 |
} |
|
345 |
</style> |
|
346 |
<script type="text/javascript"> |
|
347 |
addOnloadHook(function() |
|
348 |
{ |
|
2
2f3b76a405ce
Fixed issue where js would break on pages with no halftone blocks
Dan Fuhry <dan@enanocms.org>
parents:
1
diff
changeset
|
349 |
var first_ht = $("div.halftone").get(0); |
2f3b76a405ce
Fixed issue where js would break on pages with no halftone blocks
Dan Fuhry <dan@enanocms.org>
parents:
1
diff
changeset
|
350 |
if ( first_ht ) |
2f3b76a405ce
Fixed issue where js would break on pages with no halftone blocks
Dan Fuhry <dan@enanocms.org>
parents:
1
diff
changeset
|
351 |
first_ht.style.pageBreakBefore = "auto"; |
0 | 352 |
$("select.halftone-key").change(function() |
353 |
{ |
|
354 |
var me = this; |
|
355 |
var src = $(this.parentNode.parentNode).attr("halftone:src"); |
|
356 |
ajaxPost(makeUrlNS("Special", "HalftoneRender", "transpose=" + $(this).val()) + "&tokey=" + $("option:selected", this).attr("halftone:abs"), "src=" + encodeURIComponent(src), function(ajax) |
|
357 |
{ |
|
358 |
if ( ajax.readyState == 4 && ajax.status == 200 ) |
|
359 |
{ |
|
360 |
var $songbody = $("div.halftone-song", me.parentNode.parentNode); |
|
361 |
$songbody.html(ajax.responseText); |
|
362 |
} |
|
363 |
}); |
|
364 |
}); |
|
365 |
}); |
|
366 |
</script> |
|
367 |
'); |
|
368 |
$css_added = true; |
|
369 |
} |
|
370 |
if ( preg_match_all('/<halftone(.*?)>(.+?)<\/halftone>/s', $text, $matches) ) |
|
371 |
{ |
|
372 |
foreach ( $matches[0] as $i => $whole_match ) |
|
373 |
{ |
|
374 |
$attribs = decodeTagAttributes($matches[1][$i]); |
|
375 |
$song_title = isset($attribs['title']) ? $attribs['title'] : 'Untitled song'; |
|
376 |
$chord_list = array(); |
|
377 |
$inner = trim($matches[2][$i]); |
|
378 |
$song = halftone_render_body($inner, $chord_list); |
|
3
c3150cee8dd9
Added support for the "transpose" tag which forces a song to be transposed.
Dan Fuhry <dan@enanocms.org>
parents:
2
diff
changeset
|
379 |
|
0 | 380 |
$src = base64_encode($whole_match); |
3
c3150cee8dd9
Added support for the "transpose" tag which forces a song to be transposed.
Dan Fuhry <dan@enanocms.org>
parents:
2
diff
changeset
|
381 |
$origkey = $key = name_to_key(detect_key($chord_list)); |
c3150cee8dd9
Added support for the "transpose" tag which forces a song to be transposed.
Dan Fuhry <dan@enanocms.org>
parents:
2
diff
changeset
|
382 |
if ( isset($attribs['transpose']) && is_int($tokey = name_to_key($attribs['transpose'])) ) |
c3150cee8dd9
Added support for the "transpose" tag which forces a song to be transposed.
Dan Fuhry <dan@enanocms.org>
parents:
2
diff
changeset
|
383 |
{ |
c3150cee8dd9
Added support for the "transpose" tag which forces a song to be transposed.
Dan Fuhry <dan@enanocms.org>
parents:
2
diff
changeset
|
384 |
// re-render in new key |
c3150cee8dd9
Added support for the "transpose" tag which forces a song to be transposed.
Dan Fuhry <dan@enanocms.org>
parents:
2
diff
changeset
|
385 |
$transpose = $tokey - $key; |
c3150cee8dd9
Added support for the "transpose" tag which forces a song to be transposed.
Dan Fuhry <dan@enanocms.org>
parents:
2
diff
changeset
|
386 |
$song = halftone_render_body($inner, $chord_list, $tokey, $transpose); |
c3150cee8dd9
Added support for the "transpose" tag which forces a song to be transposed.
Dan Fuhry <dan@enanocms.org>
parents:
2
diff
changeset
|
387 |
$key = $tokey; |
c3150cee8dd9
Added support for the "transpose" tag which forces a song to be transposed.
Dan Fuhry <dan@enanocms.org>
parents:
2
diff
changeset
|
388 |
} |
0 | 389 |
$select = '<select class="halftone-key">'; |
390 |
for ( $i = 0; $i < 12; $i++ ) |
|
391 |
{ |
|
392 |
$label = in_array($i, array(KEY_C_SHARP, KEY_E_FLAT, KEY_F_SHARP, KEY_G_SHARP, KEY_B_FLAT)) ? sprintf("%s/%s", key_to_name($i, ACC_SHARP), key_to_name($i, ACC_FLAT)) : key_to_name($i); |
|
393 |
$label = prettify_accidentals($label); |
|
394 |
$sel = $key == $i ? ' selected="selected"' : ''; |
|
3
c3150cee8dd9
Added support for the "transpose" tag which forces a song to be transposed.
Dan Fuhry <dan@enanocms.org>
parents:
2
diff
changeset
|
395 |
$select .= sprintf("<option%s value=\"%d\" halftone:abs=\"%d\">%s</option>", $sel, $i - $origkey, $i, $label); |
0 | 396 |
} |
397 |
$select .= '</select>'; |
|
1
87dfd1a261bd
Several minor CSS changes to allow better integration with a theme designed for stage use and printing
Dan Fuhry <dan@enanocms.org>
parents:
0
diff
changeset
|
398 |
$headid = 'song:' . sanitize_page_id($song_title); |
87dfd1a261bd
Several minor CSS changes to allow better integration with a theme designed for stage use and printing
Dan Fuhry <dan@enanocms.org>
parents:
0
diff
changeset
|
399 |
$text = str_replace_once($whole_match, "<div id=\"$headid\" class=\"halftone\" halftone:src=\"$src\"><div class=\"halftone-key-select\">$select</div><h1 class=\"halftone-title\">$song_title</h1>\n\n<div class=\"halftone-song\">\n" . $song . "</div></div>", $text); |
0 | 400 |
} |
401 |
} |
|
402 |
} |
|
403 |
||
3
c3150cee8dd9
Added support for the "transpose" tag which forces a song to be transposed.
Dan Fuhry <dan@enanocms.org>
parents:
2
diff
changeset
|
404 |
function halftone_render_body($inner, &$chord_list, $inkey = false, $transpose = 0) |
0 | 405 |
{ |
406 |
global $accidentals; |
|
1
87dfd1a261bd
Several minor CSS changes to allow better integration with a theme designed for stage use and printing
Dan Fuhry <dan@enanocms.org>
parents:
0
diff
changeset
|
407 |
$song = '<div class="section">'; |
0 | 408 |
$chord_list = array(); |
3
c3150cee8dd9
Added support for the "transpose" tag which forces a song to be transposed.
Dan Fuhry <dan@enanocms.org>
parents:
2
diff
changeset
|
409 |
$transpose = isset($_GET['transpose']) ? intval($_GET['transpose']) : $transpose; |
0 | 410 |
$transpose_accidental = $inkey ? $accidentals[$inkey] : false; |
411 |
foreach ( explode("\n", $inner) as $line ) |
|
412 |
{ |
|
413 |
$chordline = false; |
|
5
c36fbf04faac
Added "!" trick to give hints to the key detection algorithm. It's all Chris Tomlin's fault.
Dan Fuhry <dan@enanocms.org>
parents:
4
diff
changeset
|
414 |
$chords_regex = '/(\((?:\!?[A-G][#b]?(?:[Mm]?7?|2|5|6|add9|sus4|[Mm]aj[79]|dim|aug)?(?:\/[A-G][#b]?)?)\))/'; |
0 | 415 |
$line_split = preg_split($chords_regex, $line, -1, PREG_SPLIT_DELIM_CAPTURE); |
4
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
416 |
$line_pattern = ''; |
0 | 417 |
if ( preg_match_all($chords_regex, $line, $chords) ) |
418 |
{ |
|
419 |
// this is a line with lyrics + chords |
|
5
c36fbf04faac
Added "!" trick to give hints to the key detection algorithm. It's all Chris Tomlin's fault.
Dan Fuhry <dan@enanocms.org>
parents:
4
diff
changeset
|
420 |
// echo out the line, adding spans around chords. |
0 | 421 |
$line_final = array(); |
422 |
$last_was_chord = false; |
|
423 |
foreach ( $line_split as $entry ) |
|
424 |
{ |
|
425 |
if ( preg_match($chords_regex, $entry) ) |
|
426 |
{ |
|
427 |
if ( $last_was_chord ) |
|
428 |
{ |
|
429 |
while ( !($pop = array_pop($line_final)) ); |
|
430 |
$new_entry = preg_replace('#</span>$#', '', $pop); |
|
431 |
$new_entry .= str_repeat(' ', 4); |
|
432 |
$new_entry .= prettify_accidentals($chord_list[] = transpose_chord(trim($entry, '()'), $transpose, $transpose_accidental)) . '</span>'; |
|
433 |
$line_final[] = $new_entry; |
|
434 |
} |
|
435 |
else |
|
436 |
{ |
|
437 |
$line_final[] = '<span class="halftone-chord">' . prettify_accidentals($chord_list[] = transpose_chord(trim($entry, '()'), $transpose, $transpose_accidental)) . '</span>'; |
|
438 |
} |
|
439 |
$last_was_chord = true; |
|
4
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
440 |
$line_pattern .= 'c'; |
0 | 441 |
} |
442 |
else |
|
443 |
{ |
|
444 |
if ( trim($entry) != "" ) |
|
445 |
{ |
|
446 |
$last_was_chord = false; |
|
447 |
$line_final[] = $entry; |
|
4
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
448 |
$line_pattern .= 'w'; |
0 | 449 |
} |
450 |
} |
|
451 |
} |
|
4
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
452 |
$class_append = preg_match('/^w?c+$/', $line_pattern) ? ' labeled' : ''; |
bb3789db954a
Several bugfixes and improvements.
Dan Fuhry <dan@enanocms.org>
parents:
3
diff
changeset
|
453 |
$song .= '<span class="halftone-line' . $class_append . '">' . implode("", $line_final) . "</span>\n"; |
0 | 454 |
} |
6
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
455 |
else if ( preg_match('/^=\s*(.+?)\s*=\r?$/', $line, $match) ) |
0 | 456 |
{ |
1
87dfd1a261bd
Several minor CSS changes to allow better integration with a theme designed for stage use and printing
Dan Fuhry <dan@enanocms.org>
parents:
0
diff
changeset
|
457 |
$song .= "</div>\n<div class=\"section\">\n== {$match[1]} ==\n\n"; |
0 | 458 |
} |
459 |
else if ( trim($line) == '' ) |
|
460 |
{ |
|
461 |
continue; |
|
462 |
} |
|
1
87dfd1a261bd
Several minor CSS changes to allow better integration with a theme designed for stage use and printing
Dan Fuhry <dan@enanocms.org>
parents:
0
diff
changeset
|
463 |
else if ( preg_match('/^\[(.+)\]$/', trim($line), $match) ) |
87dfd1a261bd
Several minor CSS changes to allow better integration with a theme designed for stage use and printing
Dan Fuhry <dan@enanocms.org>
parents:
0
diff
changeset
|
464 |
{ |
87dfd1a261bd
Several minor CSS changes to allow better integration with a theme designed for stage use and printing
Dan Fuhry <dan@enanocms.org>
parents:
0
diff
changeset
|
465 |
$song .= "<br /><strong>Jump to:</strong> {$match[1]}\n"; |
87dfd1a261bd
Several minor CSS changes to allow better integration with a theme designed for stage use and printing
Dan Fuhry <dan@enanocms.org>
parents:
0
diff
changeset
|
466 |
} |
0 | 467 |
else |
468 |
{ |
|
469 |
$song .= "$line<br />\n"; |
|
470 |
} |
|
471 |
} |
|
6
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
472 |
$song .= '</div>'; |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
473 |
|
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
474 |
//header('Content-type: text/plain'); |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
475 |
//die($song); |
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
476 |
|
07ceb3e35e25
Added support for the render_getpage_norender hook, allowing transposition to take place via the "key" parameter when including Halftone pages as templates.
Dan Fuhry <dan@enanocms.org>
parents:
5
diff
changeset
|
477 |
return $song; |
0 | 478 |
} |
479 |
||
480 |
function page_Special_HalftoneRender() |
|
481 |
{ |
|
482 |
global $accidentals; |
|
483 |
$text = isset($_POST['src']) ? base64_decode($_POST['src']) : ''; |
|
484 |
if ( preg_match('/<halftone(.*?)>(.+?)<\/halftone>/s', $text, $match) ) |
|
485 |
{ |
|
486 |
require_once(ENANO_ROOT . '/includes/wikiformat.php'); |
|
487 |
$carp = new Carpenter(); |
|
488 |
$carp->exclusive_rule('heading'); |
|
489 |
$tokey = isset($_GET['tokey']) ? intval($_GET['tokey']) : false; |
|
490 |
echo $carp->render(halftone_render_body($match[2], $chord_list, $tokey)); |
|
491 |
} |
|
492 |
} |