File: manual.html

package info (click to toggle)
midish 0.2.5-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 760 kB
  • ctags: 1,294
  • sloc: ansic: 13,035; makefile: 119; sh: 114
file content (3075 lines) | stat: -rw-r--r-- 103,608 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!--
/*
 * Copyright (c) 2003-2005 Alexandre Ratchov
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 *
 *      - Redistributions of source code must retain the above
 *        copyright notice, this list of conditions and the
 *        following disclaimer.
 *
 *      - Redistributions in binary form must reproduce the above
 *        copyright notice, this list of conditions and the
 *        following disclaimer in the documentation and/or other
 *        materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
-->

<HTML>
<HEAD>
<TITLE>midish 0.2 - tutorial</TITLE>
<META http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</HEAD>
<BODY bgcolor="white" text="black" link="blue" vlink="navy">

<H1>Table of contents</H1>
<UL>
<LI><A href="#intro">Introduction</A>
<LI><A href="#dev">Devices setup</A>
<LI><A href="#chan">Channels</A>
<LI><A href="#filt">Filtering/routing</A>
<LI><A href="#time">Time structure</A>
<LI><A href="#track">Tracks</A>
<LI><A href="#sysex">System exclusive messages</A>
<LI><A href="#info">Obtaining information</A>
<LI><A href="#save">Saving and loading songs</A>
<LI><A href="#export">Import/export standard MIDI files</A>
<LI><A href="#interpreter">The interpreter's language</A>
<LI><A href="#changes">Changes</A>
<LI><A href="#attributes">Project attributes</A>
<LI><A href="#ev">Events and event ranges specification</A>
<LI><A href="#language">Language reference</A>
<LI><A href="#functs">Function reference</A>
<LI><A href="#midishrc">Sample midishrc-file</A>
<LI><A href="#example">Example sessions</A>
</UL>

<A name="intro"></A><H1>Introduction</H1>
<H2>What is midish?</H2>

        Midish is an open-source MIDI sequencer/filter for 
        Unix-like operating systems (tested on OpenBSD and Linux).
        Implemented as a simple command-line interpreter (like a shell)
        it's intended to be <I>lightweight</I>,
        <I>fast</I> and <I>reliable</I> for 
        real-time performance.
        <P>
        Important features:

        <UL>
        <LI>    multiple MIDI devices handling
        <LI>    synchronisation to external midi devices
        <LI>    real-time MIDI filtering/routing (controller mapping, keyboard splitting, ...)
        <LI>    track recording, metronome
        <LI>    basic track editing (insert, copy, delete, ...)
        <LI>    track quantisation
        <LI>    import and export of standard MIDI files
        <LI>    tempo and time-signature changes
        <LI>    system exclusive messages handling
        </UL>

        Midish is open-source software distributed under
        a 2-clause BSD-style license.

<A name="install"></A><H2>Installation</H2>

        Requirements:
        <UL>
        <LI>    a midi sound module 
        <LI>    a midi keyboard
        <LI>    a POSIX unix-like operating system with "raw" midi support.
                Midish works on OpenBSD (its development platform)
                and Linux.
        <LI>    the readline(3) library
        </UL>

        (without any midi-devices Midish will be probably useless).
        <P>
        To install midish:

        <OL>
        <LI> Untar and gunzip the tar-ball:

        <PRE>
        gunzip midish-0.2.tar.gz
        tar -xf midish-0.2.tar
        cd midish-0.2
	</PRE>

        <LI> 
       	Edit Makefile and change the readline(3) options in Makefile

        <LI> 
        Compile midish, just type '<TT>make all</TT>', this will build
        midish and rmidish, the readline(3) front-end to midish.

        <LI>
        Install binaries, documentation and examples by
        typing '<TT>make install</TT>'. They are copied as follows:
        <UL>
        <LI> binaries in '<TT>PREFIX/bin</TT>'
        <LI> manual pages in '<TT>PREFIX/man/man1</TT>'
        <LI> html documentation in '<TT>PREFIX/share/doc/midish</TT>'
        <LI> example files in '<TT>PREFIX/share/examples/midish</TT>'
        where '<TT>PREFIX</TT>' is by default '<TT>/usr/local</TT>'.
        To change this, set the '<TT>PREFIX</TT>' variable in
        '<TT>Makefile</TT>', for instance: 

        <PRE>
        make PREFIX=$HOME install
        </PRE>
        </UL>
        <LI>
        If there isn't a <TT>/etc/midishrc</TT> file, 
	then copy the sample file by
        typing '<TT>cp midishrc /etc</TT>' in your shell.
        <LI>
        Read the documentation and modify <TT>/etc/midishrc</TT> in order 
        to choose the default midi device by using the '<TT>devattach</TT>' 
        function (example: '<TT>devattach 0 "/dev/rmidi3"</TT>', see next section)
        </OL>


<H2>Invocation</H2>
        <P>
        Midish is a MIDI sequencer/filter driven by a command-line 
        interpreter (like a shell).
        
        Once midish started, the interpreter prompts
        for commands. 

        Then, it can be used to configure midi-devices, 
        create tracks, define channel/controller mappings,
        route events from one device to another, play/record a song etc.

        To start midish, just type:
        <PRE>
        rmidish
        </PRE>

        Then, commands are issued interactively on the midish prompt, 
        example:
        <PRE>
        print "hello world"
        </PRE>

        Midish has two modes: <I>prompt mode</I> and <I>performance mode</I>.

        <P>
        In prompt mode, midish interactively waits for commands
        from the command-line. 
        This mode is used to configure the sequencing engine:
        create and manage tracks, define filtering rules
        start/stop recording, etc...
        Midi devices aren't used, they are let closed in order to
        let other applications to use them.

        <P>
        In performance mode, midish processes midi input/output
        in real-time.
        Commands cannot be issued on the command-line.
        This mode is typically used for playback and record.
        To stop performance mode, hit control-C (or send an interrupt
        signal (SIGINT) to midish).     


<H2>How does it work</H2>
Midish uses the following objects to represent a project:

<UL>
<LI> <B>Midi devices:</B><BR>
        these are actual midi devices (keyboards, sound modules,
        external sequencers...) from which events are received and/or to which
        they are sent. 

<LI> <B>Filters:</B><BR>
        a filter is a set of rules that says which midi event to discard
        and how to transform incoming events. The filter also "sanitises" the
        input midi stream by removing nested notes, duplicate controllers and
        other anomalies. 

<LI><B>Channels:</B><BR>
        a channel is an a output {device&nbsp;midi-channel} pair that
        represent an instrument. A channel holds some properties like patch
        number, volume, reverb depth or other controllers. 

<LI><B>Tracks:</B><BR>
        tracks represent pieces of music: they hold midi voice events
        (notes, controllers ...). Tracks aren't bound to a particular
        channel and can contain events from any channel. 

<LI><B>Sysex banks:</B> <BR>
        a sysex bank is a set of system exclusive messages. They
        will be sent to midi devices when performance mode is entered. 

<LI><B>The "meta-track":</B><BR> 
        it is a particular hidden track that contains
        only special events like tempo changes and time signature changes. 

<LI><B>Song parameters</B>: <BR>
        these are miscellaneous parameters like the
        metronome configuration, the current selection... 
</UL>

The above objects are grouped in a ''project'' (a song) and manipulated
in prompt mode by issuing interactively commands.

<P>
Performance mode is used to play/record the project. When performance
mode is entered, midi devices are opened, and all sysex messages and
channel configuration events are sent to them. There are three
performance modes:

<UL>
<LI><B>"Idle" mode</B><BR>
        The midi input passes through the <I>current filter</I>
        and the result is sent to the midi output. No tracks are
        played or recorded.
        <PRE>                                   
        +---------+             +------------+          +----------+
        |         |             |            |          |          |
        | midi in |------------>|   filter   |--------->| midi out |
        |         |             |            |          |          |
        +---------+             +------------+          +----------+
        </PRE>

<LI><B>Play mode</B><BR>
        The midi input passes through the <I>current filter</I>
        the result is mixed with the currently played tracks
        and finally sent to the midi output. No tracks are recorded.
        <PRE>                                   
                                +--------------+            
                                | track_1 play |---\
                                +--------------+   |
                                                   |
                                     ...        ---+
                                                   |
                                +--------------+   |    
                                | track_N play |---+
                                +--------------+   |
                                                   |
        +---------+             +------------+     |    +----------+
        |         |             |            |     \--->|          |
        | midi in |------------>|   filter   |--------->| midi out |
        |         |             |            |          |          |
        +---------+             +------------+          +----------+
        </PRE>

<LI><B>Record mode</B><BR>
        The midi input passes through the <I>current filter</I>
        and is recorded to the <I>current track</I>. 
        The result is mixed with the currently played tracks
        and finally sent to the midi output. System exclusive
        messages are recorded to the <I>current sysex</I> without
        being passed through the filter.
        <PRE>                                   
                                +--------------+            
                                | track_1 play |---\
                                +--------------+   |
                                                   |
                                     ...        ---+
                                                   |
                                +--------------+   |    
                                | track_N play |---+
                                +--------------+   |
                                                   |
        +---------+             +------------+     |    +----------+
        |         |             |            |     \--->|          |
        | midi in |-----+------>|   filter   |----+---->| midi out |
        |         |     |       |            |    |     |          |
        +---------+     |       +------------+    |     +----------+
                        |                         |
                        |                         |     +----------------+
                        |       +--------------+  \---->| track_X record |
                        \------>| sysex record |        +----------------+
                                +--------------+
        </PRE>
</UL>
        
The above performance modes are started respectively with
<TT>songidle</TT>, <TT>songplay</TT>, <TT>songrecord</TT>. Performance
mode is blocking (no commands can be issued on the prompt). To return
again to prompt mode, send a interrupt signal (SIGINT) to midish (hit control-C on
the console).


<H2>An example</H2>

	Suppose that there are two devices:
		<UL>
		<LI><TT>/dev/rmidi4</TT> - a midi sound module
		<LI><TT>/dev/rmidi3</TT> - a midi keyboard
		</UL>
	Thus, the <TT>/etc/midishrc</TT> file contains the
	following lines:
	<PRE>
	devattach 0 "/dev/rmidi4"	# attach the module as dev number 0
	devattach 1 "/dev/rmidi3"	# attach the keyboard as dev number 1
	</PRE>
	
	The following session shows how to  record a simple track.
	First, we define a filter  named '<TT>piano</TT>' that
	routes events from device 1, channel 0 (input channel of
	the keyboard) to device 0, channel 5  (output channel of
	the sound module). Then we create a new track
	'<TT>pi1</TT>', we start recording and we save the song
	into a file.
	<PRE>
	1> filtnew piano			# create filter 'piano'
	2> filtchanmap piano {1 0} {0 5}	# dev=1,ch=0 -> dev=0,ch=5
	3> tracknew pi1				# create track 'pi1'
	4> songrecord				# start recording
	press control-C to finish

	--interrupt--

	5> songsave "mysong"			# save the song into a file
	6>					# EOF (control-D) to quit
	</PRE>
	
	<P>
	The same task can be achieved in a much easier way
	by using the simple procedures (or macros) defined in the 
	default <TT>/etc/midishrc</TT>.
	<PRE>
	1> ci {1 0}			# select default input {dev, chan}
	2> ni piano {0 5}		# create piano on dev=0, chan=5
	3> nt pi1 			# new track named "pi1"
	4> r				# start recording
	press control-C to finish

	--interrupt--

	5> save "mysong"		# save to file "mysong"
	6>				# EOF (control-D) to quit
	</PRE>
	
	<P>
	<B>Note:</B>
	It is strongly recommended to define simple procedures
	and to use them instead of directly using the built-in functions
	of midish. 
	
<A name="dev"></A><H1>Devices setup</H1>

        In midish, midi-devices are numbered from 0 to 15.
        Each midi-device has its "slot number". For instance, 
        suppose that there is a midi sound module known as
        <TT>/dev/rmidi3</TT> and a midi keyboard known as
        <TT>/dev/rmidi4</TT>.

        The following commands will configure the module as 
        device number 0 and
        the keyboard as device number 1:
        <PRE>
        devattach 0 "/dev/rmidi4"
        devattach 1 "/dev/rmidi3"
        </PRE>
        
        <P>
        <B>Note:</B>
        To make easier the import/export procedure from systems 
        with different configurations, it's strongly recommended to 
        attach the main sound module (the mostly used one)
        as device number 0.
        
        <P>
        In order to check that the sound module is properly configured
        play the demo song:
        <PRE>
        songload "sample.sng"
        songplay
        </PRE>
        
        (hit control-C to stop playback).
        When the configuration is setup, put the "devattach" 
        commands in the user's <TT>$HOME/.midishrc</TT>. It will be
        automatically executed the next time midish is run.
        

<A name="chan"></A><H1>Channels</H1>

        Because midish handles multiple devices, instead of
        using midi-channels, it uses device/midi-channel pairs
        to represent instruments.
        
        So <I>channel</I> refers the device/midi-channel pair.
        
        Channels are handled by two-item lists, like this:
        <PRE>
        {0 1}                   # device 0, midi-channel 1
        </PRE>
        Channels can also be named, as follows:
        <PRE>
        channew mybass {0 1}
        </PRE>
        this defines a named-channel <TT>mybass</TT> that can
        be used instead of the <TT>{0 1}</TT> pair.
        
<H2>Channel configuration</H2>

        A channel represents one musical instrument; 
        midish allows to attach to the channel definition 
        basic "configuration" events like program changes and
        controllers.

        Such events are sent to the output when performance mode is entered,
        for instance just before playback is started. This approach avoids
        flooding midi devices with "slow" events (like
        program changes).       
        
        <P>
        For instance;
        to select patch 34 on channel '<TT>mybass</TT>', attach
        a "program change" event:
        <PRE>
        chanconfev mybass { pc mybass 32 }
        </PRE>
        the list-argument gives the event to attach to the channel.
        See the <A href="#ev_ev">event</A> section for
        more details about events.

        <P>     
        To set the volume (controller 7) of this channel to 120:
        <PRE>
        chanconfev mybass { ctl mybass 7 120 }
        </PRE>
        If several events of the same type are attached
        then just the last one is kept. So, the following
        will change the volume to 125 by replacing the above event:
        <PRE>
        chanconfev mybass { ctl mybass 7 125 }
        </PRE>

	

<A name="filt"></A><H1>Filtering/routing</H1>

        <P> 
        Midish supports midi filtering: a <I>filter</I> 
        transforms incoming midi events and send them to the
        output. The filter also "sanitises" the input midi stream
        by removing nested notes, duplicate controllers and other
        anomalies.

        Filters are in general used to:
        <UL>
        <LI>
        route events from a device/channel to another
        <LI>
        map a controller to another
        <LI>
        split the keyboard
        <LI>
        drop unwanted events
        <LI>
        etc...
        </UL>


<H2>About filters</H2>
        <P>
        Multiple filters can be defined, however only the
        <I>current filter</I> will run in performance
        mode. 

        If no filters are defined or if there is no current filter 
        then, in performance mode, input is sent to the output as-is.

        The current filter processes input midi events in the
        following order:
        <OL>
        <LI>    First, input events are checked for inconsistencies: nested
                note-on, orphaned note-off and duplicate controller, bender
                and aftertouch events are removed. 
                Zero-length notes are lengthened to one "tic".
                The rate of controller, bender and aftertouch events is 
                normalised in order not to flood output devices.

        <LI>    The input event is checked against all <I>voice rules</I>
                and the resulting events (if any) are sent to the output of
                the filter (if the event matches more than one <I>voice
                rule</I> then it is duplicated if needed).
                
        <LI>    If the input didn't match any <I>voice rule</I> then it is
                checked against all <I>channel rules</I> and the resulting
                events (if any) are sent to the output of the filter.  (if
                the event matches more than one <I>channel rule</I> then it
                is duplicated if needed).
                
        <LI>    If the input event didn't match any <I>channel rule</I> then
                it is checked against all <I>device rules</I> and the
                resulting events (if any) are sent to the output of the
                filter (if several <I>device rules</I> match the input event
                then it is duplicated if needed).

        <LI>    Finally, if the input event didn't match any <I>device
                rule</I> then it is passed to the output of the filter
                as-is.
                 
        </OL>

        <P>
        The following diagram summarises the event path through the filter:
        <PRE>
                +------------+  
                |   voice    | match
        in ---->|            |-----------------------------------------> out
                |   rules    |
                +------------+
              doesn't |         +------------+
                match |         |  channel   | match
                      \-------->|            |-------------------------> out
                                |   rules    |
                                +------------+
                              doesn't |         +------------+
                                match |         |   device   | match
                                      \-------->|            |---------> out
                                                |   rules    |
                                                +------------+
                                              doesn't | 
                                                match | 
                                                      \----------------> out
        
        </PRE>
        
        <P>
        Filters are defined as follows:
        <PRE>
        filtnew myfilt                  # define filter 'myfilt'
        </PRE>
        initially the filter is empty and will send input to output
        as-is. 
        
        Once the filter is created, filtering rules can be added,
        modified and removed. 
        See 
        <A href="#func_filt">filtering functions</A> section
        for details.
        
        <P>
        Rules can be listed with <TT>filtinfo</TT>. 
        All filtering rules can be removed with <TT>filtreset</TT>.


<H2>Examples</H2>
                
<H3>Device redirections</H3>

        The following example defines a filter that routes events from
        device number 1 (the midi keyboard) to device number 0
        (the sound module).
        <PRE>
        filtnew mydevmap                # define filter 'mydevmap'
        filtdevmap mydevmap 1 0         # make it route device 1 -> device 0
        </PRE>
        To test the filter, start performance mode:
        <PRE>
        songidle
        </PRE>
        (hit control-C to stop performance mode).
        
<H3>Channel maps</H3>

        The following example defines a filter 
        that routes events from device 1, channel 0 
        (first channel of the keyboard) to device 0, channel 9 
        (default drum channel of the sound module).
        <PRE>
        filtnew mydrums                 # define filter 'mydrums'
        filtchanmap mydrums {1 0} {0 9} # route dev/chan {1 0} to {0 9}
        </PRE>
        The device/channel pair is in braces. The first <TT>{1 0}</TT>
        is the input device/channel and <TT>{0 9}</TT> is the output channel.
        To test the filter, start performance mode:
        <PRE>
        songidle
        </PRE>
        (hit control-C to stop performance mode). 
        Playing on channel 0 of the keyboard will make
        sound channel 9 of the sound-module.

<H3>Controller maps</H3>

        The following example add a new rule to the above filter
        that maps the modulation wheel (controller 1) of 
        the source channel (ie device 1, channel 0)
        to the expression controller (number 11) of
        the destination channel (device 0, channel 9).
        <PRE>
        filtctlmap mydrums {1 0} {0 9} 1 11
        </PRE>
        the first three arguments are the name of the filter, 
        the input and the output device/channel pair. The 4-th
        argument is the controller number on the input (1 = modulation)
        and the 5-th argument is the controller number 
        on the output (11 = expression).
        Rules of the filter can be listed as follows:
        <PRE>
        filtinfo mydrums
        </PRE>
        which will print:
        <PRE>
        {
                chanmap {1 0} {0 9}
                ctlmap {1 0} {0 9} 1 11 id
        }
        </PRE>

<H3>Transpose</H3>

        The following example transposes by 12 half-tones
        (one octave) notes on device 1, channel 0 (keyboard) and
        sends them on device 0 channel 2 (sound-module).
        <PRE>
        filtnew mypiano                 # define filter 'mypiano'
        filtchanmap mypiano {1 0} {0 2} # route dev/chan {1 0} to {0 9}
        filtkeymap  mypiano {1 0} {0 2} 0 127 12
        </PRE>
        both rules are necessary. Note events are handled by 
        the key-rule and other events (controllers) fall trough
        the channel-rule. Arguments 4 and 5 to <TT>filtkeymap</TT>
        give the note range that will be handled 
        (from 0 to 127, i.e. the whole keyboard)
        and the 6-th argument gives the number of half-tones 
        (12, one octave) to transpose.
        
<H3>Keyboard splits</H3>

        In the same way it is possible to create a keyboard-split with two
        key-rules and two channel-rules. 
        The following example splits the
        keyboard in two parts (left and right) on note 64 (note E3, the
        middle of the keyboard).
        Notes on the left part  will be routed to
        channel 3 of the sound module and notes on the right
        part will be routed to channel 2 of the sound module.
        <PRE>
        filtnew mysplit
        filtchanmap mysplit {1 0} {0 2}
        filtkeymap mysplit  {1 0} {0 2} 0  63  0
        filtchanmap mysplit {1 0} {0 3}
        filtkeymap mysplit  {1 0} {0 3} 64 127 0
        </PRE>
        <P>
        Defining filters seems quite tedious, however it's possible
        to define procedures that do the same in a very simpler way.
        See the <A href="#interpreter">interpreter language</A> 
        for more details.

        
<A name="time"></A><H1>Time structure</H1>

        <P>
        In midish, time is split in <I>measures</I>. Each measure
        is split in <I>beats</I> and each beat is split in 
        <I>tics</I>. The <I>tic</I> is the fundamental
        time unit in midish. Duration of tics is fixed
        by the <I>tempo</I>. By default midish uses:
                <UL>
                <LI>24 tics per beat
                <LI>4 beats per measure
                <LI>120 beats per minute
                </UL>
        From the musical point of view, a beat often corresponds to
        a quarter note, to an eight note etc... 
        By default 
        an unit note corresponds to 96 tics, thus by default
        one beat corresponds to one quarter note, i.e. 
        the time signature is 4/4.
        
        
<H2>Metronome</H2>

        In order to "hear" time, a metronome can be used. It is
        used only in play and record modes. It produces
        a click sound on every beat. To start the metronome:
        <PRE>
        metroswitch 1           # switch the metronome on
        songplay                # start playback
        </PRE>
        The metronome has two kind of click-sound:
        <UL>
        <LI> high-click: on the first beat of the measure
        <LI> low-click: on the other beats.
        </UL>
        The click-sound can be configured by giving a couple 
        of note-on events, as follows:
        <PRE>
        metroconf {non {0 9} 48 127} {non {0 9} 64 100}
        </PRE>
        this configures the high-click with note 48, velocity 127 on
        device 0, channel 9 and the low-click with note 64, velocity 100
        on device 0, channel 9.

<H2>Time signature changes</H2>

        Time signature changes are achieved by inserting or
        deleting measures. The following starts
        a song with time signature of 4/4 (at measure 0) and
        change the time signature to 6/8 at measure 2 during
        5 measures:
        <PRE>
        songtimeins 0 2 4 4     # 4/4 at measure 0 during 2 measures
        songtimeins 2 5 6 8     # 8/6 at measure 2 during 5 measures
        metroswitch 1           # switch the metronome on
        songplay                # test it
        </PRE>
        To suppress measure number 2 (the first 6/8 measure)
        <PRE>
        songtimerm  2 1         # remove 1 measure starting a measure 2
        metroswitch 1           # switch the metronome on
        songplay                # test it
        </PRE>
        
<H2>Tempo changes</H2>
        
        Tempo changes are achieved simply by giving the measure
        number and the tempo value in beats per minute. For
        instance, the following changes tempo on measure 0
        to 100 beats per minute and on measure 2 to 180 beats 
        per minute.
        <PRE>
        songsettempo 0 100
        songsettempo 2 180
        </PRE>


<H2>Moving within the song</H2>

        The following selects the current position in the song to
        measure number 3:
        <PRE>
        songsetcurpos 3
        </PRE>
        This will make <TT>songrecord</TT> and <TT>songplay</TT>
        start at this particular position instead of measure
        number 0.
        
<A name="track"></A><H1>Tracks</H1>
        
        <P>
        A track is a piece of music, namely an ordered in time list 
        of midi events. In play mode, midish play simultaneously
        all defined tracks, in record-mode it plays all defined tracks
        and records the current track.
        
        <P>
        Tracks aren't assigned to any particular device/channel; a track
        can contain midi data from any device/channel. A track can have its 
        <I>current filter</I>; in this case, midi events
        are passed through that filter before being recorded. If the
        track has no current filter, then the song current
        filter is used instead. If there is neither track current
        filter nor song current filter, then midi events
        from all devices are recorded as-is.

<H2>Recording a track without a filter</H2>

        <P>
        The following defines a track and record events
        as-is from all midi devices:
        <PRE>
        tracknew mytrack
        songrecord
        </PRE>
        tracks are played as follows:
        <PRE>
        songplay
        </PRE>
        However, with the above configuration this will not
        work as expected because events from the input
        keyboard (device number 1) will be recorded as-is and then 
        sent back to the device number 1 instead of being sent
        to the sound module (device number 0).
        
<H2>Recording a track with a filter</H2>

        The following creates a filter and uses it to
        record to the above track:
        <PRE>
        filtnew mypiano
        filtchanmap mypiano {1 0} {0 0}         # dev1/chan0 -> dev0/chan0
        tracknew mytrack
        songrecord
        </PRE>
       	
<H2>Basic editing of a track</H2>

        <P>
        Most track editing functions in midish take at least the
        following arguments:
        <UL>
        <LI> start measure
        <LI> number of measures
        <LI> precision/quantum (in tics).
        </UL>
        For instance to blank measure number 3 of
        track <TT>mypiano</TT>:
        <PRE>
        trackblank mypiano 3 1 (96 / 16) {}
        </PRE>
        the 3-rd argument set the precision to sixteenth note
        (assuming 96 tics per unit note). This
        means that notes position is rounded to the nearest 16-th note
        before being removed.
        This is useful, because often recorded notes
        doesn't start exactly on the measure boundary. The precision
        argument makes possible to edit a track that is not quantised.
        The latest argument (empty list) selects the events to be 
        deleted (see section <A href="#ev_evspec">event ranges</A>).

        <P>
        In a similar way, one can cut a piece of a track, 
        for instance to cut 2 measures starting
        at measure number 5:
        <PRE>
        trackcut mypiano 5 2 (96 / 16)
        </PRE>
        
        <P>
        The following inserts 2 blank measures at
        measure number 3:
        <PRE>
        trackinsert mypiano 3 2 (96 / 16)
        </PRE>
        
        <P>
        A track portion can be copied into
        another track as follows:
        <PRE>
        trackcopy mypiano 3 2 mypiano2 5 (96 / 16) {}
        </PRE>
        this will copy 2 measures starting from measure
        number 3 into (the already existing) track <TT>mypiano2</TT>
        at measure 5.
        The latest argument (empty list) selects the events to be 
        copied (see section <A href="#ev_evspec">event ranges</A>).
        

<H2>Track quantisation</H2>

        A track can be quantised by rounding note-positions
        to the nearest exact position. The following
        will quantise 4 measures starting at measure number
        3 by rounding notes to the nearest quarter note.
        <PRE>
        trackquant mypiano 3 4 (96 / 4) 75
        </PRE>
        The last arguments gives the percent of quantisation.
        100% means full quantisation and 0% leans no
        quantisation at all. This is useful because full quantisation
        often sound to regular especially on acoustic patches.
        

<H2>Checking a track</H2>

        It is possible that a midi device transmits 
        bogus midi data. The following scans the track 
        and removes bogus notes
        and unused controller events:
        <PRE>
        trackcheck mytrack
        </PRE>
        This function can be useful to remove 
        nested notes when a track is recorded twice (or more) 
        without being erased.

<A name="sysex"></A><H1>System exclusive messages</H1>

        Midish can send system exclusive messages
        to midi devices before starting performance mode.
        Typically, this feature can be used to change 
        the configuration of the midi devices. System
        exclusive ('sysex') messages are stored into 
        named banks. To create a sysex bank named <TT>mybank</TT>:
        <PRE>
        sysexnew mybank
        </PRE>
        Then, messages can be added:
        <PRE>
        sysexadd mybank 0 {0xF0 0x7E 0x7F 0x09 0x01 0xF7}
        </PRE>  
        This will store the "General-Midi ON" messages into the
        bank. The second argument (here "0") is the device number
        to which the message will be sent when performance mode
        is entered. To send the latter messages to 
        the corresponding device, just enter performance mode,
        for instance:
        <PRE>
        songidle
        </PRE>
        Sysex messages can be recorded from
        midi devices, this is useful to save "bulk dumps"
        from synthesisers. Sysex messages are automatically
        recorded on the <I>current bank</I>. So, to record
        a sysex:
        <PRE>
        songsetcursysex mybank
        songrecord
        </PRE>
        The next time performance mode is entered, recorded
        sysex messages will be sent back to the device.
        Information about the recorded sysex messages 
        can be obtained as follows:
        <PRE>
        sysexinfo mybank
        </PRE>
        A bank can be cleared by:
        <PRE>
        sysexclear mybank {}
        </PRE>
        the second argument is a (empty) pattern, that matches
        any sysex message in the bank. The following will remove
        only sysex messages starting with 0xF0 0x7E 0x7F:
        <PRE>
        sysexclear mybank {0xF0 0x7E 0x7F}
        </PRE>
        Sysex messages recorded from any device can be configured
        to be sent to other devices. To change the device number
        of all messages to 1:
        <PRE>
        sysexsetunit mybank 1 {}
        </PRE>
        the second argument is an empty pattern, thus it matches
        any sysex message in the bank. The following will change 
        the device number of only sysex messages starting 
        with 0xF0 0x7E 0x7F:
        <PRE>
        sysexsetunit mybank 1 {0xF0 0x7E 0x7F}
        </PRE>
        
<A name="info"></A><H1>Obtaining information</H1>

        <P>
        The following functions gives some information
        about midish objects:
        <PRE>
        songinfo                        # summary
        songtimeinfo                    # tempo changes
        chaninfo mydrums                # list config. events in 'mydrums'
        filtinfo myfilt                 # list rules in 'myfilt'
        trackinfo mytrack (96 / 16) {}  # list number of events per measure
        devinfo 0                       # device properties
        </PRE>
        
        <P>
        Objects can be listed as follows:
        <PRE>
        print [tracklist]
        print [chanlist]
        print [filtlist]
        print [devlist]
        </PRE>

        <P>
        Current values can be obtained as follows:
        <PRE>
        print [songgetunit]             # tics per unit note
        print [songgetcurpos]           # print current position
        print [songgetcurlen]        # print current selection length
        print [songgetcurfilt]          # current filter
        print [songgetcurtrack]         # current track
        print [songgetcursysex]
        print [trackgetcurfilt mypiano] # current filter of track 'mypiano'
        print [filtgetcurchan mysplit]  # current channel of filter 'mysplit'
        </PRE>

        <P>
        The device and the midi channel of a channel definition
        can be obtained as follows:
        <PRE>
        print [changetch mydrums]       # print midi chan number
        print [changetdev mydrums]      # print device number
        </PRE>
        
        <P>
        To check if object exists:
        <PRE>
        print [chanexists]
        print [filtexists]
        print [trackexists]
        print [sysexexists]
        </PRE>
        this will print 1 if the corresponding object exists
        and 0 otherwise.
        

<A name="save"></A><H1>Saving and loading songs</H1>

        <P>
        A song can be saved into a file. All channel definitions, 
        filters, tracks, their properties, 
        and values of the current track, current 
        filter will be saved by:
        <PRE>
        songsave "myfile"
        </PRE>
        In a similar way, the song can be load from a file 
        as follows:
        <PRE>
        songload "myfile"
        </PRE>
        
        <P>
        Note that the "local settings" (like device configuration,
        metronome settings) are not saved. 
        
<A name="export"></A><H1>Import/export standard MIDI files</H1>

        <P>
        Standard MIDI files type 0 or 1 can be imported. Each
        track in the standard midi file corresponds to a track in midish.
        Tracks are named <TT>trk00</TT>, <TT>trk01</TT>, ... 
        All midi events are assigned to device number 0. Only the following
        meta events are handled:
                <UL>
                <LI> tempo changes
                <LI> time signature changes
                </UL>
        all meta-events are removed from the "voice" tracks and
        are moved into the midish's meta-track. Finally tracks
        are checked for anomalies. Example:
        <PRE>
        songimportsmf "mysong.mid"
        </PRE>
        
        <P>
        Midish songs can be exported into standard midi files.
        Tempo changes and time signature changes are exported
        to a meta-track (first track of the midi file). Each
        channel definition is exported as a track containing
        the channel configuration events. Voice tracks
        are exported as is in separate tracks. Note that device 
        numbers of midi events are not stored in the midi file
        because the file format does not allow this.    
        Example:
        <PRE>
        songexportsmf "mysong.mid"
        </PRE>

<A name="interpreter"></A><H1>The interpreter's language</H1>

        <P> 
        
        Even to achieve some simple tasks with midish, it's
        sometimes necessary to write several long statements.  To
        make midish more usable, it suggested to use variables
        and/or to define procedures, as follows.

<H2>Global variables</H2>

        <P>
        Variables can be used to store numbers, strings and
        references to tracks, channels and filters, like:
        
        <PRE>
        let x = 53              # store 53 into 'x'
        print $x                # prints '53'
        </PRE>
        
        The <TT>let</TT> keyword is used to assign values to 
        variables and the dollar sign ("<TT>$</TT>") is used
        to obtain variable values.

<H2>Defining simple procedures</H2>

        <P>
        For instance, let
        us create a procedure named "<TT>i</TT>" that just replaces
        <TT>songidle</TT> in order to avoid typing its name.
        <PRE>
        proc i { songidle; }
        </PRE>
        The <TT>proc</TT> keyword is followed by the procedure
        name and then follows a list of statements between
        braces. In a similar way can define the following
        procedures:
        <PRE>
        proc p {
                metroswitch 0           # turn off metronome
                songplay                # start playback
        }
        
        proc r {
                metroswitch 1           # turn on metronome
                songrecord              # start recording
        }
        </PRE>
        
        <P>
        Procedures can take arguments. 
        For instance, to define a procedure named <TT>nt</TT> 
        that creates a new track:
        <PRE>
	proc nt name {
		tracknew $name
	}
        </PRE>
        After the name of the procedure follows the argument names list
        that can be arbitrary identifiers. The value of an argument
        is obtained by preceding the variable name by the dollar
        sign ("$"). We can use the above procedure to create a track:
        <PRE>
        nt myfilt
        </PRE>
        
        A lot of similar procedures are defined in the
        sample <TT>midishrc</TT> file, shipped in the source
        tar-ball. To make midish easy to use, most of
        the usual tasks can be performed with only 2 or
        three character statements.
        
        <P>
        Procedure and variables definitions can be
        stored in the <TT>~/.midishrc</TT> file (or <TT>/etc/midishrc</TT>). 
	It will be automatically executed the next time you run midish.
                

<A name="changes"></A><H1>Changes</H1>
<A name="changes_02"></A><H2>Changes from release 0.1 to release 0.2</H2>

        <UL>
        <LI> added '<TT>device</TT>' parameter to '<TT>sendraw</TT>'
        <LI> removed '<TT>filtchangein</TT>' and added
		<TT>filtchgich</TT>, <TT>filtchgidev</TT>,
		<TT>filtswapich</TT>, <TT>filtswapidev</TT>,
		<TT>filtchgoch</TT>, <TT>filtchgodev</TT>,
		<TT>filtswapoch</TT>, <TT>filtswapodev</TT>.		
        <LI> added new filter rules: 
                <TT>filtdevdrop</TT>, 
                <TT>filtchandrop</TT>,
                <TT>filtctldrop</TT> and 
                <TT>filtkeydrop</TT>.
        <LI> added functions that remove existing rules: 
                <TT>filtnodevdrop</TT>, 
                <TT>filtnodevmap</TT>, 
                <TT>filtnochandrop</TT>,
                <TT>filtnochanmap</TT>,
                <TT>filtnoctldrop</TT>,
                <TT>filtnoctlmap</TT>,
                <TT>filtnokeydrop</TT> and
                <TT>filtnokeymap</TT>.
        <LI> added support for external midi synchronisation,
             added <TT>devsetmaster</TT>, <TT>devgetmaster</TT>
             and <TT>devsendrt</TT>
        <LI> added 
                <TT>trackdelete</TT>,
                <TT>chandelete</TT>, 
                <TT>filtdelete</TT>
        <LI> added 
                <TT>trackrename</TT>,
                <TT>chanrename</TT>, 
                <TT>filtrename</TT>
        <LI> split <TT>changetnum</TT> into <TT>changetdev</TT> and <TT>changetch</TT>,
	     added <TT>chanset</TT>
        <LI> added "event ranges", and an event range argument to 
                <TT>trackblank</TT> and
                <TT>trackcopy</TT>
        <LI> removed support for single number channels.
        <LI> added <TT>tracksetmute</TT> and <TT>trackgetmute</TT>
        <LI> added support for system exclusive messages; added
                <TT>sysexlist</TT>,
                <TT>sysexnew</TT>,
                <TT>sysexdelete</TT>,
                <TT>sysexrename</TT>,
                <TT>sysexexists</TT>,
                <TT>sysexinfo</TT>, 
                <TT>sysexclear</TT>, 
                <TT>sysexsetunit</TT>, 
                <TT>sysexadd</TT>, 
                <TT>songgetcursysex</TT> and
                <TT>songsetcursysex</TT>.
        <LI> removed <TT>tracksave</TT> and <TT>trackload</TT>
        <LI> removed support for gnu readline(3) library from midish, 
                and created the <TT>rmidish</TT> utility, a front-end
                to midish using the readline(3) library.        
        <LI> added filters the ability to limit midi traffic
                (one controller, one bender, one aftertouch per tic)
        <LI> make the filter drop duplicate controllers, pitch bends and
                aftertouches
        <LI> added global and per filter current channel: 
                <TT>songgetcurchan</TT>,
                <TT>songsetcurchan</TT>,
                <TT>filtgetcurchan</TT> and
                <TT>filtsetcurchan</TT>.
	<LI> added global and per channel current input:
                <TT>songgetcurinput</TT>,
                <TT>songsetcurinput</TT>,
                <TT>changetcurinput</TT> and
                <TT>chansetcurinput</TT>.
        <LI> added <TT>trackchanlist</TT> and improved <TT>songinfo</TT>        
	<LI> added a midi file player and recorder: smfplay(1) and smfrec(1)
        </UL>

<A name="attributes"></A><H1>Project attributes</H1>

<H2>Device attributes</H2>

	The following table summarises the device attributes:
	
	<P align="center">
	<TABLE border="1">
	<TR>
	<TH>attrubute
	<TH>description
	<TR>
	<TD>unit number
	<TD>integer that is used to reference the device
	<TR>
	<TD>ticrate
	<TD>number of tic per unit note, default is 96, which corresponds
		to the midi standard
	<TR>
	<TD>sendrt flag
	<TD>boolean; if sendrt = true, the real-time events
		(like start, stop, tics) are transmitted to the midi device.
	</TABLE>


<H2>Channel attributes</H2>

	The following table summarises the channel attributes:
	
	<P align="center">
	<TABLE border="1">
	<TR>
	<TH>attrubute
	<TH>description
	<TR>
	<TD>name
	<TD>identifier used to reference the channel
	<TR>
	<TD>{dev&nbsp;chan}
	<TD>device and midi channel to which midi events are sent
	<TR>
	<TD>conf
	<TD>events that are sent when performance mode is entered
	<TR>
	<TD>curinput
	<TD>default input {dev&nbsp;chan} pair. This value isn't used in
		real-time, however it can be used as default
		value when adding new rules to a filter
		that uses this channel.
	</TABLE>

<H2>Filter attributes</H2>

	The following table summarises the filter attributes:
	
	<P align="center">
	<TABLE border="1">
	<TR>
	<TH>attrubute
	<TH>description
	<TR>
	<TD>name
	<TD>identifier used to reference the fitler
	<TR>
	<TD>rules set
	<TD>set of rules that handle midi events
	<TR>
	<TD>current channel
	<TD>default channel. This value isn't used in real-time, 
		however it can be used as default value when
		adding new rules to the filter.
	</TABLE>


<H2>Track attributes</H2>

	The following table summarises the track attributes:
	
	<P align="center">
	<TABLE border="1">
	<TR>
	<TH>attrubute
	<TH>description
	<TR>
	<TD>name
	<TD>identifier used to reference the track
	<TR>
	<TD>mute flag
	<TD>if the mute = true, the the track is not played on playback
	<TR>
	<TD>current filter
	<TD>default filter. The track is recorded
		with this filter. If there is no current filter, 
		then is is recorded with the song's default fitler.
	</TABLE>


<H2>Sysex attributes</H2>

	The following table summarises the sysex back attributes:
	
	<P align="center">
	<TABLE border="1">
	<TR>
	<TH>attrubute
	<TH>description
	<TR>
	<TD>name
	<TD>identifier used to reference the sysex back
	<TR>
	<TD>list of messages
	<TD>each message in the list contains
		the actual message and the unit number of the device
		to which the message has to be sent.
	</TABLE>

<H2>Song attributes</H2>

	The following table summarises the song attributes:
	
	<P align="center">
	<TABLE border="1">
	<TR>
	<TH>attrubute
	<TH>description
	<TR>
	<TD>meta track
	<TD>a track containing tempo changes and time signature changes
	<TR>
	<TD>tics_per_unit
	<TD>number of midi tics per unit note, the default value is 96
		 which corresponds to the midi standard.
	<TR>
	<TD>metronome flag
	<TD>if the metronome = true, then the metronome is audible
	<TR>
	<TD>metro_hi
	<TD>a note-on event that is sent on the begining of every measure
		if the metronome is enabled
	<TR>
	<TD>metro_lo
	<TD>a note-on event that is sent on the begining of every beat
		if the metronome is enabled
	<TR>
	<TD>curtrack
	<TD>default track: the track that will be recorded in record mode
	<TR>
	<TD>curfilt
	<TD>default filter. The filter with which the 
		default trach is recorded if it hasn't its 
		default filter.
	<TR>
	<TD>curchan
	<TD>default channel. This value isn't used in real-time, 
		however it can be used as default value when
		adding new rules to the filter.
	<TR>
	<TD>curpos
	<TD>current position (in measures) within the song. Playback
		and record start from this positions. It is also
		user as the beginning of the current selection
	<TR>
	<TD>curlen
	<TD>length (in measures) of the current selection. 
		This value isn't used in real-time, 
		however it can be used as default value in track
		editing functions.
	<TR>
	<TD>curquant
	<TD>current quatisation step in tics. 
		This value isn't used in real-time, 
		however it can be used as default value for
		the track editing functions
	<TR>
	<TD>curinput
	<TD>default input {dev&nbsp;chan} pair. This value isn't used in
		real-time, however it can be uses as default
		value when adding new values to a filter
		that uses this channel.
	</TABLE>

<A name="ev"></A><H1>Events and event ranges specification</H1>
<A name="ev_ev"></A><H2>Event specification</H2>
        <P>
        Some functions take events as arguments. An event
        is specified as a list containing:
        <UL>
        <LI> a reference from the following list:
             <TT>noff</TT>, <TT>non</TT>, <TT>kat</TT>, 
             <TT>ctl</TT>, <TT>pc</TT>, <TT>cat</TT>, <TT>bend</TT>.
        <LI> a channel
        <LI> a number 
        <LI> a second number (not for <TT>pc</TT> and <TT>cat</TT>)
        </UL>
                
        Event references correspond to the following
        midi events:
        <P align="center">
        <TABLE border="1">
        <TR>    <TD><TT>noff</TT>       <TD>note off
        <TR>    <TD><TT>non</TT>        <TD>note off
        <TR>    <TD><TT>kat</TT>        <TD>key after-touch (poly)
        <TR>    <TD><TT>ctl</TT>        <TD>controller
        <TR>    <TD><TT>pc</TT>         <TD>program change
        <TR>    <TD><TT>cat</TT>        <TD>channel after-touch (mono)
        <TR>    <TD><TT>bend</TT>       <TD>pitch bend
        </TABLE>

        <P align="left">
        Examples:
        <BR>
        note-on event on device 2, channel 9, note 64 with velocity 100:

        <PRE>
        { non {2 9} 64 100 }
        </PRE>

        program change device 1, channel 3, patch 34

        <PRE>
        { pc {1 3} 34 }
        </PRE>

        set controller number 7 to 99
        on device/channel drums:

        <PRE>
        { ctl drums 7 99 }
        </PRE>

<A name="ev_evspec"></A><H2>Event ranges specification</H2>

        Some track editing functions take an event range as argument. 
        The event range is specified as a list containing:
        <UL>
        <LI> an optional reference from the following list:
             <TT>any</TT>, <TT>note</TT>, <TT>ctl</TT>, <TT>pc</TT>, <TT>cat</TT>, <TT>bend</TT>.
        <LI> an optional channel range specified as a list containing
                a device number range and a midi-channel number
                range. Number ranges are specified as two-number list
                like this <TT>{12 34}</TT>. Channel name matches an unique channel.
        <LI> an optional  number range, specified as a list
                of two number like this <TT>{12 65}</TT>
        <LI> an optional second number range, in the same
                format as the first one (not permitted for <TT>pc</TT>, 
                <TT>bend</TT> and <TT>cat</TT>)
        </UL>
        In the above, empty lists can also be used. An empty list
        means "match everything".
        
        <P>
        Examples:
        <BR>
        <PRE>
        {}                      # match everything
        { any }                 # match everything
        { any bass }            # match anything on channel 'bass'
        { any {1 4} }           # match anything on device 1, channel 4
        { any {1 {}} }          # match anything on device 1, any channel
        { any {{} 9} }          # match anything on any device and channel 9
        { note }                # match note events
        { note {1 9} }          # match notes on dev 1, channel 9
        { note {0 {}} }         # match notes on device 0
        { note {0 {3 5}} }      # match notes on device 0, channel 3, 4, 5
        { note {} {0 64} }      # match notes between 0 an 64
        { note {} 60 {80 127} } # match note 60 with velocity between 80 an 127
        { ctl bass }            # match controllers on channel 'bass'
        { ctl bass 7 }          # match controller 7 on channel 'bass'
        { ctl bass 7 {0 64} }   # match ctl 7 on chan 'bass' with value 0->64
        { bend {} {0 0x1fff} }  # match "lower" bender
        </PRE>  


<A name="language"></A><H1>Language reference</H1>
<H2>Lexical structure</H2>

        The input line is split into tokens:

        <UL>
        <LI> Identifiers:
                <BR>
                an identifier is a sequence of up to 32
                characters, digits and underscores ('<TT>_</TT>').
                However, an identifier cannot start with a
                digit. Examples:
        <PRE>
        mytrack _mytrack  my34_track23          # good
        123mytrack                              # bad, starts with digit
        mytrackabcdefghijklmnopqrstuvwxyz       # bad, to long
        </PRE>
        
        <LI> Numbers 
                <BR>
                numbers should be in decimal or hex format and may
                not exceed 2^31. Hex numbers are preceded
                by "0x", as in the C language. Examples:
                
                <P align="center">
                <TABLE border="1">
                <TR>    <TD><TT>123</TT>        <TD>123 in decimal
                <TR>    <TD><TT>0x100</TT>      <TD>256 in hex
                <TR>    <TD><TT>0xF0</TT>       <TD>240 in hex
                </TABLE>
                        
        <LI> String constants
                <BR>
                string constants are sequence of printable
                characters enclosed in pairs of double quotes.
                Thus a string cannot contain double quotes, 
                tabs, newlines.

        <LI> Keywords
                <BR>
                valid keywords are: <TT>nil</TT>, <TT>let</TT>, 
                <TT>if</TT>, <TT>else</TT>, <TT>for</TT>, and <TT>proc</TT>.

        <LI> Operators, separators etc...
                <BR>
                sequences of meta-characters like '<TT>(</TT>', '<TT>)</TT>', 
                '<TT>+</TT>', '<TT>$</TT>', newline character, 
                '<TT>;</TT>',  etc... 

        <LI> Comments 
                <BR>
                comments are ignored, they start with '<TT>#</TT>' 
                and end with the new line
                character.

        </UL>

        Multiple lines ending with '<TT>\</TT>' are parsed as a 
        single line. Anything else generates a "bad token" error.


<H2>Statements</H2>

        <P>
        Any input line can be ether a function definition or a
        statement. 

        Most statements end with the '<TT>;</TT>'
        character.  However, in order to improve
        interactivity, the newline character can be used
        instead. Thus, the newline character cannot be
        used as a space.

        A statement can be:

        <UL>
        <LI>
        A procedure call, example:

        <PRE>
        myproc arg1 arg2
        </PRE>


        <LI>
        An assignment using the <TT>let</TT> keyword,
        examples:

        <PRE>
        let x = 123
        let y = 1 + 2 * (3 + x)
        </PRE>

        <P>
        The left-hand side should be the name of
        a variable and the right hand side an
        expression (see the expression section).


        <LI>
        An <TT>if..else</TT> statement, example:

        <PRE>
        if $i {
                print "i is not zero";
        } else {
                print "i is zero";
        }
        </PRE>

        the <TT>else</TT> and the second block are
        not mandatory. Note that since newline
        character is interpreted as a '<TT>;</TT>', the
        line cannot be broken in an arbitrary
        way. If the expression following the <TT>if</TT>
        keyword is true the first block is executed,
        otherwise the second one (if any) is executed. The
        expression is evaluated in the following way:

        <P align="center">
        <TABLE border="1">
        <TR>    <TD>non-zero integer    <TD>true
        <TR>    <TD>zero integer        <TD>false
        <TR>    <TD>non-empty list      <TD>true
        <TR>    <TD>empty list          <TD>false
        <TR>    <TD>any name            <TD>true
        <TR>    <TD>nil                 <td>false
        </TABLE>
        
        <LI>
        A loop over a list:

        <PRE>
        for i in { "bli" "bla" "blu" } {
                print $i;
        }
        </PRE>

        the block is executed for each value
        of the list to which '<TT>$i</TT>' is set.

        <LI>
        A return statement. The return statement ends
        the procedure execution and returns a
        value to the caller. Example:

        <PRE>
        return $x * $x;
        </PRE>

        </UL>


<H2>Expressions</H2>

        An expression can be an arithmetic expression of constants,
        expressions, variable values, return values of
        function calls. 

        The following constant types are supported:

        <P align="center">
        <TABLE border="1">
        <TR>    <TD><TT>"this is a string"</TT>         <TD> a string
        <TR>    <TD><TT>12345</TT>                      <TD> a number
        <TR>    <TD><TT>mytrack</TT>                    <TD> a reference
        <TR>    <TD><TT>nil</TT>                        <TD> has no value
        </TABLE>

        <P>
        Variable are referenced by their identifier. 
        Value of a variable is obtained with the '<TT>$</TT>'
        character.

        <PRE>
        let i = 123             # puts 123 in 'i'
        print $i                # prints the value of 'i'
        </PRE>

        The following operators are recognised:

        <P align="center">
        <TABLE border="1">

        <TR>    <TH>oper.       <TH>usage               <TH>associativity

        <TR>    <TD><TT>{}</TT> 
                <TD>list definition     
                <TD rowspan="3">left to right

        <TR>    <TD><TT>()</TT> 
                <TD>grouping            

        <TR>    <TD><TT>[]</TT> 
                <TD>function call

        <TR>    <TD><TT>!</TT>  
                <TD>logical NOT         
                <TD rowspan="3">right to left

        <TR>    <TD><TT>~</TT>  
                <TD>bitwise NOT         

        <TR>    <TD><TT>-</TT>
                <TD>unary minus

        <TR>    <TD><TT>*</TT>
                <TD>multiplication
                <TD rowspan="3">left to right

        <TR>    <TD><TT>/</TT>
                <TD>division

        <TR>    <TD><TT>%</TT>
                <TD>reminder

        <TR>    <TD><TT>+</TT>
                <TD>addition
                <TD rowspan="2">left to right

        <TR>    <TD><TT>-</TT>
                <TD>subtraction

        <TR>    <TD><TT>&lt;&lt;</TT>
                <TD>left shift  
                <TD rowspan="2">left to right

        <TR>    <TD><TT>&gt;&gt;</TT>
                <TD>right shift
        
        <TR>    <TD><TT>&lt;</TT>
                <TD>less
                <TD rowspan="4">left to right

        <TR>    <TD><TT>&lt;=</TT>
                <TD>less or equal

        <TR>    <TD><TT>&gt;</TT>
                <TD>greater

        <TR>    <TD><TT>&gt;=</TT>
                <TD>greater or equal

        <TR>    <TD><TT>==</TT>
                <TD>equal
                <TD rowspan="2">left to righ

        <TR>    <TD><TT>!=</TT>
                <TD>not equal

        <TR>    <TD><TT>&amp;</TT>
                <TD>bitwise AND
                <TD>left to right

        <TR>    <TD><TT>^</TT>
                <TD>bitwise XOR
                <TD>left to right

        <TR>    <TD><TT>|</TT>
                <TD>bitwise OR
                <TD>left to right

        <TR>    <TD><TT>&amp;&amp;</TT>
                <TD>logical AND
                <TD>left to right

        <TR>    <TD><TT>||</TT>
                <TD>logical OR
                <TD>left to right
        </TABLE>

        <P>
        Examples:

        <PRE>   
        2 * (3 + 4) + $x
        </PRE>

        is an usual integer arithmetic expression.

        <PRE>
        [tracklen mytrack]
        </PRE>
                
        is the returned value of the procedure <TT>tracklen</TT>
        called with a single argument <TT>mytrack</TT>.

        <PRE>
        { "bla" 3 zer }
        </PRE>

        is a list containing the string <TT>"bla"</TT> the integer
        3 and the name <TT>zer</TT>. A list is a set of
        expressions separated by spaces and enclosed between
        braces, a more complicated example is:

        <PRE>
        { "hello" 1+2*3 mytrack $i [myproc] { a b c } } 
        </PRE>


<H2>Procedure definition</H2>

        A procedure is defined with the keyword
        <TT>proc</TT> followed by the name of the procedure, 
        the names of its arguments and a block containing
        its body, example:

        <PRE>
        proc doubleprint x y { 
                print $x
                print $y
        }
        </PRE>

        Arguments and variables defined within a procedure 
        are local to that procedure
        and may shadow a global variable with the same
        name. The return value is given to the caller
        with a <TT>return</TT> statement:

        <PRE>
        proc square x {
                return $x * $x
        }
        </PRE>



        
<A name="functs"></A><H1>Function reference</H1>

<A name="func_track"></A>
<H2>Track functions</H2>

<A name="func_tracklist"></A>
<B><TT>tracklist</TT></B>
        <BLOCKQUOTE>
        return the list of names of the tracks in the song
        example:
        <PRE>
        print [tracklist]
        </PRE>
        </BLOCKQUOTE>

<A name="func_tracknew"></A>
<B><TT>tracknew trackname</TT></B>
        <BLOCKQUOTE>
        create an empty track named <TT>trackname</TT>
        </BLOCKQUOTE>

<A name="func_trackdelete"></A>
<B><TT>trackdelete trackname</TT></B>
        <BLOCKQUOTE>
        delete existing track '<TT>trackname</TT>'.
        Current track cannot be deleted.
        </BLOCKQUOTE>

<A name="func_trackreaname"></A>
<B><TT>trackrename trackname newname</TT></B>
        <BLOCKQUOTE>
        rename track '<TT>trackname</TT>' to '<TT>newname</TT>'
        </BLOCKQUOTE>

<A name="func_trackexists"></A>
<B><TT>trackexists trackname</TT></B>
        <BLOCKQUOTE>
        return 1 if <TT>trackname</TT> is a track, 0 otherwise
        </BLOCKQUOTE>
        
<A name="func_trackaddev"></A>
<B><TT>trackaddev trackname measure beat tic ev</TT></B>
        <BLOCKQUOTE>
        put the event <TT>ev</TT> on track <TT>trackname</TT>
        at the position given by <TT>measure</TT>,
        <TT>beat</TT> and <TT>tic</TT>
        </BLOCKQUOTE>

<A name="func_tracksetcurfilt"></A>
<B><TT>tracksetcurfilt trackname filtname</TT></B>
        <BLOCKQUOTE>
        set the default filter (for recording) of
        <TT>trackname</TT> to <TT>filtname</TT>. It will
        be user if there is no current filter.
        </BLOCKQUOTE>

<A name="func_trackgetcurfilt"></A>
<B><TT>trackgetcurfilt trackname</TT></B>
        <BLOCKQUOTE>
        return the default filter (for recording) 
        of <TT>trackname</TT>, returns <TT>nil</TT> if none
        </BLOCKQUOTE>
                
<A name="func_trackcheck"></A>
<B><TT>trackcheck trackname</TT></B>
        <BLOCKQUOTE>
        check the whole track for orphaned notes,
        nested notes and other anomalies; also
        removes multiple controllers in the same tic
        </BLOCKQUOTE>

<A name="func_trackcut"></A>
<B><TT>trackcut trackname from amount quantum</TT></B>
        <BLOCKQUOTE>
        cut <TT>amount</TT> measures of the track <TT>trackname</TT>
        from measure <TT>from</TT>.
        </BLOCKQUOTE>

<A name="func_trackblank"></A>
<B><TT>trackblank trackname from amount quantum evspec</TT></B>
        <BLOCKQUOTE>
        clear <TT>amount</TT> measures of the track <TT>trackname</TT>
        from the measure <TT>from</TT>. Only events matching
        the <TT>evspec</TT> argument are removed (see event
        <A href="#ev_evspec">ranges</A>)
        </BLOCKQUOTE>

<A name="func_trackinsert"></A>
<B><TT>trackinsert trackname from amount</TT></B>
        <BLOCKQUOTE>
        insert <TT>amount</TT> blank measures in track
        <TT>trackname</TT> just before the measure <TT>from</TT>
        </BLOCKQUOTE>

<A name="func_trackcopy"></A>
<B><TT>trackcopy trackname1 from amount trackname2 where quantum evspec</TT></B>
        <BLOCKQUOTE>
        copy <TT>amount</TT> measures starting at <TT>from</TT>
        from track <TT>trackname1</TT> into <TT>trackname2</TT>
        at position <TT>where</TT>. Only events matching
        the <TT>evspec</TT> argument are copied (see event
        <A href="#ev_evspec">ranges</A>)
        </BLOCKQUOTE>

<A name="func_trackquant"></A>
<B><TT>trackquant trackname from amount rate quantum</TT></B>
        <BLOCKQUOTE>
        quantise <TT>amount</TT> measures of the track
        <TT>trackname</TT> from measure <TT>from</TT> ; the quantum is
        the round in tics (see songsetunit). Rate must be
        between 0 and 100. 0 means no quantisation and
        100 means full quantisation.
        </BLOCKQUOTE>


<A name="func_tracksetmute"></A>
<B><TT>tracksetmute trackname muteflag</TT></B>
        <BLOCKQUOTE>
        If <TT>muteflag</TT> is equal to 1 the the track
        is muted ie it will not be played during record/playback.
        If <TT>muteflag</TT> is equal to 0 the the track
        is no more muted ie it will be played during record/playback.
        </BLOCKQUOTE>

<A name="func_trackgetmute"></A>
<B><TT>trackgetmute trackname</TT></B>
        <BLOCKQUOTE>
        Return 1 if the give track is muted and 0 otherwise.
        </BLOCKQUOTE>

<A name="func_trackchanlist"></A>
<B><TT>trackchanlist trackname</TT></B>
        <BLOCKQUOTE>
        Return the list of channels used by events stored in track 
        <TT>trackname</TT>.
        </BLOCKQUOTE>

<A name="func_trackinfo"></A>
<B><TT>trackinfo trackname quantum evspec</TT></B>
        <BLOCKQUOTE>
        display the number of events that match <TT>evspec</TT>
        for each measure of track <TT>trackname</TT>.
        </BLOCKQUOTE>

<A name="func_chan"></A>
<H2>Channel functions</H2>

<A name="func_channew"></A>
<B><TT>channew channelname { device midichan }</TT></B>
        <BLOCKQUOTE>
        create an new channel named <TT>channelname</TT>
        and assigned the given device and midi channel.
        </BLOCKQUOTE>

<A name="func_chanset"></A>
<B><TT>chanset channelname { dev, midichan }</TT></B>
        <BLOCKQUOTE>
        set the device/channel pair of an existing
	channel named <TT>channelname</TT>.
        </BLOCKQUOTE>

<A name="func_chandelete"></A>
<B><TT>chandelete channame</TT></B>
        <BLOCKQUOTE>
        delete existing channel '<TT>channame</TT>'.
        </BLOCKQUOTE>

<A name="func_chanrename"></A>
<B><TT>chanrename channame newname</TT></B>
        <BLOCKQUOTE>
        rename channel '<TT>channame</TT>' to '<TT>newname</TT>'
        </BLOCKQUOTE>

<A name="func_chanexists"></A>
<B><TT>chanexists channelname</TT></B>
        <BLOCKQUOTE>
        return 1 if <TT>channelname</TT> is a channel, 0 otherwise
        </BLOCKQUOTE>

<A name="func_changetch"></A>
<B><TT>changetch channelname</TT></B>
        <BLOCKQUOTE>
        return the midi channel number of channel named
        <TT>channelname</TT>
        </BLOCKQUOTE>

<A name="func_changetdev"></A>
<B><TT>changetdev channelname</TT></B>
        <BLOCKQUOTE>
        return the device number of channel named
        <TT>channelname</TT>
        </BLOCKQUOTE>

<A name="func_chanconfev"></A>
<B><TT>chanconfev channelname event</TT></B>
        <BLOCKQUOTE>
        add the event to the configuration of 
        channel <TT>channelname</TT>, typically used set
        the program, volume, depth etc... The channel
        of the event is not used.
        </BLOCKQUOTE>

<A name="func_chaninfo"></A>
<B><TT>chaninfo channame</TT></B>
        <BLOCKQUOTE>
        print all events on the config
        of the channel.
        </BLOCKQUOTE>

<A name="func_chansetcurinput"></A>
<B><TT>chansetcurinput channame {dev chan}</TT></B>
        <BLOCKQUOTE>
        set the default input <TT>{dev chan}</TT> pair 
	of channel <TT>channame</TT>. These values are currently not
	used in realtime.
        </BLOCKQUOTE>

<A name="func_changetcurinput"></A>
<B><TT>changetcurinput channame</TT></B>
        <BLOCKQUOTE>
        return the default input <TT>{dev chan}</TT> pair 
	of channel <TT>channame</TT>.
        </BLOCKQUOTE>

<A name="func_filt"></A>
<H2>Filter functions</H2>

<A name="func_filtnew"></A>
<B><TT>filtnew filtname</TT></B>
        <BLOCKQUOTE>
        create an new filter named <TT>filtname</TT>
        </BLOCKQUOTE>

<A name="func_filtdelete"></A>
<B><TT>filtdelete filtname</TT></B>
        <BLOCKQUOTE>
        delete existing filter '<TT>filtname</TT>'.
        Current filter and filters used by tracks cannot be deleted.
        </BLOCKQUOTE>

<A name="func_filtrename"></A>
<B><TT>filtrename filtname newname</TT></B>
        <BLOCKQUOTE>
        rename filter '<TT>filtname</TT>' to '<TT>newname</TT>'
        </BLOCKQUOTE>

<A name="func_filtexists"></A>
<B><TT>filtexists filtname</TT></B>
        <BLOCKQUOTE>
        return 1 if <TT>filtname</TT> is a filter, 0 otherwise
        </BLOCKQUOTE>

<A name="func_filtreset"></A>
<B><TT>filtreset filtname</TT></B>
        <BLOCKQUOTE>
        remove all rules from the filter <TT>filtname</TT>
        </BLOCKQUOTE>

<A name="func_filtinfo"></A>
<B><TT>filtinfo filtname</TT></B>
        <BLOCKQUOTE>
        list the rules of the given filter
        </BLOCKQUOTE>

<A name="func_filtsetcurchan"></A>
<B><TT>filtsetcurchan filtname channame</TT></B>
        <BLOCKQUOTE>
        set the default channel of filter
        <TT>filtname</TT> to <TT>channame</TT>.
        </BLOCKQUOTE>

<A name="func_filtgetcurchan"></A>
<B><TT>filtgetcurchan filtname</TT></B>
        <BLOCKQUOTE>
        return the default channel 
        of <TT>filtname</TT>, returns <TT>nil</TT> if none
        </BLOCKQUOTE>

<A name="func_filtchgich"></A>
<B><TT>filtchgich filtname oldchan newchan</TT></B>
        <BLOCKQUOTE>
        change the input channel of 
        all rules with input channel equal to <TT>oldchan</TT>
        to <TT>newchan</TT>
        </BLOCKQUOTE>

<A name="func_filtchgidev"></A>
<B><TT>filtchgidev filtname olddev newdev</TT></B>
        <BLOCKQUOTE>
        change the input device of 
        all rules with input device equal to <TT>olddev</TT>
        to <TT>newdev</TT>
        </BLOCKQUOTE>


<A name="func_filtswapich"></A>
<B><TT>filtswapich filtname oldchan newchan</TT></B>
        <BLOCKQUOTE>
        change the input channel of 
        all rules with input channel equal to <TT>oldchan</TT>
        to <TT>newchan</TT>, and the input channel of 
        all rules with input channel equal to <TT>newchan</TT>
        to <TT>oldchan</TT>,
        </BLOCKQUOTE>

<A name="func_filtswapidev"></A>
<B><TT>filtswapidev filtname olddev newdev</TT></B>
        <BLOCKQUOTE>
        change the input device of 
        all rules with input device equal to <TT>olddev</TT>
        to <TT>newdev</TT>, and the input device of 
        all rules with input device equal to <TT>newdev</TT>
        to <TT>olddev</TT>
        </BLOCKQUOTE>

<A name="func_filtchgoch"></A>
<B><TT>filtchgoch filtname oldchan newchan</TT></B>
        <BLOCKQUOTE>
        change the output channel of 
        all rules with output channel equal to <TT>oldchan</TT>
        to <TT>newchan</TT>
        </BLOCKQUOTE>

<A name="func_filtchgodev"></A>
<B><TT>filtchgodev filtname olddev newdev</TT></B>
        <BLOCKQUOTE>
        change the output device of 
        all rules with output device equal to <TT>olddev</TT>
        to <TT>newdev</TT>
        </BLOCKQUOTE>


<A name="func_filtswapoch"></A>
<B><TT>filtswapoch filtname oldchan newchan</TT></B>
        <BLOCKQUOTE>
        change the output channel of 
        all rules with output channel equal to <TT>oldchan</TT>
        to <TT>newchan</TT>, and the output channel of 
        all rules with output channel equal to <TT>newchan</TT>
        to <TT>oldchan</TT>,
        </BLOCKQUOTE>

<A name="func_filtswapodev"></A>
<B><TT>filtswapodev filtname olddev newdev</TT></B>
        <BLOCKQUOTE>
        change the output device of 
        all rules with output device equal to <TT>olddev</TT>
        to <TT>newdev</TT>, and the output device of 
        all rules with output device equal to <TT>newdev</TT>
        to <TT>olddev</TT>
        </BLOCKQUOTE>

<A name="func_filtdevdrop"></A>
<B><TT>filtdevdrop filtname inputdev</TT></B>
        <BLOCKQUOTE>
        make filter drop events from device <TT>inputdev</TT>
        </BLOCKQUOTE>

<A name="func_filtnodevdrop"></A>
<B><TT>filtnodevdrop filtname inputdev</TT></B>
        <BLOCKQUOTE>
        remove <TT>devdrop</TT> rules that drop events from device <TT>inputdev</TT>
        </BLOCKQUOTE>

<A name="func_filtdevmap"></A>
<B><TT>filtdevmap filtname inputdev outputdev</TT></B>
        <BLOCKQUOTE>
        route all events from device <TT>inputdev</TT>
        to device <TT>outputdev</TT>. If multiple dev maps are 
        defined for the same input device then events are 
        duplicated
        </BLOCKQUOTE>

<A name="func_filtnodevmap"></A>
<B><TT>filtnodevmap filtname outputdev</TT></B>
        <BLOCKQUOTE>
        remove <TT>devmap</TT> rules that route events to 
        device number <TT>outputdev</TT>. 
        </BLOCKQUOTE>

<A name="func_filtchandrop"></A>
<B><TT>filtchandrop filtname inputchan</TT></B>
        <BLOCKQUOTE>
        make filter drop events from channel <TT>inputchan</TT>
        </BLOCKQUOTE>

<A name="func_filtnochandrop"></A>
<B><TT>filtnochandrop filtname inputchan</TT></B>
        <BLOCKQUOTE>
        remove <TT>chandrop</TT> rules that 
        drop events from channel <TT>inputchan</TT>
        </BLOCKQUOTE>

<A name="func_filtchanmap"></A>
<B><TT>filtchanmap filtname inputchan outputchan</TT></B>
        <BLOCKQUOTE>
        route all events from channel <TT>inputchan</TT> 
        (ie device/midi-channel pair)
        to channel <TT>outputchan</TT>. If multiple channel maps are 
        defined for the same input channel then events are 
        duplicated
        </BLOCKQUOTE>

<A name="func_filtnochanmap"></A>
<B><TT>filtnochanmap filtname outputchan</TT></B>
        <BLOCKQUOTE>
        remove channel map rules that route events to channel 
        <TT>outputchan</TT>. 
        </BLOCKQUOTE>

<A name="func_filtctldrop"></A>
<B><TT>filtctldrop filtname inchan inctl</TT></B>
        <BLOCKQUOTE>
        make the filter drop controller number <TT>inctl</TT> 
        on channel <TT>inctl</TT>.
        </BLOCKQUOTE>

<A name="func_filtnoctldrop"></A>
<B><TT>filtnoctldrop filtname inchan inctl</TT></B>
        <BLOCKQUOTE>
        remove <TT>ctldrop</TT> rules that drop controller number 
        <TT>inctl</TT>  on channel <TT>inctl</TT>.
        </BLOCKQUOTE>

<A name="func_filtctlmap"></A>
<B><TT>filtctlmap filtname inchan outchan inctl outctl</TT></B>
        <BLOCKQUOTE>
        route controller <TT>inctl</TT> from <TT>inchan</TT>
        to controller <TT>outctl</TT> on <TT>outchan</TT>.
        If multiple ctlmaps are defined for the same input 
        channel and the same input controller then events are duplicated
        </BLOCKQUOTE>

<A name="func_filtnoctlmap"></A>
<B><TT>filtnoctlmap filtname outchan outctl</TT></B>
        <BLOCKQUOTE>
        remove <TT>ctlmap</TT> rules that route controllers to
        controller <TT>outctl</TT>, channel <TT>outchan</TT>.
        </BLOCKQUOTE>

<A name="func_filtkeydrop"></A>
<B><TT>filtkeydrop filtname inchan keystart keyend</TT></B>
        <BLOCKQUOTE>
        drop notes between <TT>keystart</TT> and <TT>keyend</TT>
        on channel <TT>inchan</TT>.
        </BLOCKQUOTE>

<A name="func_filtnokeydrop"></A>
<B><TT>filtnokeydrop filtname inchan keystart keyend</TT></B>
        <BLOCKQUOTE>
        remove <TT>keydrop</TT> rule that drop notes between 
        <TT>keystart</TT> and <TT>keyend</TT>
        on channel <TT>inchan</TT>.
        </BLOCKQUOTE>

<A name="func_filtkeymap"></A>
<B><TT>filtkeymap filtname inchan outchan keystart keyend keyplus</TT></B>
        <BLOCKQUOTE>
        route note events from channel <TT>inchan</TT> and
        in the range <TT>keystart..keyend</TT> to <TT>outchan</TT>.
        Routed notes are transposed by keyplus half-tones
        If multiple keymaps are defined for the same input 
        channel and key-range then events are duplicated
        </BLOCKQUOTE>

<A name="func_filtnokeymap"></A>
<B><TT>filtnokeymap filtname outchan keystart keyend</TT></B>
        <BLOCKQUOTE>
        remove <TT>keymap</TT> rules that route note events 
        in the range <TT>keystart..keyend</TT> to channel <TT>outchan</TT>.
        </BLOCKQUOTE>

<A name="func_sysex"></A>
<H2>System exclusive messages functions</H2>

<A name="func_sysexnew"></A>
<B><TT>sysexnew sysexname</TT></B>
        <BLOCKQUOTE>
        create a new bank of sysex messages named <TT>sysexname</TT>
        </BLOCKQUOTE>

<A name="func_sysexdelete"></A>
<B><TT>sysexdelete sysexname</TT></B>
        <BLOCKQUOTE>
        delete the bank of sysex messages named <TT>sysexname</TT>.
        Current 'sysex' cannot be deleted.
        </BLOCKQUOTE>

<A name="func_sysexrename"></A>
<B><TT>sysexrename sysexname newname</TT></B>
        <BLOCKQUOTE>
        rename sysex bank '<TT>sysexname</TT>' to '<TT>newname</TT>'
        </BLOCKQUOTE>

<A name="func_sysexexists"></A>
<B><TT>sysexexists sysexname</TT></B>
        <BLOCKQUOTE>
        return 1 if <TT>sysexname</TT> is a sysex bank, 0 otherwise
        </BLOCKQUOTE>

<A name="func_sysexclear"></A>
<B><TT>sysexclear sysexname pattern</TT></B>
        <BLOCKQUOTE>
        remove all sysex messages starting with <TT>pattern</TT>
        from sysex bank <TT>sysexname</TT>. The given pattern
        is a list of bytes; an empty pattern matches any 
        sysex message.
        </BLOCKQUOTE>

<A name="func_sysexsetunit"></A>
<B><TT>sysexsetunit sysexname newunit pattern</TT></B>
        <BLOCKQUOTE>
        set device number to <TT>newunit</TT> 
        on all sysex messages starting with <TT>pattern</TT> 
        from sysex bank <TT>sysexname</TT>. The given pattern
        is a list of bytes; an empty pattern matches any 
        sysex message.
        </BLOCKQUOTE>

<A name="func_sysexadd"></A>
<B><TT>sysexadd sysexname unit data</TT></B>
        <BLOCKQUOTE>
        add to sysex bank <TT>sysexname</TT>
        an new sysex message. <TT>data</TT> is a list containing the
        midi system exclusive message and <TT>unit</TT> is the device number to which
        the message will be sent
        </BLOCKQUOTE>

<A name="func_sysexinfo"></A>
<B><TT>sysexinfo sysexname</TT></B>
        <BLOCKQUOTE>
        print debug info about sysex bank <TT>sysexname</TT>
        </BLOCKQUOTE>

<A name="func_rt"></A>
<H2>Real-time functions</H2>

<A name="func_songidle"></A>
<B><TT>songidle</TT></B>
        <BLOCKQUOTE>
        put midi input to the midi output,
        data passes through the current filter (if any)
        or through the current track's filter (if any).
        </BLOCKQUOTE>

<A name="func_songplay"></A>
<B><TT>songplay</TT></B>
        <BLOCKQUOTE>
        play the song from the current position.
        Input passes through the current filter (if any)
        or through the current track's filter (if any).
        </BLOCKQUOTE>

<A name="func_songrecord"></A>
<B><TT>songrecord</TT></B>
        <BLOCKQUOTE>
        play the song and record the input.
        Input passes through the current filter (if any)
        or through the current track's filter (if any).
	<TT>songrecord</TT> always tries to play one measure before
	the actual position on which recording starts.
        </BLOCKQUOTE>

<A name="func_sendraw"></A>
<B><TT>sendraw device arrayofbytes</TT></B>
        <BLOCKQUOTE>
        send raw midi data to device number '<TT>device</TT>',
        can be used to send system exclusive messages,
        example:
        <PRE>
        sendraw 0 { 0xF0 0x7E 0x7F 0x09 0x01 0xF7 }
        </PRE>
        </BLOCKQUOTE>

<A name="func_song"></A>
<H2>Song functions</H2>

<A name="func_songsetcurquant"></A>
<B><TT>songsetcurquant tics</TT></B>
        <BLOCKQUOTE>
        set the number of tics in the time scale 
        (for quantisation, track editing...). 
        Currently this value is not used in real-time.
        </BLOCKQUOTE>

<A name="func_songgetcurquant"></A>
<B><TT>songgetcurquant tics</TT></B>
        <BLOCKQUOTE>
        get the number of tics in the time scale.
        </BLOCKQUOTE>

<A name="func_songsetcurpos"></A>
<B><TT>songsetcurpos measure</TT></B>
        <BLOCKQUOTE>
        set the current song position pointer to
        the measure <TT>measure</TT>. Record and playback
        will start a that position.
	This corresponds also
	to the start postition of the current selection.
        </BLOCKQUOTE>

<A name="func_songgetcurpos"></A>
<B><TT>songgetcurpos</TT></B>
        <BLOCKQUOTE>
        return the current measure ie the
        current song position pointer. This corresponds
	to the start postition of the current selection.
        </BLOCKQUOTE>

<A name="func_songsetcurlen"></A>
<B><TT>songsetcurlen length</TT></B>
        <BLOCKQUOTE>
        set the length of the current selection to '<TT>length</TT>' measures.
        </BLOCKQUOTE>

<A name="func_songgetcurlen"></A>
<B><TT>songgetcurlen</TT></B>
        <BLOCKQUOTE>
        return the length (in measures) of the current selection.
        </BLOCKQUOTE>


<A name="func_songsetcurtrack"></A>
<B><TT>songsetcurtrack trackname</TT></B>
        <BLOCKQUOTE>
        set the current track ie the track to be recorded
        </BLOCKQUOTE>

<A name="func_songgetcurtrack"></A>
<B><TT>songgetcurtrack</TT></B>
        <BLOCKQUOTE>
        return the current track (if any) or <TT>nil</TT>
        </BLOCKQUOTE>

<A name="func_songsetcurfilt"></A>
<B><TT>songsetcurfilt filtname</TT></B>
        <BLOCKQUOTE>
        set the current filter ie the one used (with
        songplay and songidle).
        </BLOCKQUOTE>

<A name="func_songgetcurfilt"></A>
<B><TT>songgetcurfilt</TT></B>
        <BLOCKQUOTE>
        return the current filter
        or <TT>'nil'</TT> if none
        </BLOCKQUOTE>

<A name="func_songsetcursysex"></A>
<B><TT>songsetcursysex sysexname</TT></B>
        <BLOCKQUOTE>
        set the current sysex bank, 
        ie the one that will be recorded
        </BLOCKQUOTE>

<A name="func_songgetcursysex"></A>
<B><TT>songgetcursysex</TT></B>
        <BLOCKQUOTE>
        return the current sysex bank
        or <TT>'nil'</TT> if none
        </BLOCKQUOTE>

<A name="func_songsetcurchan"></A>
<B><TT>songsetcurchan channame</TT></B>
        <BLOCKQUOTE>
        set the current (named) channel.
        </BLOCKQUOTE>

<A name="func_songgetcurchan"></A>
<B><TT>songgetcurchan</TT></B>
        <BLOCKQUOTE>
        return the name of the current channel 
        or <TT>'nil'</TT> if none
        </BLOCKQUOTE>

<A name="func_chansetcurinput"></A>
<B><TT>songsetcurinput {dev chan}</TT></B>
        <BLOCKQUOTE>
        set the (global) default input <TT>{dev chan}</TT> pair.
	These values are currently not used in realtime.
        </BLOCKQUOTE>

<A name="func_changetcurinput"></A>
<B><TT>changetcurinput channame</TT></B>
        <BLOCKQUOTE>
        return the (global) default input <TT>{dev chan}</TT> pair.
        </BLOCKQUOTE>

<A name="func_songsetunit"></A>
<B><TT>songsetunit tpu</TT></B>
        <BLOCKQUOTE>
        set the time resolution of the sequencer to <TT>tpu</TT>
        tics per unit (1 unit = 4 quarter notes).  the
        unit shall be changed before creating any tracks. 
        The default is 96 tics per unit, which is the
        default of the midi standard.
        </BLOCKQUOTE>

<A name="func_songgetunit"></A>
<B><TT>songgetunit</TT></B>
        <BLOCKQUOTE>
        return the number of tics per unit note
        </BLOCKQUOTE>

<A name="func_songsettempo"></A>
<B><TT>songsettempo measure bpm</TT></B>
        <BLOCKQUOTE>
        set the tempo to <TT>bpm</TT> beats per
        minute at measure <TT>measure</TT>
        </BLOCKQUOTE>

<A name="func_songtimeins"></A>
<B><TT>songtimeins from amount numerator denominator</TT></B>
        <BLOCKQUOTE>
        insert <TT>amount</TT> blank measures at measure
        <TT>from</TT>. The used time signature is given
        by numerator/denominator.
        </BLOCKQUOTE>

<A name="func_songtimerm"></A>
<B><TT>songtimerm from amount</TT></B>
        <BLOCKQUOTE>
        delete <TT>amount</TT> measures starting at
        measure <TT>from</TT>. The time signature is
        restored with the value preceding the
        <TT>from</TT> measure.
        </BLOCKQUOTE>

<A name="func_songtimeinfo"></A>
<B><TT>songtimeinfo</TT></B>
        <BLOCKQUOTE>
        print the meta-track (tempo changes, time signature
        changes
        </BLOCKQUOTE>

<A name="func_songinfo"></A>
<B><TT>songinfo</TT></B>
        <BLOCKQUOTE>
        display some info about the default values of
        the song
        </BLOCKQUOTE>

<A name="func_songsave"></A>
<B><TT>songsave filename</TT></B>
        <BLOCKQUOTE>
        save the song in a file, <TT>filename</TT>
        is a quoted string.
        </BLOCKQUOTE>

<A name="func_songload"></A>
<B><TT>songload filename</TT></B>
        <BLOCKQUOTE>
        load the song from a file named <TT>filename</TT>.
        the current song is destroyed, even if 
        the load command failed
        </BLOCKQUOTE>

<A name="func_songreset"></A>
<B><TT>songreset</TT></B>
        <BLOCKQUOTE>
        destroy completely the song, useful to
        start a new song without restarting the
        program
        </BLOCKQUOTE>

<A name="func_songexportsmf"></A>
<B><TT>songexportsmf filename</TT></B>
        <BLOCKQUOTE>
        save the song into a standard midi file, <TT>filename</TT>
        is a quoted string.
        </BLOCKQUOTE>

<A name="func_songimportsmf"></A>
<B><TT>songimportsmf filename</TT></B>
        <BLOCKQUOTE>
        load the song from a standard midi file, <TT>filename</TT>
        is a quoted string. Currently only midi file "type 1" is
        supported.
        </BLOCKQUOTE>

<A name="func_dev"></A>
<H2>Device functions</H2>

<A name="func_devlist"></A>
<B><TT>devlist</TT></B>
        <BLOCKQUOTE>
        return the list of attached devices
        (list of numbers)
        </BLOCKQUOTE>

<A name="func_devattach"></A>
<B><TT>devattach devnum filename</TT></B>
        <BLOCKQUOTE>
        attach midi device <TT>filename</TT> as
        device number <TT>devnum</TT>; <TT>filename</TT>
        is a quoted string.
        </BLOCKQUOTE>

<A name="func_devdetach"></A>
<B><TT>devdetach devnum</TT></B>
        <BLOCKQUOTE>
        detach device number <TT>devnum</TT>
        </BLOCKQUOTE>

<A name="func_devmaster"></A>
<B><TT>devsetmaster devnum</TT></B>
        <BLOCKQUOTE>
        set device number <TT>devnum</TT> to be the master clock source.
        It will give tempo, start event and stop event. If <TT>devnum</TT> is
        <TT>nil</TT>, then the internal clock will be used and midish
        will act as master device.
        </BLOCKQUOTE>

<A name="func_devgetmaster"></A>
<B><TT>devgetmaster devnum</TT></B>
        <BLOCKQUOTE>
        return the current master device. If non, <TT>nil</TT> is
        returned.
        </BLOCKQUOTE>

<A name="func_devsendrt"></A>
<B><TT>devsendrt devnum bool</TT></B>
        <BLOCKQUOTE>
        If <TT>bool</TT> is true, the real-time information (midi tics, 
        midi start and midi trop events) will be transmitted to device
        number <TT>devnum</TT>. 
        Otherwise no real-time midi events are transmitted.
        </BLOCKQUOTE>
        
<A name="func_devticrate"></A>
<B><TT>devticrate devnum ticrate</TT></B>
        <BLOCKQUOTE>
        set the number of tics per unit note that are transmitted
        to the midi device if "sendrt" feature is active. Default
        value is 96 tics. This is the standard MIDI value and
        its not recommended to change it.
        </BLOCKQUOTE>
        
<A name="func_devinfo"></A>
<B><TT>devinfo devnum</TT></B>
        <BLOCKQUOTE>
        Print some information about the midi device.
        </BLOCKQUOTE>

<A name="func_misc"></A>
<H2>Misc. functions</H2>

<A name="func_metroswitch"></A>
<B><TT>metroswitch number</TT></B>
        <BLOCKQUOTE>
        if <TT>number</TT> is equal to zero then the metronome is disabled
        else it is enabled
        </BLOCKQUOTE>   

<A name="func_metroconf"></A>
<B><TT>metroconf eventhi eventlo</TT></B>
        <BLOCKQUOTE>    
        select the notes that the metronome plays. The
        pair of events must be note-ons
        </BLOCKQUOTE>
        
<A name="func_info"></A>
<B><TT>info</TT></B>
        <BLOCKQUOTE>
        display the list of built-in and user-defined
        procedures and global variables
        </BLOCKQUOTE>

<A name="func_print"></A>
<B><TT>print expression</TT></B>
        <BLOCKQUOTE>
        display the value of the expression
        </BLOCKQUOTE>

<A name="func_exec"></A>
<B><TT>exec filename</TT></B>
        <BLOCKQUOTE>
        read and executes the script from a file, <TT>filename</TT>
        is a quoted string.
        </BLOCKQUOTE>

<A name="func_debug"></A>
<B><TT>debug flag val</TT></B>
        <BLOCKQUOTE>
        set debug-flag <TT>flag</TT> to (integer) value <TT>val</TT>. 
        If <TT>val=0</TT> the corresponding debug-info are
        turned off. <TT>flag</TT> can be: 
        <UL>
        <LI><TT>rmidi</TT> - show raw midi traffic on stderr
        <LI><TT>filt</TT> - show events passing through the current filter 
        <LI><TT>song</TT> - show start/stop events
        </UL>
        </BLOCKQUOTE>

<A name="func_panic"></A>
<B><TT>panic</TT></B>
        <BLOCKQUOTE>
        cause the sequencer to core-dump
        </BLOCKQUOTE>

        
<A name="midishrc"></A><H1>Sample midishrc-file</H1>
        
        <P>
        The sample midishrc file shipped in the source tar-balls
        contains a lot of examples of procedure definitions.
        
        <P>
	<B><TT>ci { dev chan }</TT></B>
                <BLOCKQUOTE>
                set the current input device/channel pair.
		It will be used as default value
		when tracks, filters and channels are created.
                </BLOCKQUOTE>

        
        <B><TT>cc channame</TT></B>
                <BLOCKQUOTE>
                set the current output channel.
		It will be used as default value
		when tracks and filters are created.
		The current input that was used the last time 
		this channel was the current one is restored.
                </BLOCKQUOTE>

        <B><TT>cf filtname</TT></B>
                <BLOCKQUOTE>
		set the default filter, that will be used in
		performance mode. 
		It will be  used as default
		value when tracks are created.
		The value of the default track is reset to 'nil'
		(no default track).
		The current channel and the current input 
		that were used the last time
		this filter was the current one are restored.
                </BLOCKQUOTE>

        <B><TT>ct trackname</TT></B>
                <BLOCKQUOTE>
		set the current track, that will be recorded in
		record mode. 
		The current filter, the current channel and 
		the current input that were used the last time 
		this track was the current one are restored.
                </BLOCKQUOTE>

	<B><TT>ni instrname {device channel}</TT></B>
                <BLOCKQUOTE>
		create a new channel and a new filter
		with the same name in such
		a way that the current input is routed
		to this channel.
                </BLOCKQUOTE>
        
        <B><TT>ctldrop ictl</TT></B>
                <BLOCKQUOTE>
                make the current filter drop controller number <TT>ictl</TT>
		on the current input
                </BLOCKQUOTE>

        <B><TT>ctlmap ictl octl</TT></B>
                <BLOCKQUOTE>
                make the current filter route controller number
                <TT>ictl</TT> on the current input
		to controller <TT>octl</TT> on the current channel
                </BLOCKQUOTE>
                
        <B><TT>transpose halftones</TT></B>
                <BLOCKQUOTE>
                make the current filter to transpose
		all notes from the current input and
		to route them to the current channel.
                </BLOCKQUOTE>

        <B><TT>nt trackname</TT></B>
                <BLOCKQUOTE>
                create a new track.
                </BLOCKQUOTE>
                        
        <B><TT>i</TT></B>
                <BLOCKQUOTE>
                go into performance mode and run the current filter
                of the current track.
                </BLOCKQUOTE>
                
        <B><TT>p</TT></B>
                <BLOCKQUOTE>
                go in performance mode and play the all defined 
                tracks and run the current filter of the current track
                </BLOCKQUOTE>
                
        <B><TT>r</TT></B>
                <BLOCKQUOTE>
                go in performance mode and record the current track
                using its current filter
                </BLOCKQUOTE>
                
        <B><TT>l</TT></B>
                <BLOCKQUOTE>
                list tracks, channels and filter
                and print some additional info
                </BLOCKQUOTE>
                
        <B><TT>g measurenum</TT></B> 
                <BLOCKQUOTE>
                move the current song position to 
                measure number <TT>measurenum</TT>. Play/record
                and all editing procedures that follow
                will start at that position
                </BLOCKQUOTE>

        <B><TT>sel nummeasures</TT></B> 
                <BLOCKQUOTE>
                select measures from the current position.
		Track editing procedures (q, copy, cut, clr ...)
                will use the current selection.
                </BLOCKQUOTE>

        <B><TT>n denominator</TT></B>
                <BLOCKQUOTE>
                set the current note length for quantisation
                to <TT>denominator</TT>, 4 means quarter-note, 
                8 means eighth-note, 16 means sixteenth-note etc...
		This value will be used by track editing functions.
                </BLOCKQUOTE>
                
        <B><TT>q rate</TT></B>
                <BLOCKQUOTE>
                quantise the current selection of 
                the current track (rate=100 means full quantisation
		and rate=0 means no quantisation).
                </BLOCKQUOTE>
                
        <B><TT>cut amount</TT></B>
                <BLOCKQUOTE>
                cut the given number of measures
		from the current position on the current track.
                </BLOCKQUOTE>
                
        <B><TT>clr</TT></B>
                <BLOCKQUOTE>
                clear (removes events but not blank space) 
		the current selection on the current track.
                </BLOCKQUOTE>
                
        <B><TT>ins num</TT></B> 
                <BLOCKQUOTE>
                insert <TT>num</TT> empty measures into the
                current track at the current position
                </BLOCKQUOTE>
                
        <B><TT>copy pos</TT></B> 
                <BLOCKQUOTE>
                copy the current selection <TT>pos</TT> measures
		forward from the current position.
                </BLOCKQUOTE>

        <B><TT>gcut</TT></B> 
                <BLOCKQUOTE>
                same as <TT>cut</TT> but acts on all tracks
                simultaneously ("g" like global).
                </BLOCKQUOTE>
                
        <B><TT>gins num</TT></B> 
                <BLOCKQUOTE>
                same as <TT>ins</TT> but acts on all tracks
                simultaneously ("g" like global).
                </BLOCKQUOTE>

        <B><TT>gcopy num</TT></B> 
                <BLOCKQUOTE>
                same as <TT>copy</TT> but acts on all tracks
                simultaneously ("g" like global).
                </BLOCKQUOTE>

        <B><TT>mute trackname</TT></B>
                <BLOCKQUOTE>
                mute track <TT>trackname</TT>. The track will
                be no more audible during playback.
                </BLOCKQUOTE>
                
        <B><TT>solo</TT></B>
                <BLOCKQUOTE>
                mute all tracks but current
                </BLOCKQUOTE>

        <B><TT>unmute trackname</TT></B>
                <BLOCKQUOTE>
                unmute track <TT>trackname</TT>. The track will
                be audible during playback.
                </BLOCKQUOTE>
                
        <B><TT>nomute</TT></B>
                <BLOCKQUOTE>
                unmute all tracks.
                </BLOCKQUOTE>   
                
        <B><TT>save filename</TT></B>
                <BLOCKQUOTE>
                save the whole project (filters, tracks, channels,
                and current settings) in file <TT>filename</TT>.
                </BLOCKQUOTE>
                                
        <B><TT>load filename</TT></B>
                <BLOCKQUOTE>
                load the whole project (filters, tracks, channels,
                and current settings) from file <TT>filename</TT>.
                </BLOCKQUOTE>
                
        <B><TT>tempo bpm</TT></B>
                <BLOCKQUOTE>
                change the tempo at the current position
                to <TT>bpm</TT> beats per measure.
                </BLOCKQUOTE>
                
        <B><TT>timeins num numerator denominator</TT></B> 
                <BLOCKQUOTE>
                insert <TT>num</TT> measures in the
                meta-track with the time signature 
                <TT>numerator/denominator</TT>
                </BLOCKQUOTE>
                
        <B><TT>timerm num</TT></B>
                <BLOCKQUOTE>
                remove <TT>num</TT> measures from
                the meta-track.
                </BLOCKQUOTE>
                
        <B><TT>gmon devnum</TT></B>
                <BLOCKQUOTE>
                send "general midi on" system exclusive message
                to device number <TT>devnum</TT>
                </BLOCKQUOTE>
                                
        <B><TT>gmp patch</TT></B> 
                <BLOCKQUOTE>
                configures the current channel
                to use general midi patch number <TT>patch</TT>.
                (this will send program change event when
                performance mode is entered).
                </BLOCKQUOTE>
                
        <B><TT>vol value</TT></B> 
                <BLOCKQUOTE>
                set volume (controller number 7) of
                the current channel
                </BLOCKQUOTE>
                
        <B><TT>reverb value</TT></B> 
                <BLOCKQUOTE>
                set reverb (controller number 91) of
                the current channel
                </BLOCKQUOTE>
                
        <B><TT>chorus value</TT></B> 
                <BLOCKQUOTE>
                set chorus (controller number 93) of
                the current channel
                </BLOCKQUOTE>
                        
<A name="example"></A><H1>Example sessions</H1>

<H2>Example - midi filtering</H2>
        
        The following session show how to 
        configure a keyboard split:
                
        <PRE>
        1> channew bass {0 5}
        2> chanconfev bass {pc bass 33}
        3> channew piano {0 6}
        4> chanconfev piano {pc piano 2}
        5> filtnew split
        6> filtchanmap split {1 0} bass 
        7> filtchanmap split {1 0} piano
        8> filtkeymap  split {1 0} bass   0  63 (-12)
        9> filtkeymap  split {1 0} piano 64 127 0   
        10> filtinfo split
        {
                keymap {1 0} {0 2} 65 127 0 id
                keymap {1 0} {0 1} 0 64 116 id
                chanmap {1 0} {0 2}
                chanmap {1 0} {0 1}
        }
        11> songidle
        press enter to finish
        ^C
        -- interrupt --

        12> songsave "piano-bass"
	13>
        </PRE>

        First we define 2 named-channels 
        <TT>bass</TT> on device 0, channel 5
        and <TT>piano</TT> on device 0 channel 6.
        Then we assign patches to the respective
        channels. After this, we define a new
        filter <TT>split</TT> and we add
        rules corresponding to the keyboard-split
        on note number 64 (note E3), the bass is 
        transposed by -12 half-tones (one octave).

<H2>Example - recording a track</H2>

        The following session show how to
        record a track. It uses the procedures defined
	in the default <TT>/etc/midishrc</TT>.
        <PRE>
	1> ci {1 0}
	2> ni drums {0 9}
	3> nt dr1
	4> tempo 90
	5> r
	press control-C to finish

	--interrupt--

	6> n 16
	7> sel 32
	8> q 75
	9> p
	press control-C to finish

	--interrupt--

	10> save "myrhythm"
	11> 
        </PRE>
        first, we set the default input channel to {1 0}
	(default channel of the keyboard). Then, we	
	define the <TT>drum</TT> channel
        on device 0, channel 9 and the corresponding
	filter that will route events from the
	keyboard to the drum channel.  Then we define 
        a new track named <TT>dr1</TT> an we start recording.
        Then, we set the quantisation step to 16 
        (sixteenth note), we select the first 32 measures of 
        the track and we quantise them. Finally,
	we start playback and we save the song into a file.


<HR>
<SMALL><EM>
Copyright (c) 2003-2005 Alexandre Ratchov<BR>
Last updated oct 27, 2005       
</EM></SMALL>
        

</BODY>
</HTML>