A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2004 Matthias Wientapper, 2014-2015 Thomas Orgis
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 * TODO:
21 * - Think about generating the sounds on startup with SWCODEC.
22 ****************************************************************************/
23#include "plugin.h"
24#include "lib/pluginlib_actions.h"
25#include "lib/pluginlib_exit.h"
26#include "fixedpoint.h"
27
28/* About time resolution:
29 1000 means 1 ms resolution. It should get better with higher values
30 in theory, but in practice, too small timer intervals increase the
31 chance of being missed and make the metronome lag behind. Mean tempo
32 still works out with very small divider values (29 even) as long as
33 the rounding error compensation is active, although beat intervals
34 become jerky. You compromise between long-term accuracy and steadyness
35 from one beat to the next.
36
37 A drift you have to accept comes just from the audio clock itself, or even
38 from the difference between clocks in the device. The Sansa Clip+ has around
39 0.04 % error in audio frequency using the "good" PLLB. I presume that the
40 difference between timing using PLLA and PLLB is at least that big. Something
41 up to 40 ms time difference over one minute when comparing to an external
42 reference or just the metronome plugin with playback of a prepared PCM track
43 is to be expected.
44
45 Also, since playback on SWCODEC is not allowed to happen inside the timer
46 callback, there is a delay introduced by the main loop scheduling. This
47 could be compensated for by delaying the audio depending on a counter
48 incremented since the period elapsed in the callback, at the price of
49 putting the display out of sync. On a Clip+, the schedule delay isn't
50 biggest problem (drift for fine timer resolution is).
51
52 All in all, 1 ms is too small, 2 ms seems to work fine ...
53 4 ms might still be cool, too.
54*/
55#if defined(SIMULATOR)
56/* Simulator really wants 1024. Not 1000, not 512, only 1024.
57 Otherwise it is strangely slow. */
58static const unsigned int timerfreq_div = 1024;
59#else
60static const unsigned int timerfreq_div = 500; /* 2 ms resolution */
61#endif
62/* actual (not quarter) beats per minute above which display blinking
63 is deactivated (since it is not needed anymore and because of performance
64 issues) */
65static const unsigned int blinklimit = 135;
66
67enum metronome_errors
68{
69 MERR_NOTHING = 0
70, MERR_MISSING
71, MERR_OOM
72, MERR_TEMPO
73, MERR_METER
74, MERR_VOLUME
75, MERR_PATTERN
76};
77
78#define PART_MAX 10 /* maximum count of programmed parts */
79
80#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) \
81 || (CONFIG_KEYPAD == SANSA_E200_PAD) || (CONFIG_KEYPAD == SAMSUNG_YH820_PAD)
82#define MET_SYNC
83#endif
84
85#if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \
86 || (CONFIG_KEYPAD == IPOD_3G_PAD) \
87 || (CONFIG_KEYPAD == IPOD_4G_PAD)
88#define METRONOME_QUIT PLA_UP
89#else
90#define METRONOME_QUIT PLA_EXIT
91#endif
92
93#ifdef HAVE_SCROLLWHEEL
94#define METRONOME_VOL_UP PLA_SCROLL_FWD
95#define METRONOME_VOL_UP_REP PLA_SCROLL_FWD_REPEAT
96#define METRONOME_VOL_DOWN PLA_SCROLL_BACK
97#define METRONOME_VOL_DOWN_REP PLA_SCROLL_BACK_REPEAT
98#else
99#define METRONOME_VOL_UP PLA_UP
100#define METRONOME_VOL_DOWN PLA_DOWN
101#define METRONOME_VOL_UP_REP PLA_UP_REPEAT
102#define METRONOME_VOL_DOWN_REP PLA_DOWN_REPEAT
103#endif
104#define METRONOME_LEFT PLA_LEFT
105#define METRONOME_RIGHT PLA_RIGHT
106#define METRONOME_LEFT_REP PLA_LEFT_REPEAT
107#define METRONOME_RIGHT_REP PLA_RIGHT_REPEAT
108#define METRONOME_TAP PLA_SELECT_REL
109#define METRONOME_PAUSE PLA_CANCEL
110#define METRONOME_PLAY PLA_SELECT_REPEAT
111
112#define METRONOME_START PLA_SELECT
113
114#ifdef MET_SYNC
115enum{ METRONOME_SYNC = LAST_PLUGINLIB_ACTION+1 };
116static const struct button_mapping iriver_syncaction[] =
117{
118 { METRONOME_SYNC, BUTTON_REC, BUTTON_NONE },
119 LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_PLUGIN)
120};
121#endif /* IRIVER_H100_PAD||IRIVER_H300_PAD */
122
123const struct button_mapping *plugin_contexts[] =
124{
125 pla_main_ctx,
126#if defined(MET_SYNC)
127 iriver_syncaction,
128#endif
129};
130#define PLA_ARRAY_COUNT sizeof(plugin_contexts)/sizeof(plugin_contexts[0])
131
132/* raw PCM */
133static signed short tick_sound[] =
134{
135 32767,32764,32767,32767,32763,32767,32762,32767,32765,32767,32767
136,32766,32767,32766,32767,32767,32765,32767,32764,32767,32764,32767
137,32763,-32764,-32768,-32766,-32768,-32768,-32767,-32767,-32767,-32765,-32768
138,-32764,-32768,-32768,-32766,-32768,-32764,-32768,-32766,-32767,-32768,-32767
139,-32766,32763,32767,32763,32767,32767,32766,32767,32766,32767,32765
140,32767,32763,32767,32766,32767,32766,32767,32763,32767,32765,32767
141,32767,-32768,-32765,-32768,-32767,-32765,-32767,-32765,-32768,-32764,-32768
142,-32766,-32768,-32768,-32766,-32767,-32768,-32764,-32768,-32764,-32768,-32768
143,-32766,32716,32668,32620,32564,32520,32467,32418,32370,32316,32272
144,32214,32176,32114,32074,32020,31972,31922,31873,31823,31775,31726
145,31676,-31627,-31579,-31530,-31479,-31433,-31383,-31333,-31287,-31236,-31188
146,-31141,-31090,-31042,-30998,-30943,-30899,-30849,-30800,-30757,-30702,-30659
147,-30609,30561,30515,30463,30422,30365,30326,30273,30229,30177,30135
148,30084,30035,29995,29936,29903,29844,29802,29755,29706,29661,29614
149,29565,-29519,-29472,-29426,-29381,-29331,-29288,-29239,-29191,-29149,-29099
150,-29055,-29007,-28962,-28914,-28871,-28821,-28779,-28730,-28685,-28638,-28596
151,-28544,28496,28463,28404,28371,28314,28278,28225,28185,28136,28093
152,28048,28001,27956,27912,27865,27824,27773,27736,27682,27646,27593
153,27555,-27509,-27462,-27418,-27375,-27328,-27286,-27239,-27200,-27145,-27116
154,-27055,-27026,-26972,-26930,-26891,-26838,-26805,-26750,-26716,-26663,-26630
155,-26575,26534,26495,26448,26408,26360,26324,26272,26235,26188,26149
156,26101,26061,26016,25976,25930,25888,25847,25800,25763,25714,25676
157,25632,-25589,-25547,-25505,-25461,-25419,-25376,-25337,-25291,-25251,-25209
158,-25162,-25129,-25078,-25043,-24995,-24960,-24910,-24876,-24830,-24787,-24751
159,-24703,24663,24622,24583,24539,24499,24456,24418,24374,24334,24292
160,24252,24209,24173,24124,24092,24042,24011,23960,23930,23879,23845
161,23803,-23762,-23722,-23680,-23644,-23597,-23562,-23518,-23482,-23437,-23402
162,-23357,-23320,-23281,-23236,-23203,-23158,-23119,-23082,-23040,-23000,-22962
163,-22922,22885,22837,22809,22759,22728,22685,22644,22608,22567,22528
164,22491,22449,22412,22372,22334,22295,22254,22221,22173,22146,22096
165,22066,-22026,-21984,-21947,-21911,-21867,-21836,-21790,-21757,-21719,-21677
166,-21644,-21601,-21567,-21526,-21489,-21454,-21411,-21378,-21337,-21301,-21263
167,-21226,21189,21151,21111,21077,21036,21002,20964,20926,20889,20852
168,20814,20779,20741,20703,20666,20632,20590,20562,20512,20490,20440
169,20416,-20380,-20331,-20303,-20261,-20230,-20188,-20158,-20114,-20085,-20045
170,-20009,-19975,-19935,-19904,-19864,-19829,-19797,-19753,-19726,-19685,-19650
171,-19616,19580,19544,19508,19471,19441,19397,19373,19325,19301,19256
172,19229,19189,19155,19122,19081,19055,19013,18980,18947,18908,18879
173,18840,-18807,-18771,-18739,-18701,-18669,-18634,-18600,-18564,-18531,-18497
174,-18461,-18430,-18392,-18360,-18326,-18291,-18258,-18223,-18191,-18154,-18123
175,-18088,18055,18019,17989,17953,17919,17887,17853,17817,17791,17746
176,17726,17680,17656,17619,17585,17555,17519,17488,17453,17423,17385
177,17359,17320,-17287,-17261,-17220,-17196,-17156,-17128,-17093,-17062,-17029
178,-16996,-16966,-16929,-16901,-16868,-16834,-16804,-16769,-16741,-16705,-16675
179,-16644,-16609,16579,16545,16519,16479,16455,16419,16388,16359,16321
180,16300,16256,16235,16198,16166,16141,16102,16076,16043,16011,15981
181,15950,15920,-15891,-15852,-15832,-15789,-15768,-15732,-15703,-15672,-15642
182,-15609,-15582,-15548,-15521,-15487,-15459,-15426,-15401,-15364,-15339,-15305
183,-15275,-15250,15219,15184,15159,15122,15101,15061,15041,15002,14981
184,14944,14919,14886,14858,14829,14797,14772,14736,14715,14675,14657
185,14617,14598,-14567,-14533,-14506,-14475,-14447,-14419,-14389,-14358,-14334
186,-14299,-14277,-14241,-14218,-14186,-14158,-14131,-14100,-14072,-14046,-14012
187,-13991,-13955,13927,13904,13873,13844,13819,13787,13761,13732,13706
188,13674,13651,13619,13590,13570,13530,13516,13475,13457,13423,13401
189,13368,13345,-13317,-13287,-13260,-13234,-13204,-13178,-13152,-13122,-13098
190,-13068,-13043,-13013,-12990,-12958,-12937,-12902,-12884,-12849,-12829,-12798
191,-12771,-12746,12718,12693,12663,12641,12611,12586,12559,12531,12510
192,12475,12459,12421,12408,12367,12357,12315,12301,12268,12244,12218
193,12194,12164,-12140,-12113,-12093,-12056,-12043,-12008,-11987,-11961,-11931
194,-11911,-11884,-11855,-11836,-11804,-11782,-11757,-11729,-11708,-11679,-11655
195,-11631,-11601,11574,11560,11525,11508,11479,11454,11431,11403,11382
196,11356,11329,11307,11279,11260,11229,11211,11179,11161,11133,11110
197,11085,11061,-11038,-11010,-10991,-10960,-10944,-10913,-10893,-10866,-10845
198,-10818,-10796,-10772,-10747,-10725,-10699,-10676,-10653,-10629,-10605,-10580
199,-10561,-10531,10507,10491,10461,10442,10416,10394,10369,10350,10319
200,10305,10276,10252,10236,10202,10190,10160,10138,10117,10093,10070
201,10050,10020,-9997,-9984,-9953,-9935,-9912,-9885,-9871,-9840,-9823
202,-9799,-9773,-9756,-9730,-9710,-9687,-9664,-9642,-9620,-9598,-9576
203,-9554,-9532,9510,9488,9466,9444,9419,9405,9374,9361,9331
204,9314,9293,9268,9250,9225,9206,9184,9160,9143,9118,9098
205,9077,9053,-9029,-9018,-8988,-8973,-8948,-8928,-8906,-8888,-8862
206,-8848,-8819,-8805,-8780,-8760,-8740,-8720,-8695,-8681,-8653,-8638
207,-8615,-8594,8573,8556,8531,8515,8492,8472,8451,8433,8409
208,8393,8368,8354,8326,8315,8284,8277,8243,8236,8206,8192
209,8170,8151,-8133,-8107,-8095,-8068,-8054,-8030,-8014,-7991,-7975
210,-7953,-7933,-7916,-7894,-7876,-7857,-7836,-7818,-7799,-7778,-7761
211,-7740,-7720,7700,7684,7665,7645,7626,7610,7582,7577,7545
212,7534,7513,7493,7477,7455,7438,7419,7402,7379,7368,7341
213,7328,7307,-7289,-7272,-7250,-7237,-7216,-7196,-7183,-7157,-7146
214,-7123,-7108,-7091,-7065,-7058,-7030,-7020,-6998,-6979,-6965,-6944
215,-6927,-6911,6895,6870,6859,6836,6824,6800,6790,6763,6755
216,6730,6717,6699,6679,6667,6642,6632,6610,6596,6574,6564
217,6539,6529,6507,-6492,-6474,-6457,-6442,-6422,-6406,-6392,-6371
218,-6358,-6338,-6322,-6306,-6291,-6269,-6259,-6237,-6223,-6206,-6190
219,-6172,-6157,-6139,6123,6108,6088,6077,6057,6043,6025,6010
220,5992,5978,5962,5944,5928,5914,5897,5879,5869,5844,5837
221,5816,5799,5789,-5773,-5750,-5742,-5720,-5710,-5687,-5680,-5656
222,-5648,-5627,-5613,-5600,-5581,-5568,-5552,-5534,-5525,-5501,-5496
223,-5470,-5464,-5443,5430,5413,5402,5383,5370,5353,5343,5320
224,5314,5292,5280,5267,5248,5237,5219,5208,5190,5176,5162
225,5148,5131,5121,-5107,-5086,-5077,-5058,-5047,-5030,-5017,-5002
226,-4990,-4971,-4963,-4941,-4935,-4915,-4902,-4892,-4869,-4867,-4841
227,-4836,-4816,-4806,4792,4774,4767,4744,4740,4716,4712,4692
228,4680,4668,4649,4642,4624,4612,4599,4584,4570,4560,4541
229,4535,4513,4508,-4496,-4472,-4467,-4450,-4437,-4427,-4407,-4401
230,-4384,-4372,-4358,-4346,-4331,-4322,-4305,-4294,-4281,-4266,-4257
231,-4240,-4231,-4216,4204,4190,4180,4162,4156,4137,4131,4111
232,4104,4091,4075,4068,4048,4043,4026,4016,4002,3990,3980
233,3962,3957,3938,-3926,-3919,-3904,-3892,-3882,-3866,-3858,-3843
234,-3833,-3820,-3810,-3792,-3789,-3769,-3762,-3751,-3732,-3730,-3710
235,-3704,-3689,-3678,3666,3656,3640,3637,3615,3613,3594,3586
236,3576,3560,3555,3537,3529,3518,3504,3497,3481,3473,3462
237,3447,3441,3425,-3414,-3406,-3394,-3383,-3372,-3359,-3353,-3336
238,-3330,-3316,-3306,-3295,-3287,-3270,-3266,-3251,-3241,-3233,-3218
239,-3210,-3197,-3192,3182,3160,3165,3139,3140,3121,3116,3104
240,3093,3083,3075,3057,3058,3038,3033,3021,3009,3003,2990
241,2981,2969,2960,-2947,-2943,-2928,-2921,-2910,-2898,-2891,-2881
242,-2868,-2863,-2846,-2846,-2826,-2824,-2810,-2800,-2795,-2779,-2774
243,-2763,-2751,-2746,2735,2724,2715,2705,2697,2682,2682,2662
244,2663,2645,2641,2629,2620,2612,2602,2592,2585,2572,2566
245,2557,2544,2540,-2530,-2520,-2508,-2503,-2492,-2482,-2477,-2463
246,-2457,-2447,-2439,-2430,-2419,-2416,-2398,-2399,-2382,-2380,-2365
247,-2364,-2346,-2345,2335,2324,2316,2308,2301,2290,2281,2275
248,2263,2262,2241,2250,2220,2232,2211,2208,2199,2189,2180
249,2177,2161,2163,-2154,-2137,-2138,-2119,-2122,-2102,-2107,-2087
250,-2088,-2073,-2073,-2055,-2057,-2040,-2040,-2027,-2022,-2013,-2005
251,-1997,-1991,-1981,1973,1967,1959,1953,1940,1941,1922,1928
252,1908,1911,1892,1896,1879,1882,1862,1866,1850,1847,1840
253,1829,1827,1815,-1809,-1802,-1797,-1785,-1784,-1770,-1768,-1757
254,-1755,-1742,-1740,-1729,-1724,-1716,-1711,-1701,-1697,-1688,-1682
255,-1676,-1665,-1663,1654,1649,1638,1637,1624,1622,1611,1611
256,1594,1599,1582,1582,1573,1566,1560,1554,1547,1538,1538
257,1523,1524,1512,1509,-1502,-1493,-1491,-1480,-1478,-1469,-1462
258,-1458,-1450,-1444,-1441,-1427,-1431,-1414,-1418,-1405,-1400,-1397
259,-1385,-1388,-1371,-1376,1370,1354,1355,1345,1341,1334,1329
260,1323,1316,1311,1305,1299,1294,1287,1282,1276,1270,1266
261,1255,1258,1244,1244,-1239,-1226,-1231,-1212,-1220,-1205,-1202
262,-1199,-1190,-1186,-1182,-1173,-1171,-1163,-1158,-1156,-1145,-1145
263,-1136,-1131,-1128,-1121,1116,1111,1106,1100,1094,1092,1082
264,1084,1068,1075,1061,1061,1053,1047,1047,1037,1036,1025
265,1027,1016,1017,1007,-1005,-996,-998,-986,-986,-980,-973
266,-973,-962,-962,-956,-949,-949,-939,-938,-931,-929,-920
267,-921,-911,-911,-903,899,896,891,885,880,881,869
268,873,858,863,853,851,847,840,840,829,833,819
269,826,811,815,804,-801,-800,-794,-788,-791,-778,-780
270,-774,-766,-771,-755,-764,-747,-754,-742,-743,-736,-734
271,-728,-727,-718,-720,715,708,708,699,703,687,697
272,681,687,675,679,665,675,657,665,653,654,648
273,646,642,637,634,-629,-629,-621,-623,-614,-615,-607
274,-607,-602,-599,-594,-594,-586,-588,-577,-583,-571,-574
275,-567,-564,-562,-559,557,548,552,541,546,532,542
276,527,531,524,522,521,515,513,509,507,504,500
277,497,495,490,489,-485,-482,-479,-476,-474,-468,-470
278,-462,-462,-458,-455,-454,-449,-447,-443,-442,-437,-437
279,-432,-429,-429,-422,420,419,417,412,411,409,404
280,403,400,397,394,393,388,388,382,384,375,381
281,371,372,369,364,-360,-365,-355,-360,-351,-354,-347
282,-347,-345,-340,-341,-336,-335,-331,-333,-323,-329,-322
283,-319,-321,-314,-316,314,308,308,303,304,300,298
284,297,292,294,288,288,285,281,285,275,279,276
285,270,272,269,264,-260,-267,-257,-261,-256,-254,-254
286,-249,-250,-247,-244,-245,-238,-242,-235,-237,-233,-232
287,-229,-229,-225,-225,222,222,218,218,214,215,211
288,212,206,210,201,206,202,199,199,197,192,197
289,191,188,192,183,-185,-179,-189,-174,-183,-177,-174
290,-178,-169,-174,-168,-169,-167,-165,-165,-161,-162,-158
291,-160,-155,-155,-155,154,149,151,148,147,146,143
292,145,138,144,136,139,136,134,136,129,135,125
293,134,123,130,120,-119,-126,-118,-123,-116,-122,-111
294,-120,-113,-111,-115,-108,-111,-109,-108,-104,-107,-103
295,-106,-99,-104,-94,93,100,95,98,93,97,88
296,96,85,96,84,91,85,84,89,81,84,82
297,79,84,75,82,75,-76,-75,-76,-73,-74,-71
298,-73,-70,-68,-72,-65,-70,-65,-65,-67,-61,-66
299,-62,-60,-62,-61,-57,54,64,52,61,52,57
300,54,54,53,53,50,53,48,53,45,53,43
301,51,45,45,47,42,-41,-45,-43,-40,-44,-39
302,-42,-40,-38,-38,-40,-36,-39,-34,-39,-32,-37
303,-33,-34,-34,-34,-29,28,35,28,32,29,30
304,27,31,27,28,27,26,27,24,30,20,28
305,21,27,20,27,18,-19,-23,-21,-22,-19,-23
306,-16,-24,-15,-23,-15,-21,-16,-17,-20,-14,-19
307,-14,-18,-13,-19,-11,11,18,10,19,8,17
308,13,10,18,5,18,7,16,8,12,11,10
309,10,12,6,14,5,-4,-14,-5,-10,-10,-5
310,-11,-6,-8,-8,-6,-9,-5,-7,-8,-2,-12
311,-1,-8,-6,-4,-7,6,5,4,7,2,6
312,4,3,8,1,4,4,4,3,5,1,5
313,3,1,5,2,3,-1,-5,-2,0,-5,1
314,-6,2,-6,3,-6,1,-5,2,-6,5,-8
315,4,-6,3,-5,3,-2,2,1,0,1,4
316,-5,6,-3,1,3,-2,3,-3,5,-5,5
317,-1,0,0,2,-3,4,-3,0,1,-1,-1
318,2,-2,1,-1,0,1,-1,0,0,0,1
319,-1,1,-2,2,-1,1,0,-3,5,-5,4
320,-1,-2,2,-1,1,0,-1,1,-1,2,-3
321,3,-3
322};
323static signed short tock_sound[] =
324{
325 32767,32761,32767,32762,32767,32763,32767,32765,32767,32767,32766
326,32767,32764,32767,32765,32767,32763,32767,32761,32767,32765,32767
327,32766,32767,32766,32767,32767,32764,32767,32763,32767,32767,32766
328,32767,32766,32767,32767,32765,32767,32763,32767,32761,32767,32764
329,32767,-32766,-32768,-32765,-32767,-32768,-32762,-32768,-32762,-32768,-32768
330,-32765,-32768,-32765,-32768,-32766,-32766,-32766,-32766,-32768,-32766,-32768
331,-32766,-32768,-32767,-32768,-32766,-32768,-32767,-32767,-32768,-32763,-32768
332,-32765,-32768,-32768,-32765,-32768,-32767,-32768,-32768,-32767,-32766,-32768
333,-32767,32720,32666,32619,32567,32516,32471,32414,32373,32314,32270
334,32220,32167,32123,32068,32023,31970,31924,31872,31824,31775,31725
335,31678,31625,31581,31527,31482,31431,31383,31334,31286,31238,31185
336,31144,31087,31046,30993,30947,30898,30848,30804,30750,30709,30653
337,30614,-30566,-30509,-30470,-30415,-30371,-30322,-30276,-30226,-30181,-30131
338,-30085,-30039,-29988,-29945,-29894,-29849,-29800,-29756,-29707,-29658,-29617
339,-29562,-29522,-29473,-29425,-29380,-29334,-29283,-29242,-29193,-29145,-29103
340,-29051,-29011,-28959,-28917,-28866,-28827,-28773,-28735,-28682,-28641,-28591
341,-28550,28503,28457,28407,28369,28316,28275,28229,28182,28137,28094
342,28044,28006,27952,27915,27864,27823,27775,27734,27682,27645,27597
343,27550,27513,27455,27426,27368,27333,27284,27240,27197,27152,27105
344,27069,27012,26982,26926,26891,26841,26799,26756,26712,26666,26628
345,26574,-26528,-26502,-26443,-26410,-26362,-26318,-26277,-26233,-26189,-26147
346,-26103,-26059,-26019,-25973,-25931,-25888,-25846,-25801,-25763,-25714,-25675
347,-25633,-25587,-25549,-25502,-25463,-25419,-25378,-25333,-25294,-25249,-25208
348,-25167,-25123,-25084,-25037,-25000,-24954,-24917,-24871,-24832,-24788,-24748
349,-24706,24665,24622,24582,24539,24501,24454,24420,24371,24336,24292
350,24251,24212,24167,24131,24084,24052,24001,23969,23921,23886,23842
351,23804,23760,23724,23678,23644,23598,23561,23521,23478,23440,23401
352,23356,23324,23275,23243,23197,23161,23118,23082,23039,23003,22959
353,22922,-22882,-22844,-22801,-22763,-22729,-22679,-22653,-22601,-22569,-22529
354,-22488,-22453,-22409,-22374,-22331,-22297,-22254,-22220,-22176,-22141,-22100
355,-22064,-22024,-21985,-21947,-21910,-21869,-21833,-21794,-21754,-21721,-21675
356,-21645,-21601,-21566,-21529,-21486,-21455,-21410,-21380,-21335,-21304,-21258
357,-21232,21195,21144,21118,21072,21038,21003,20960,20932,20882,20858
358,20810,20781,20740,20703,20668,20628,20595,20557,20518,20483,20447
359,20409,20374,20336,20299,20265,20225,20194,20150,20123,20079,20047
360,20008,19975,19937,19902,19866,19827,19797,19755,19725,19682,19654
361,19614,-19581,-19540,-19512,-19471,-19437,-19405,-19362,-19335,-19292,-19264
362,-19223,-19194,-19151,-19124,-19082,-19053,-19014,-18980,-18946,-18911,-18876
363,-18842,-18804,-18775,-18735,-18704,-18668,-18634,-18598,-18568,-18527,-18500
364,-18460,-18428,-18394,-18360,-18324,-18295,-18254,-18225,-18190,-18154,-18124
365,-18087,18054,18021,17987,17953,17921,17884,17855,17818,17786,17754
366,17718,17685,17654,17619,17586,17554,17519,17488,17454,17421,17387
367,17358,17319,17295,17251,17230,17186,17164,17123,17096,17061,17028
368,16996,16967,16929,16902,16865,16837,16801,16774,16736,16708,16675
369,16641,16612,-16578,-16549,-16513,-16486,-16449,-16423,-16385,-16361,-16321
370,-16297,-16260,-16233,-16198,-16169,-16137,-16102,-16080,-16038,-16017,-15976
371,-15954,-15914,-15892,-15855,-15826,-15796,-15762,-15735,-15702,-15673,-15638
372,-15617,-15572,-15556,-15515,-15489,-15461,-15424,-15400,-15365,-15338,-15304
373,-15281,-15241,15212,15189,15155,15125,15098,15064,15038,15005,14977
374,14947,14918,14886,14859,14827,14799,14771,14738,14711,14681,14651
375,14623,14592,14565,14532,14508,14474,14449,14416,14391,14357,14334
376,14301,14273,14246,14214,14188,14159,14128,14104,14069,14046,14016
377,13986,13958,-13928,-13905,-13869,-13849,-13816,-13789,-13758,-13736,-13702
378,-13678,-13649,-13616,-13598,-13561,-13539,-13508,-13480,-13455,-13424,-13399
379,-13371,-13341,-13318,-13284,-13263,-13232,-13205,-13179,-13150,-13124,-13096
380,-13069,-13041,-13017,-12984,-12965,-12930,-12908,-12881,-12849,-12831,-12793
381,-12779,-12739,12714,12694,12666,12636,12616,12583,12561,12531,12509
382,12476,12459,12421,12406,12373,12347,12325,12294,12271,12244,12218
383,12194,12164,12142,12112,12091,12062,12038,12009,11989,11956,11939
384,11903,11888,11855,11834,11806,11782,11755,11732,11705,11679,11658
385,11628,11605,-11579,-11557,-11527,-11505,-11480,-11455,-11429,-11406,-11380
386,-11355,-11331,-11305,-11283,-11256,-11231,-11210,-11178,-11166,-11126,-11117
387,-11080,-11063,-11037,-11010,-10992,-10961,-10940,-10916,-10890,-10871,-10838
388,-10825,-10791,-10774,-10747,-10724,-10699,-10679,-10648,-10634,-10600,-10586
389,-10554,-10537,10513,10485,10466,10438,10420,10391,10370,10349,10321
390,10305,10273,10257,10228,10211,10183,10164,10138,10115,10096,10066
391,10053,10019,10007,9975,9960,9930,9916,9883,9871,9839,9823
392,9801,9771,9759,9726,9714,9684,9666,9640,9623,9596,9577
393,9553,9532,-9510,-9487,-9467,-9443,-9422,-9401,-9377,-9358,-9334
394,-9313,-9292,-9270,-9248,-9227,-9205,-9182,-9165,-9138,-9121,-9098
395,-9075,-9057,-9032,-9015,-8989,-8973,-8947,-8929,-8907,-8885,-8867
396,-8842,-8824,-8802,-8780,-8763,-8737,-8720,-8699,-8676,-8657,-8637
397,-8614,-8597,8576,8554,8532,8513,8494,8470,8454,8429,8413
398,8390,8371,8351,8328,8314,8286,8274,8247,8233,8207,8192
399,8170,8149,8134,8108,8092,8070,8053,8031,8014,7991,7974
400,7953,7935,7912,7899,7872,7861,7832,7820,7798,7779,7761
401,7739,7724,-7706,-7679,-7669,-7641,-7628,-7607,-7588,-7570,-7551
402,-7530,-7515,-7491,-7478,-7456,-7438,-7419,-7401,-7379,-7369,-7338
403,-7335,-7300,-7295,-7267,-7255,-7233,-7218,-7196,-7181,-7159,-7145
404,-7124,-7107,-7090,-7068,-7055,-7033,-7018,-6999,-6979,-6966,-6942
405,-6929,-6909,6891,6875,6855,6840,6820,6803,6787,6768,6750
406,6733,6717,6695,6687,6657,6650,6629,6608,6599,6573,6562
407,6543,6525,6508,6494,6470,6462,6437,6426,6405,6391,6371
408,6358,6338,6323,6305,6289,6273,6254,6241,6221,6206,6191
409,6170,6160,6136,-6121,-6108,-6090,-6075,-6057,-6044,-6023,-6013
410,-5988,-5983,-5955,-5950,-5926,-5914,-5897,-5879,-5867,-5846,-5837
411,-5813,-5806,-5780,-5774,-5751,-5741,-5720,-5710,-5687,-5680,-5656
412,-5648,-5626,-5616,-5596,-5584,-5566,-5552,-5538,-5519,-5507,-5490
413,-5475,-5463,-5440,5425,5419,5396,5385,5373,5350,5342,5324
414,5308,5297,5278,5266,5250,5236,5218,5209,5190,5176,5162
415,5148,5131,5120,5103,5088,5075,5061,5043,5035,5013,5005
416,4988,4973,4960,4946,4931,4916,4905,4885,4879,4856,4850
417,4829,4823,4799,-4785,-4783,-4758,-4749,-4738,-4718,-4710,-4693
418,-4679,-4669,-4649,-4643,-4621,-4616,-4596,-4585,-4572,-4555,-4548
419,-4527,-4521,-4501,-4492,-4477,-4464,-4451,-4437,-4425,-4410,-4399
420,-4384,-4372,-4359,-4345,-4332,-4320,-4307,-4292,-4283,-4265,-4256
421,-4243,-4227,-4217,4201,4196,4171,4173,4145,4147,4123,4117
422,4103,4087,4079,4065,4051,4042,4026,4014,4005,3988,3981
423,3962,3956,3939,3931,3917,3903,3892,3882,3866,3860,3841
424,3831,3824,3804,3800,3782,3772,3761,3749,3737,3726,3712
425,3702,3690,3679,-3667,-3656,-3640,-3637,-3614,-3614,-3594,-3587
426,-3573,-3564,-3549,-3542,-3528,-3517,-3506,-3494,-3482,-3475,-3458
427,-3452,-3437,-3427,-3417,-3406,-3392,-3384,-3372,-3359,-3354,-3335
428,-3330,-3316,-3306,-3297,-3283,-3276,-3259,-3256,-3239,-3232,-3220
429,-3210,-3196,-3192,3182,3161,3161,3143,3137,3124,3114,3103
430,3096,3080,3075,3060,3054,3040,3034,3018,3013,2999,2992
431,2980,2971,2958,2953,2937,2933,2918,2910,2901,2889,2881
432,2869,2862,2849,2842,2828,2824,2810,2801,2793,2780,2774
433,2762,2755,2740,-2730,-2729,-2711,-2706,-2697,-2683,-2681,-2665
434,-2658,-2650,-2636,-2633,-2618,-2614,-2599,-2593,-2585,-2571,-2568
435,-2556,-2542,-2544,-2521,-2526,-2507,-2502,-2492,-2483,-2474,-2467
436,-2455,-2447,-2440,-2428,-2422,-2412,-2402,-2396,-2385,-2376,-2369
437,-2359,-2351,-2344,2336,2323,2319,2303,2306,2282,2290,2269
438,2268,2254,2251,2238,2234,2221,2217,2203,2203,2187,2184
439,2171,2168,2155,2150,2141,2132,2125,2116,2109,2099,2094
440,2083,2078,2066,2062,2052,2045,2037,2027,2023,2011,2009
441,1994,1992,1980,-1973,-1967,-1959,-1950,-1945,-1937,-1926,-1923
442,-1911,-1907,-1899,-1889,-1885,-1873,-1871,-1860,-1853,-1847,-1838
443,-1832,-1824,-1816,-1811,-1801,-1795,-1789,-1778,-1776,-1765,-1759
444,-1753,-1742,-1742,-1726,-1728,-1714,-1710,-1703,-1696,-1688,-1682
445,-1676,-1664,-1667,1661,1641,1645,1632,1625,1625,1607,1612
446,1596,1596,1585,1581,1570,1571,1556,1556,1546,1539,1536
447,1525,1523,1512,1511,1497,1499,1487,1481,1480,1465,1466
448,1455,1450,1447,1436,1434,1423,1420,1414,1407,1401,1395
449,1388,1382,1379,1369,-1364,-1359,-1352,-1348,-1338,-1336,-1328
450,-1322,-1318,-1310,-1305,-1300,-1291,-1290,-1280,-1277,-1269,-1267
451,-1256,-1255,-1246,-1242,-1238,-1228,-1225,-1221,-1212,-1209,-1203
452,-1195,-1193,-1186,-1180,-1175,-1170,-1163,-1161,-1150,-1150,-1142
453,-1137,-1133,-1126,-1119,1113,1112,1105,1100,1096,1089,1084
454,1080,1075,1068,1067,1054,1059,1045,1045,1041,1031,1031
455,1022,1018,1016,1007,1006,997,996,987,986,979,975
456,970,966,959,957,949,948,940,939,928,932,920
457,918,915,907,906,-900,-896,-890,-885,-883,-877,-871
458,-870,-862,-860,-856,-848,-848,-841,-837,-834,-827,-827
459,-817,-817,-811,-808,-803,-798,-794,-791,-786,-783,-777
460,-774,-769,-765,-763,-756,-754,-748,-746,-741,-737,-732
461,-731,-722,-727,-710,707,714,704,700,702,690,693
462,684,685,676,677,671,665,668,656,657,653,649
463,644,645,632,640,626,631,620,623,614,615,607
464,608,601,598,598,588,592,582,584,576,577,568
465,571,564,561,558,-554,-553,-546,-546,-541,-540,-532
466,-537,-522,-531,-519,-521,-515,-513,-510,-505,-507,-495
467,-503,-489,-495,-486,-486,-481,-480,-476,-472,-472,-465
468,-467,-458,-461,-453,-455,-450,-444,-446,-439,-441,-433
469,-435,-428,-428,-425,424,416,417,413,411,407,407
470,401,400,397,396,389,394,381,388,379,381,375
471,376,368,371,365,365,360,360,356,353,353,347
472,347,346,340,339,339,331,337,326,330,323,325
473,319,321,312,318,-316,-305,-310,-303,-303,-302,-296
474,-298,-292,-293,-289,-288,-285,-283,-281,-279,-278,-274
475,-273,-269,-271,-265,-265,-264,-257,-262,-255,-254,-255
476,-248,-250,-247,-243,-247,-236,-244,-232,-240,-231,-232
477,-232,-223,-232,-220,219,224,217,218,216,212,212
478,212,207,208,204,202,204,200,197,197,195,193
479,194,187,191,186,184,187,177,186,175,180,175
480,173,175,169,172,168,165,167,162,166,157,162
481,156,158,156,152,-152,-151,-149,-149,-146,-147,-142
482,-145,-140,-141,-138,-137,-139,-131,-138,-128,-135,-126
483,-132,-124,-129,-123,-125,-121,-123,-116,-123,-116,-117
484,-115,-113,-114,-112,-112,-107,-110,-108,-104,-109,-100
485,-105,-103,-99,-101,99,99,94,98,93,96,89
486,96,87,91,88,89,86,88,81,86,83,82
487,82,78,83,73,83,73,77,76,72,74,73
488,69,73,70,67,71,63,71,62,69,59,68
489,58,66,58,63,57,-58,-58,-57,-56,-56,-55
490,-56,-51,-57,-47,-56,-48,-53,-49,-48,-50,-45
491,-50,-45,-46,-46,-43,-45,-43,-43,-41,-43,-39
492,-43,-37,-42,-35,-42,-34,-39,-36,-36,-35,-35
493,-34,-34,-34,-31,-35,35,28,34,27,35,23
494,35,23,32,26,27,28,24,28,23,27,24
495,24,25,21,25,22,22,23,19,23,20,20
496,22,16,23,15,23,13,23,12,23,13,18
497,16,15,16,16,14,-14,-14,-16,-11,-18,-9
498,-17,-8,-17,-10,-14,-10,-11,-13,-10,-12,-9
499,-10,-11,-9,-11,-8,-9,-10,-6,-13,-4,-12
500,-4,-12,-2,-14,-1,-12,-3,-8,-6,-7,-6
501,-6,-5,-6,-5,-6,6,3,8,2,7,2
502,7,2,6,1,6,4,1,9,-5,12,-5
503,10,-1,5,0,5,1,5,0,3,3,1
504,3,2,1,3,0,5,-2,4,0,2,3
505,-1,4,-3,6,-3,2,-2,-2,0,-1,-2
506,1,-1,-2,1,-2,0,0,-2,2,-3,2
507,-4,4,-5,5,-5,2,0,-1,0,1,-4
508,5,-5,4,-3,2,-1,-1,1,-2,2,-2
509,2,-2,2,-1,0,1,-1,0,1,-2,3
510,-3,2,-1,0,1,-1,0,0,1,-1,1
511,-2,3
512};
513
514/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
515 Utilities from pdbox plugin (Copyright (C) 2009 Wincent Balin) --- am I
516 supposed to supply these functions with the plugin? Should I use a library?
517* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
518
519/* Implementation of strtod() and atof(),
520 taken from SanOS (http://www.jbox.dk/sanos/). */
521static int rb_errno = 0;
522
523static double rb_strtod(const char *str, char **endptr)
524{
525 double number;
526 int exponent;
527 int negative;
528 char *p = (char *) str;
529 double p10;
530 int n;
531 int num_digits;
532 int num_decimals;
533
534 /* Reset Rockbox errno -- W.B. */
535#ifdef ROCKBOX
536 rb_errno = 0;
537#endif
538
539 // Skip leading whitespace
540 while (isspace(*p)) p++;
541
542 // Handle optional sign
543 negative = 0;
544 switch (*p)
545 {
546 case '-': negative = 1; // Fall through to increment position
547 case '+': p++;
548 }
549
550 number = 0.;
551 exponent = 0;
552 num_digits = 0;
553 num_decimals = 0;
554
555 // Process string of digits
556 while (isdigit(*p))
557 {
558 number = number * 10. + (*p - '0');
559 p++;
560 num_digits++;
561 }
562
563 // Process decimal part
564 if (*p == '.')
565 {
566 p++;
567
568 while (isdigit(*p))
569 {
570 number = number * 10. + (*p - '0');
571 p++;
572 num_digits++;
573 num_decimals++;
574 }
575
576 exponent -= num_decimals;
577 }
578
579 if (num_digits == 0)
580 {
581#ifdef ROCKBOX
582 rb_errno = 1;
583#else
584 errno = ERANGE;
585#endif
586 return 0.0;
587 }
588
589 // Correct for sign
590 if (negative) number = -number;
591
592 // Process an exponent string
593 if (*p == 'e' || *p == 'E')
594 {
595 // Handle optional sign
596 negative = 0;
597 switch(*++p)
598 {
599 case '-': negative = 1; // Fall through to increment pos
600 case '+': p++;
601 }
602
603 // Process string of digits
604 n = 0;
605 while (isdigit(*p))
606 {
607 n = n * 10 + (*p - '0');
608 p++;
609 }
610
611 if (negative)
612 exponent -= n;
613 else
614 exponent += n;
615 }
616
617#ifndef ROCKBOX
618 if (exponent < DBL_MIN_EXP || exponent > DBL_MAX_EXP)
619 {
620 errno = ERANGE;
621 return HUGE_VAL;
622 }
623#endif
624
625 // Scale the result
626 p10 = 10.;
627 n = exponent;
628 if (n < 0) n = -n;
629 while (n)
630 {
631 if (n & 1)
632 {
633 if (exponent < 0)
634 number /= p10;
635 else
636 number *= p10;
637 }
638 n >>= 1;
639 p10 *= p10;
640 }
641
642#ifndef ROCKBOX
643 if (number == HUGE_VAL) errno = ERANGE;
644#endif
645 if (endptr) *endptr = p;
646
647 return number;
648}
649
650static double rb_atof(const char *str)
651{
652 return rb_strtod(str, NULL);
653}
654
655/* * * * * * * * * * * * * * * * * * * * * * *
656 Actual metronome stuff
657* * * * * * * * * * * * * * * * * * * * * * */
658
659static int fd = -1; /* file descriptor, global for cleanup(). */
660
661/* Round fixed-point number to integer. */
662static int fp_rint(long fp_num)
663{
664 fp_num += fp_num > 0 ? +((long)1<<15) : -((long)1<<15);
665 return (int)(fp_num / ((long)1<<16));
666}
667/* float to fixed-point */
668static long fp_frac(float fl_num)
669{
670 return (long)(fl_num*((long)1<<16));
671}
672
673/* simple dynamic memory management
674 - only allocate blocks serially
675 - deallocation of most recent blocks by resetting the free region pointer
676 - everything aligned to 4 bytes (wasting some bytes, but playing safe)
677*/
678static void *mem_begin = NULL; /* beginning of managed region. */
679static void *mem_end = NULL; /* just after end of managed region */
680static void *mem_free_region = NULL; /* pointer to unused free space */
681static void *mem_checkpointer = NULL; /* position to reset to */
682
683/* Initialize memory management. */
684static void mem_init(void)
685{
686 size_t bufsize;
687 /* Can I trust that pointer to be aligned? Better be safe. */
688 mem_begin = ALIGN_UP(rb->plugin_get_buffer(&bufsize), 4);
689 mem_end = mem_begin + bufsize - 3;
690 mem_free_region = mem_begin;
691 mem_checkpointer = mem_begin;
692}
693
694/* Remember and reset free region, for temporary mem usage. */
695static void mem_checkpoint(void){ mem_checkpointer = mem_free_region; }
696static void mem_reset (void){ mem_free_region = mem_checkpointer; }
697static void *mem_allocate(size_t bytes)
698{
699 void *handout = mem_free_region;
700 /* Always handing out multiples of alignment size. */
701 if(bytes % 4) bytes += 4 - bytes % 4;
702 if(mem_free_region + bytes >= mem_end)
703 {
704 rb->splash(2*HZ, "Out Of Memory");
705 return NULL;
706 }
707 mem_free_region += bytes;
708 return handout;
709}
710
711struct part;
712struct part /* One part of a track, with one tempo (range), meter, etc. */
713{
714 struct part *prev, *next; /* linked list links*/
715 unsigned int id; /* index (in order, please) */
716 char *label;
717 unsigned int bars; /* Duration of part in bars. */
718 unsigned int beats_per_bar; /* 3 in 3/4 */
719 unsigned int base_beat; /* 4 in 3/4 to adjust bpm value */
720 unsigned int bpm; /* base tempo (1/4 notes per minute) */
721 unsigned int bpm2; /* end tempo */
722 unsigned int *beat_bpm; /* either NULL or (bars*beats_per_bar) values */
723 long accel; /* fixed-point acceleration in 1/min (really) */
724 int volume; /* volume offset in integer dB */
725 /* Store pattern characters verbatim for max. 64 beats (no string
726 termination). One could save storage here by encoding things in bits,
727 or by allocating dynamically to begin with. */
728 char *pattern;
729};
730
731static struct part *part_list = NULL; /* linked list of parts */
732static struct part *part = NULL; /* current part */
733static unsigned int parts = 0; /* total number of parts */
734static unsigned int bad_parts = 0; /* Count parts with parsing errors. */
735
736/* Initialize a part that is not yet placed into the list. */
737static void part_init(struct part *ps)
738{
739 ps->prev = NULL;
740 ps->next = NULL;
741 ps->id = 0;
742 ps->label = NULL;
743 ps->bars = 0;
744 ps->beats_per_bar = 4;
745 ps->base_beat = 4;
746 ps->bpm = 120;
747 ps->bpm2 = 120;
748 ps->beat_bpm = NULL;
749 ps->accel = 0;
750 ps->volume = 0;
751 ps->pattern = NULL;
752}
753
754/* Add to the list. */
755static void part_add(struct part *ps)
756{
757 if(part)
758 {
759 part->next = ps;
760 ps->prev = part;
761 part = ps;
762 }
763 else part = part_list = ps;
764
765 ps->id = parts++;
766}
767
768/* Stay away from zero. */
769static unsigned int positive(long long value)
770{
771 return value > 0 ? value : 1;
772}
773
774/* Yay! Global state variables! */
775static bool track_mode = false; /* switch for programmed tracks metronome */
776static int loop = 0; /* Needed? */
777static unsigned int beat = 0;
778static unsigned int bar = 0; /* How big shall this become? */
779/* The currently (approximate) active bpm value, set from calc_period(). */
780static unsigned int bpm = 1;
781
782/* Should be unsigned? */
783static unsigned int period = 0; /* beat interval in timer ticks */
784static long period_diff = 0; /* fixed-point error of last period computation */
785static unsigned int minitick = 0; /* elapsed ticks */
786static bool beating = false; /* A beat is/was playing and count needs to increase. */
787static int display_state = 0; /* Current display state code. */
788static bool display_trigger = false; /* Draw display on next occasion */
789
790static bool sound_active = false;
791static bool sound_paused = true;
792
793/* global static buffer for messages in any situation */
794static char buffer[64];
795/* For line parsing, more is needed, allocated on demand.
796 As my memory management doesn't allow to free it, keeping it local
797 ist not smart. */
798static char* linebuf = NULL;
799size_t linebuf_size = 0;
800
801
802/* global state for tempo tapping */
803static bool reset_tap = false;
804static int tap_count = 0;
805static int tap_time = 0;
806static int tap_timeout = 0;
807
808static int bpm_step_counter = 0;
809
810static bool sound_trigger = false;
811
812#define MET_IS_PLAYING rb->pcm_is_playing()
813#define MET_PLAY_STOP rb->audio_stop()
814
815/* Really necessary? Cannot just play mono?
816 Also: This is wasted memory! */
817static short tick_buf[sizeof(tick_sound)*2];
818static short tock_buf[sizeof(tock_sound)*2];
819
820/* Convert the mono samples to interleaved stereo */
821static void prepare_buffers(void)
822{
823 size_t i;
824 for(i = 0;i < sizeof(tick_sound)/sizeof(short);i++)
825 tick_buf[i*2] = tick_buf[i*2+1] = tick_sound[i];
826 for(i = 0;i < sizeof(tock_sound)/sizeof(short);i++)
827 tock_buf[i*2] = tock_buf[i*2+1] = tock_sound[i];
828}
829
830static void play_tick(void)
831{
832 rb->pcm_play_data(NULL, NULL, tick_buf, sizeof(tick_buf));
833}
834
835static void play_tock(void)
836{
837 rb->pcm_play_data(NULL, NULL, tock_buf, sizeof(tock_buf));
838}
839
840/* State: 0: blank/title, 1: tick, 2: tock 3: silent klick */
841/* TODO: Could use more smart placement, using
842 lcd_getstringsize() and such. */
843static void metronome_draw(struct screen* display, int state)
844{
845 struct part *ps;
846 int textlen = display->lcdwidth / display->getcharwidth();
847 ps = part;
848 display->clear_display();
849 display->setfont(FONT_SYSFIXED);
850 int rectangle_height = display->lcdheight - ((SYSFONT_HEIGHT + 1) * 7);
851 if (rectangle_height < 12)
852 rectangle_height = 12;
853 switch(state)
854 {
855 case 0:
856 if(sound_paused)
857 {
858 if(track_mode) display->puts(0, 0, "Metronome Track");
859 else display->puts(0, 0, "Metronome");
860
861 display->hline(0, display->lcdwidth, 12);
862 }
863 break;
864 /* Draw odd/even ticks/tocks differently to be able to go without
865 display clearing in between for fast beats. */
866 case 1:
867 if((beat+1) % 2 == 0)
868 display->fillrect( display->lcdwidth/2, 0
869 , display->lcdwidth, rectangle_height );
870 else
871 display->fillrect( 0, 0
872 , display->lcdwidth/2-1, rectangle_height );
873 break;
874 case 2:
875 if((beat+1) % 2 == 0)
876 display->fillrect( display->lcdwidth/2, display->lcdheight - rectangle_height - 1
877 , display->lcdwidth, rectangle_height );
878 else
879 display->fillrect( 0, display->lcdheight - rectangle_height - 1
880 , display->lcdwidth/2-1, rectangle_height );
881 break;
882 case 3:
883 display->puts((textlen-3)/2,0, "o.O");
884 break;
885 }
886
887 if(track_mode)
888 {
889
890 /* One line in several. */
891 rb->snprintf( buffer, sizeof(buffer), "%u/%u@%u V%d"
892 , ps->beats_per_bar, ps->base_beat
893 , bpm, rb->global_status->volume );
894 display->puts(0,4, buffer);
895
896 /* Would it hurt to draw a 3rd line to 2-line display?
897 I guess there are 3-line displays out there. */
898 if(ps->label && rb->strlen(ps->label))
899 {
900 rb->snprintf(buffer, sizeof(buffer), "\"%s\"", ps->label);
901 display->puts((textlen-rb->strlen(buffer))/2, 2, buffer);
902 }
903
904 /* Wildly guessing here with puts(). */
905 if(ps->bars)
906 rb->snprintf( buffer, sizeof(buffer), "P%u/%u: B%u/%u+%u"
907 , part->id+1, parts, bar+1, ps->bars, beat+1 );
908 else
909 rb->snprintf( buffer, sizeof(buffer), "P%u/%u: B%u/_+%u"
910 , part->id+1, parts, bar+1, beat+1 );
911 display->puts(0, 5, buffer);
912
913 }
914 else /* track mode */
915 {
916
917 if(display->screen_type==SCREEN_MAIN)
918 {
919#ifdef MET_SYNC
920 display->puts(0, 5, "Select=TAP Rec=SYNC");
921#else
922 display->puts(0, 5, "Select=TAP");
923#endif
924 }
925#ifdef HAVE_REMOTE_LCD
926 else
927 {
928#ifdef MET_SYNC
929 display->puts(0, 5, "Rec=TAP Mode=SYNC");
930#else
931 display->puts(0, 5, "Rec=TAP");
932#endif
933 }
934#endif
935
936 rb->snprintf( buffer, sizeof(buffer), "BPM: %d Vol: %d"
937 , bpm, rb->global_status->volume );
938 display->puts(0,3, buffer);
939
940 display->hline(0, 111, 12);
941 if(sound_paused) display->puts(0,2,"start: hold select");
942 else display->puts(0,2,"stop : cancel");
943
944 } /* !track_mode */
945
946 display->setfont(FONT_UI);
947 display->update();
948}
949
950/* Trigger drawing of display at the next occasion using given state. */
951static void trigger_display(int state)
952{
953 display_state = state;
954 display_trigger = true;
955}
956
957/* Actually draw display. */
958static void draw_display(void)
959{
960 FOR_NB_SCREENS(i)
961 metronome_draw(rb->screens[i], display_state);
962}
963
964/* Modify actual volume by given offset without changing the configured one.
965 This is for parts with associated volume. */
966static void tweak_volume(int offset)
967{
968 int vol = rb->global_status->volume + offset;
969 int minvol = rb->sound_min(SOUND_VOLUME);
970 int maxvol = rb->sound_max(SOUND_VOLUME);
971
972 if (vol > maxvol) vol = maxvol;
973 else if(vol < minvol) vol = minvol;
974
975 rb->sound_set(SOUND_VOLUME, vol);
976}
977
978/* tempo at a certain point in beat space in an accelerated part */
979static long accel_tempo(struct part *ps, long offset)
980{
981 long fp_bpm = (long)ps->bpm<<16;
982 long fp_bpm2 = (long)ps->bpm2<<16;
983 long v = fp_bpm + fp_mul(ps->accel, offset, 16);
984 /* Offset could be negative, actually, so ensure tempo stays within both
985 bounds */
986 if(ps->accel > 0)
987 {
988 if(v < fp_bpm) v = fp_bpm;
989 if(v > fp_bpm2) v = fp_bpm2;
990 }
991 else /* deceleration */
992 {
993 if(v > fp_bpm) v = fp_bpm;
994 if(v < fp_bpm2) v = fp_bpm2;
995 }
996 return v;
997}
998
999/* Calculate number of ticks to wait till next beat. */
1000static void calc_period(void)
1001{
1002 struct part *ps = part;
1003 long deltat;
1004 long beatlen; /* in quarter notes */
1005 long period_fp;
1006
1007 beatlen = fp_div(4<<16, ps->base_beat<<16, 16);
1008 /* Hack: Put the factor 60 in before computing deltat, to preserve
1009 some accuracty. */
1010 if(ps->beat_bpm)
1011 {
1012 bpm = ps->beat_bpm[bar*ps->beats_per_bar+beat];
1013 deltat = fp_div(fp_mul(60<<16,beatlen,16), bpm<<16, 16);
1014 } else
1015 if(ps->accel == 0.f)
1016 { /* Fixed tempo. */
1017 bpm = ps->bpm;
1018 /* Minutes per base beat, from quarters per minute. */
1019 deltat = fp_div(fp_mul(60<<16,beatlen,16), bpm<<16, 16);
1020 }
1021 else
1022 { /* Acceleration, varying period with each beat. */
1023 long v0, v1;
1024 long offset = (bar*ps->beats_per_bar + beat) << 16;
1025 /* Always computed from start of part for seeking and accuracy. */
1026 v0 = accel_tempo(ps, fp_mul(beatlen, offset, 16));
1027 offset += 1<<16;
1028 v1 = accel_tempo(ps, fp_mul(beatlen, offset, 16));
1029 /* Playing safe with too small tempo changes, avoiding the acceleration
1030 math that might divide by very small deltat. */
1031 if(labs(v1-v0) > 1<<8)
1032 {
1033 /* deltat = 1.f / ps->accel * rb_log(v1/v0) */
1034 deltat = fp_mul( fp_div(60<<16, ps->accel, 16)
1035 , fp16_log(fp_div(v1, v0, 16))
1036 , 16 );
1037 bpm = fp_rint(fp_div(fp_mul(60<<16, beatlen, 16), deltat, 16));
1038 }
1039 else
1040 { /* Arbitrarily choosing v1. */
1041 bpm = fp_rint(v1);
1042 deltat = fp_div(fp_mul(60<<16,beatlen,16), v1, 16);
1043 }
1044 }
1045 /* The treatment of the rounding error when converting to integer
1046 period using period_diff helps a lot to keep track lengths close to
1047 "correct" even with timerfreq_div as low as 77. Actually, I have _less_
1048 drift than with timerfreq_div of 1000! */
1049 period_fp = fp_mul(timerfreq_div<<16, deltat, 16) + period_diff;
1050 period = positive(fp_rint( period_fp ));
1051 period_diff = period_fp - (long)(period<<16);
1052}
1053
1054/* Last beat finished, to prepare for the next one. */
1055static void advance_beat(void)
1056{
1057 if(++beat == part->beats_per_bar)
1058 {
1059 beat = 0;
1060 /* Bar counter always incremented for acceleration, but only checked
1061 against a limit if there is one. */
1062 ++bar;
1063 if(part->bars && bar == part->bars)
1064 {
1065 bar = 0;
1066 if(part->next) part = part->next;
1067 else
1068 {
1069 part = part_list;
1070 if(!loop) sound_paused = true;
1071 }
1072 tweak_volume(part->volume);
1073 }
1074 }
1075 /* Always recompute period, as acceleration changes it for each beat. */
1076 calc_period();
1077}
1078
1079/* Decide what to play, update display, play it.
1080 Beat counting happens here, too. */
1081static void play_ticktock(void)
1082{
1083 if(beating) advance_beat();
1084
1085 /* Hack: Clear trigger to avoid race condition. */
1086 display_trigger = 0;
1087 if(sound_paused)
1088 {
1089 beating = false;
1090 display_state = 0;
1091 draw_display();
1092 }
1093 else
1094 {
1095 char pat = 'x';
1096 if(part->pattern) pat = part->pattern[beat];
1097
1098 beating = true;
1099 /* Blinking and specific sound for tick, tock and silent beat.
1100 Drawing display first for slow machines (YH820), to avoid
1101 interrupting audio for regular playback. */
1102 switch(pat)
1103 {
1104 case 'X':
1105 display_state = 1;
1106 draw_display();
1107 play_tick();
1108 break;
1109 case 'x':
1110 display_state = 2;
1111 draw_display();
1112 play_tock();
1113 break;
1114 default:
1115 display_state = 3;
1116 draw_display();
1117 }
1118 }
1119}
1120
1121/* helper function to change the volume by a certain amount, +/-
1122 ripped from video.c */
1123static void change_volume(int delta)
1124{
1125 int minvol = rb->sound_min(SOUND_VOLUME);
1126 int maxvol = rb->sound_max(SOUND_VOLUME);
1127 int vol = rb->global_status->volume + delta;
1128
1129 if (vol > maxvol) vol = maxvol;
1130 else if(vol < minvol) vol = minvol;
1131 if(vol != rb->global_status->volume)
1132 {
1133 rb->global_status->volume = vol;
1134 tweak_volume(part->volume);
1135 trigger_display(display_state);
1136 }
1137}
1138
1139/*function to accelerate bpm change*/
1140static void change_bpm(int direction)
1141{
1142 if( (bpm_step_counter < 20)
1143 || (bpm > 389)
1144 || (bpm < 10) )
1145 bpm = bpm + direction;
1146 else if(bpm_step_counter < 60)
1147 bpm = bpm + direction * 2;
1148 else
1149 bpm = bpm + direction * 9;
1150
1151 if(bpm > 400) bpm = 400;
1152 if(bpm < 1) bpm = 1;
1153
1154 part->bpm = bpm;
1155 calc_period();
1156 trigger_display(display_state);
1157 bpm_step_counter++;
1158}
1159
1160/* I presume the timer ensures that not more than one instance
1161 of the callback is running at a given time. */
1162static void timer_callback(void)
1163{
1164 ++minitick;
1165
1166 /* Clear blinker if tempo is slow enough. */
1167 if( (bpm*part->base_beat)/4 <= blinklimit &&
1168 !sound_paused && minitick == period/2 )
1169 trigger_display(0);
1170
1171 if(minitick >= period)
1172 {
1173 minitick = 0;
1174 if(!sound_active && !sound_paused && !tap_count)
1175 {
1176 sound_trigger = true;
1177 rb->reset_poweroff_timer();
1178 }
1179 }
1180
1181 if(tap_count)
1182 {
1183 tap_time++;
1184 if(tap_count > 1 && tap_time > tap_timeout)
1185 tap_count = 0;
1186 }
1187}
1188
1189/* Stopping playback means incrementing the beat. Normally, it would be
1190 incremented after the passing of the current note duration, naturally
1191 while starting the next one. */
1192static void metronome_pause(void)
1193{
1194 if(beating)
1195 {
1196 /* Finish the current beat. */
1197 advance_beat();
1198 beating = false;
1199 }
1200 sound_paused = true;
1201 trigger_display(0);
1202 rb->timer_unregister();
1203}
1204
1205static void metronome_unpause(void)
1206{
1207 sound_paused = false;
1208 minitick = period; /* Start playing immediately (or after a millisecond). */
1209 /* Conserve power: Only start timer when actually playing. */
1210 rb->timer_register( 1, NULL, TIMER_FREQ/timerfreq_div
1211 , timer_callback IF_COP(, CPU) );
1212}
1213
1214static void cleanup(void)
1215{
1216 if(fd >= 0) rb->close(fd);
1217
1218 metronome_pause();
1219 MET_PLAY_STOP; /* stop audio ISR */
1220 tweak_volume(0);
1221 rb->led(0);
1222 rb->pcm_set_frequency(HW_SAMPR_DEFAULT);
1223}
1224
1225/*
1226 Parse part definitions from tempomap file (see header for format).
1227 Not bothering with encoding issues here.
1228*/
1229
1230/* parse meter spec into part structure if given token matches */
1231static bool parse_meter(char *token, struct part *ps)
1232{
1233 char *toktok;
1234 /* Careful not to misinterpret accelerated tempo specification:
1235 120-150/4 -> tempo
1236 3/4 -> meter */
1237 if( !rb->strchr(token, '-') && (toktok = rb->strchr(token, '/')) )
1238 {
1239 /* Number before and after the '/'. */
1240 int num[2];
1241 num[0] = rb->atoi(token);
1242 num[1] = rb->atoi(++toktok);
1243 /* Only accept positive numbers. */
1244 if(num[0] > 0 && num[1] > 0)
1245 {
1246 ps->beats_per_bar = (unsigned int) num[0];
1247 ps->base_beat = (unsigned int) num[1];
1248 return true;
1249 }
1250 }
1251 return false;
1252}
1253
1254/* Parse tempo, successful when getting a positive integer out of the token. */
1255static bool parse_tempo(char *token, struct part *ps)
1256{
1257 char *toktok;
1258 /* tempo[-tempo2/accel] ... first number always main tempo */
1259 int num = rb->atoi(token);
1260 /* Only positive numbers. This avoids the pattern string and general
1261 strangeness, unless -150 should mean "from previous tempo to 150". */
1262 if(num < 1) return false;
1263
1264 ps->bpm = (unsigned int) num;
1265 ps->bpm2 = ps->bpm;
1266 ps->accel = 0;
1267 /* This parser is not fool-proof. It parses valid data, but could
1268 do funny things if you provide tempo/tempo2-accel, for example.
1269 My credo is that the application doesn't crash, but if you give rubbish,
1270 you'll get rubbish. */
1271 if( (toktok = rb->strchr(token, '-')) )
1272 {
1273 char *subtok = toktok+1;
1274 float faccel = 0.;
1275 ps->bpm2 = positive(rb->atoi(subtok));
1276 /* Parse or compute accel in bpm/bar. */
1277 if( (toktok = rb->strchr(subtok, '/')) )
1278 { /* bars/bpm */
1279 float c = rb_atof(++toktok);
1280 if( (c > 0.f ? c : -c) > 0.0001f)
1281 faccel = 1./c;
1282 }
1283 else if( (toktok = rb->strchr(subtok, '*')) )
1284 { /* bpm/bar */
1285 faccel = rb_atof(++toktok);
1286 }
1287 else if(ps->bars > 0)
1288 { /* Compute from tempo difference and bar count. */
1289 faccel = ((float)ps->bpm2 - (float)ps->bpm)/ps->bars;
1290 }
1291 /* Correct sign for all cases, starting with positive value. */
1292 if(faccel < 0) faccel = -faccel;
1293 /* Negative only when end tempo is smaller. */
1294 if(ps->bpm2 < ps->bpm) faccel = -faccel;
1295 /* Convert (quarterbeats-per-minute per bar) -> 1/min, which could be
1296 seen as beats-per-minute/beat */
1297 faccel *= 1.f / (4.f/ps->base_beat * ps->beats_per_bar); /* 1/min */
1298 ps->accel = fp_frac(faccel);
1299 } else
1300 /* The other fancy variant: One tempo per beat. */
1301 if( (toktok = rb->strchr(token, ',')) )
1302 {
1303 size_t i;
1304 char *subtok = token;
1305 /* It is a bug when the parser called this before. Alloc once. */
1306 if( ps->beat_bpm || !(ps->beat_bpm =
1307 mem_allocate(sizeof(unsigned int)*ps->beats_per_bar*ps->bars)) )
1308 return false;
1309 for(i=0; i<ps->beats_per_bar*ps->bars; ++i)
1310 {
1311 int num;
1312 if(!subtok) return false;
1313 if(subtok != token) ++subtok;
1314
1315 num = rb->atoi(subtok);
1316 if(num < 1) return false;
1317
1318 ps->beat_bpm[i] = (unsigned int) num;
1319 subtok = rb->strchr(subtok, ',');
1320 }
1321 }
1322 return true;
1323}
1324
1325/* The metronome pattern.
1326 Ensure that the correct meter is present before calling this! */
1327static bool parse_pattern(char *token, struct part *ps)
1328{
1329 size_t pi;
1330 size_t pats = rb->strlen(token);
1331
1332 /* First check if the pattern is valid, error out if not. */
1333 if(pats != ps->beats_per_bar)
1334 return false;
1335 for(pi=0; pi<pats; ++pi)
1336 switch(token[pi])
1337 {
1338 case 'X':
1339 case 'x':
1340 case '.':
1341 break;
1342 default: return false;
1343 }
1344
1345 if(!(ps->pattern || (ps->pattern = mem_allocate(pats))))
1346 return false;
1347 /* Now store it. */
1348 memcpy(ps->pattern, token, pats);
1349 return true;
1350}
1351
1352static bool parse_volume(char *token, struct part *ps)
1353{
1354 float factor = rb_atof(token);
1355 ps->volume = fp_rint(fp_decibels(fp_frac(factor > 0.f ? factor : 0.f), 16));
1356 return true;
1357}
1358
1359/* Check condition, set error code and bail out if violated. */
1360#define CHECK(a, c) if(!(a)){ errcode = c; goto parse_part_revert; }
1361
1362static void parse_part(char *line, unsigned int num)
1363{
1364 char *saveptr;
1365 char *toktok;
1366 char *token[5];
1367 struct part *ps;
1368 size_t tokens = 0;
1369 unsigned int errcode = MERR_NOTHING;
1370
1371 while (isspace(*line)) line++;
1372 /* Skip comments and empty lines quickly. */
1373 if(line[0] == '#' || line[0] == 0) return;
1374
1375 mem_checkpoint();
1376 CHECK(ps = mem_allocate(sizeof(struct part)), MERR_OOM);
1377 part_init(ps);
1378
1379 /* Check for and store label. */
1380 if( (toktok = rb->strchr(line, ':')) )
1381 {
1382 size_t len = toktok-line;
1383 CHECK(ps->label = mem_allocate(len+1), MERR_OOM);
1384 rb->memcpy(ps->label, line, len);
1385 ps->label[len] = 0;
1386 line = toktok+1;
1387 }
1388
1389 CHECK(token[0] = rb->strtok_r(line, " \t", &saveptr), MERR_MISSING);
1390 tokens = 1;
1391 /* After the optional label, there can be up to 5 tokens of interest.
1392 Collect them in advance to make the parser code more sane. */
1393 while( tokens < 5
1394 && (token[tokens] = rb->strtok_r(NULL, " \t", &saveptr)) )
1395 {
1396 if(token[tokens][0] == '#')
1397 break;
1398 ++tokens;
1399 }
1400
1401 CHECK(tokens >= 2, MERR_MISSING);
1402
1403 /* Now try to be smart about guessing which token can be what value.
1404 Remember: Always parse meter before pattern or tempo! */
1405 ps->bars = (unsigned int) rb->atoi(token[0]);
1406 if(tokens == 2) /* <bars> <tempo> */
1407 {
1408 CHECK(parse_tempo(token[1], ps), MERR_TEMPO);
1409 } else
1410 if(tokens == 3)
1411 {
1412 /* <bars> <meter> <tempo> */
1413 if(parse_meter(token[1], ps))
1414 {
1415 CHECK(parse_tempo(token[2], ps), MERR_TEMPO);
1416 } else
1417 /* <bars> <tempo> <pattern> */
1418 if(parse_pattern(token[2], ps))
1419 {
1420 CHECK(parse_tempo(token[1], ps), MERR_TEMPO);
1421 } else
1422 /* <bars> <tempo> <volume> */
1423 {
1424 CHECK(parse_tempo(token[1], ps), MERR_TEMPO);
1425 CHECK(parse_volume(token[2], ps), MERR_VOLUME);
1426 }
1427 } else
1428 if(tokens == 4)
1429 {
1430 /* <bars> <meter> <tempo> <pattern> */
1431 if(parse_meter(token[1], ps) && parse_pattern(token[3], ps))
1432 {
1433 CHECK(parse_tempo(token[2], ps), MERR_TEMPO);
1434 } else
1435 /* <bars> <tempo> <pattern> <volume> */
1436 if(parse_pattern(token[2], ps))
1437 {
1438 CHECK(parse_tempo(token[1], ps), MERR_TEMPO);
1439 CHECK(parse_volume(token[3], ps), MERR_VOLUME);
1440 } else
1441 /* <bars> <meter> <tempo> <volume> */
1442 {
1443 CHECK(parse_meter(token[1], ps), MERR_METER);
1444 CHECK(parse_tempo(token[2], ps), MERR_TEMPO);
1445 CHECK(parse_volume(token[3], ps), MERR_VOLUME);
1446 }
1447 } else
1448 if(tokens == 5) /* the complete set */
1449 {
1450 /* <bars> <meter> <tempo> <pattern> <volume> */
1451 CHECK(parse_meter(token[1], ps), MERR_METER);
1452 CHECK(parse_tempo(token[2], ps), MERR_TEMPO);
1453 CHECK(parse_pattern(token[3], ps), MERR_PATTERN);
1454 CHECK(parse_volume(token[4], ps), MERR_VOLUME);
1455 }
1456
1457 if(!ps->pattern)
1458 {
1459 /* For parsed parts default to emphasize every first beat. */
1460 CHECK(ps->pattern = mem_allocate(ps->beats_per_bar), MERR_OOM);
1461 memset(ps->pattern, 'x', ps->beats_per_bar);
1462 ps->pattern[0] = 'X';
1463 }
1464
1465 part_add(ps);
1466 return; /* all good */
1467
1468 /* Remove part after some error. */
1469parse_part_revert:
1470 rb->snprintf(buffer, sizeof(buffer), "ERR %u @line %u", errcode, num);
1471 rb->splash(2*HZ, buffer);
1472 ++bad_parts;
1473 mem_reset();
1474}
1475
1476#undef CHECK
1477
1478static void step_back(void)
1479{
1480 beating = false;
1481 beat = 0;
1482 if(bar)
1483 {
1484 /* Endless parts only know position 0 to step to. */
1485 if(part->bars) --bar;
1486 else bar = 0;
1487 }
1488 else if(part->prev)
1489 {
1490 part = part->prev;
1491 /* This will jump to bar 0 for endless parts. */
1492 bar = positive(part->bars)-1;
1493 tweak_volume(part->volume);
1494 }
1495 /* Always calculate period for acceleration. */
1496 calc_period();
1497 minitick = period;
1498}
1499
1500static void step_forw(void)
1501{
1502 beating = false;
1503 /* Stepping forward in endless part always goes to the next one, if any. */
1504 if(part->bars == 0 || bar+1 == part->bars)
1505 {
1506 if(part->next)
1507 { /* Advanced one part. */
1508 part = part->next;
1509 bar = 0;
1510 beat = 0;
1511 tweak_volume(part->volume);
1512 }
1513 }
1514 else ++bar;
1515 /* Always calculate period for acceleration. */
1516 calc_period();
1517 minitick = period;
1518}
1519
1520static void tap(void)
1521{
1522 struct part *ps = part;
1523
1524 /* Each tap resets the position. */
1525 beat = 0;
1526 bar = 0;
1527
1528 if(tap_count == 0 || tap_time < tap_count)
1529 tap_time = 0;
1530 else
1531 {
1532 if(tap_time > 0)
1533 {
1534 /* Could use fixed point math and rounding, even. */
1535 ps->bpm = 60*timerfreq_div*tap_count/tap_time;
1536
1537 if(ps->bpm > 400) ps->bpm = 400;
1538 }
1539 tap_timeout = (tap_count+2)*tap_time/tap_count;
1540 }
1541
1542 tap_count++;
1543 minitick = 0; /* sync tock to tapping */
1544 reset_tap = false;
1545 play_ticktock();
1546}
1547
1548enum plugin_status plugin_start(const void* file)
1549{
1550 int button;
1551 static int last_button = BUTTON_NONE;
1552 bool common_action;
1553
1554 atexit(cleanup);
1555
1556 mem_init();
1557
1558 if(MET_IS_PLAYING) MET_PLAY_STOP; /* stop audio IS */
1559
1560 prepare_buffers();
1561#if INPUT_SRC_CAPS != 0
1562 /* Select playback */
1563 rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
1564 rb->audio_set_output_source(AUDIO_SRC_PLAYBACK);
1565#endif
1566 rb->pcm_set_frequency(SAMPR_44);
1567
1568 if(file)
1569 {
1570 parts = 0;
1571 bad_parts = 0;
1572 fd = rb->open(file, O_RDONLY);
1573 if(fd >= 0)
1574 {
1575 unsigned int linenum = 0;
1576 /* Crazyness, allocating line buffer depending on free memory. */
1577 linebuf_size = mem_end - mem_free_region > 32*1024
1578 ? 1024
1579 : ( mem_end - mem_free_region > 16*1024
1580 ? 256
1581 : 128 );
1582 if(!(linebuf = mem_allocate(linebuf_size))) return PLUGIN_ERROR;
1583 /* I'm assuming that read_line always terminates. */
1584 while(rb->read_line(fd, linebuf, linebuf_size) > 0)
1585 {
1586 parse_part(linebuf, ++linenum);
1587 }
1588 }
1589 rb->close(fd);
1590 if(bad_parts)
1591 {
1592 rb->snprintf(buffer, sizeof(buffer), "%u bad parts", bad_parts);
1593 rb->splash(2*HZ, buffer);
1594 }
1595 if(!parts)
1596 {
1597 rb->splash(2*HZ, "Got no parts. Bye!");
1598 return PLUGIN_OK;
1599 }
1600 }
1601
1602 /* If no parts given, start in simple metronome mode. */
1603 if(!parts)
1604 { /* Just checking the early bailout here. */
1605 struct part *ps = mem_allocate(sizeof(struct part));
1606 if(!ps) return PLUGIN_ERROR;
1607 part_init(ps);
1608 part_add(ps);
1609 track_mode = false;
1610 }
1611 else track_mode = true;
1612
1613 part = part_list;
1614 tweak_volume(part->volume);
1615 calc_period();
1616 draw_display();
1617
1618 /* main loop */
1619 while(true)
1620 {
1621 reset_tap = true;
1622 button = pluginlib_getaction( TIMEOUT_NOBLOCK, plugin_contexts
1623 , PLA_ARRAY_COUNT );
1624 if(sound_trigger)
1625 {
1626 sound_trigger = false;
1627 play_ticktock(); /* Draws display before playback. */
1628 }
1629
1630 common_action = false;
1631 if(track_mode)
1632 {
1633 switch(button)
1634 {
1635 case METRONOME_START:
1636 if(sound_paused) metronome_unpause();
1637 else metronome_pause();
1638 break;
1639 case METRONOME_PAUSE:
1640 if(!sound_paused) metronome_pause();
1641 break;
1642 case METRONOME_LEFT:
1643 case METRONOME_LEFT_REP:
1644 step_back();
1645 trigger_display(0);
1646 break;
1647 case METRONOME_RIGHT:
1648 case METRONOME_RIGHT_REP:
1649 step_forw();
1650 trigger_display(0);
1651 break;
1652 default:
1653 common_action = true;
1654 }
1655 }
1656 else
1657 {
1658 switch(button)
1659 {
1660 case METRONOME_PAUSE:
1661 if(!sound_paused) metronome_pause();
1662 break;
1663 case METRONOME_PLAY:
1664 if(sound_paused) metronome_unpause();
1665 break;
1666 case METRONOME_TAP:
1667 if(last_button != METRONOME_PLAY)
1668 {
1669 if(sound_paused) metronome_unpause();
1670 tap();
1671 }
1672 break;
1673 case METRONOME_LEFT:
1674 bpm_step_counter = 0;
1675 /* fallthrough */
1676 case METRONOME_LEFT_REP:
1677 change_bpm(-1);
1678 break;
1679 case METRONOME_RIGHT:
1680 bpm_step_counter = 0;
1681 /* fallthrough */
1682 case METRONOME_RIGHT_REP:
1683 change_bpm(1);
1684 break;
1685#ifdef MET_SYNC
1686 case METRONOME_SYNC:
1687 minitick = period;
1688 break;
1689#endif
1690 default:
1691 common_action = true;
1692 }
1693 }
1694
1695 if(common_action)
1696 switch(button)
1697 {
1698 case METRONOME_QUIT:
1699 /* get out of here */
1700 return PLUGIN_OK;
1701 case METRONOME_VOL_UP:
1702 case METRONOME_VOL_UP_REP:
1703 change_volume(1);
1704 trigger_display(0);
1705 break;
1706 case METRONOME_VOL_DOWN:
1707 case METRONOME_VOL_DOWN_REP:
1708 change_volume(-1);
1709 trigger_display(0);
1710 break;
1711 default:
1712 exit_on_usb(button);
1713 reset_tap = false;
1714 break;
1715 }
1716
1717 if(button)
1718 last_button = button;
1719 if(reset_tap)
1720 tap_count = 0;
1721 /* If there was some action, display drawing is still needed.
1722 This _might_ disturb audio on slow machines, but
1723 then, you could just stop pressing buttons, then;-) */
1724 if(display_trigger)
1725 {
1726 display_trigger = false;
1727 draw_display();
1728 }
1729
1730 /* This determines the accuracy of the metronome with SWCODEC ... the
1731 scheduler decides when we are allowed to play. */
1732 rb->yield();
1733 }
1734}