nodeskini 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/README.md +31 -0
  2. package/client/archive/bundle.js +11528 -0
  3. package/client/archive/golem.html +60 -0
  4. package/client/archive/golemClient.js +595 -0
  5. package/client/archive/golembundle.js +11634 -0
  6. package/client/archive/sequencer.html +43 -0
  7. package/client/archive/sequenceurClient.js +815 -0
  8. package/client/archive/stylegolem.css +158 -0
  9. package/client/archive/stylesequenceur.css +204 -0
  10. package/client/clientListe/Sortable-master/.circleci/config.yml +33 -0
  11. package/client/clientListe/Sortable-master/.editorconfig +15 -0
  12. package/client/clientListe/Sortable-master/.github/ISSUE_TEMPLATE/bug-report.md +73 -0
  13. package/client/clientListe/Sortable-master/.github/ISSUE_TEMPLATE/custom-template.md +48 -0
  14. package/client/clientListe/Sortable-master/.github/ISSUE_TEMPLATE/feature-request.md +41 -0
  15. package/client/clientListe/Sortable-master/.jshintrc +25 -0
  16. package/client/clientListe/Sortable-master/.testcaferc.json +7 -0
  17. package/client/clientListe/Sortable-master/CONTRIBUTING.md +26 -0
  18. package/client/clientListe/Sortable-master/LICENSE +21 -0
  19. package/client/clientListe/Sortable-master/README.md +813 -0
  20. package/client/clientListe/Sortable-master/Sortable.js +3709 -0
  21. package/client/clientListe/Sortable-master/Sortable.min.js +2 -0
  22. package/client/clientListe/Sortable-master/Sortable.min.old.js +2 -0
  23. package/client/clientListe/Sortable-master/Sortable.min.old.old.js +2 -0
  24. package/client/clientListe/Sortable-master/babel.config.js +27 -0
  25. package/client/clientListe/Sortable-master/bower.json +30 -0
  26. package/client/clientListe/Sortable-master/entry/entry-complete.js +8 -0
  27. package/client/clientListe/Sortable-master/entry/entry-core.js +19 -0
  28. package/client/clientListe/Sortable-master/entry/entry-defaults.js +19 -0
  29. package/client/clientListe/Sortable-master/index.html +460 -0
  30. package/client/clientListe/Sortable-master/modular/sortable.complete.esm.js +3701 -0
  31. package/client/clientListe/Sortable-master/modular/sortable.core.esm.js +3698 -0
  32. package/client/clientListe/Sortable-master/modular/sortable.esm.js +3699 -0
  33. package/client/clientListe/Sortable-master/package-lock.json +5704 -0
  34. package/client/clientListe/Sortable-master/package.json +56 -0
  35. package/client/clientListe/Sortable-master/plugins/AutoScroll/AutoScroll.js +270 -0
  36. package/client/clientListe/Sortable-master/plugins/AutoScroll/README.md +80 -0
  37. package/client/clientListe/Sortable-master/plugins/AutoScroll/index.js +1 -0
  38. package/client/clientListe/Sortable-master/plugins/MultiDrag/MultiDrag.js +617 -0
  39. package/client/clientListe/Sortable-master/plugins/MultiDrag/README.md +96 -0
  40. package/client/clientListe/Sortable-master/plugins/MultiDrag/index.js +1 -0
  41. package/client/clientListe/Sortable-master/plugins/OnSpill/OnSpill.js +79 -0
  42. package/client/clientListe/Sortable-master/plugins/OnSpill/README.md +60 -0
  43. package/client/clientListe/Sortable-master/plugins/OnSpill/index.js +1 -0
  44. package/client/clientListe/Sortable-master/plugins/README.md +178 -0
  45. package/client/clientListe/Sortable-master/plugins/Swap/README.md +55 -0
  46. package/client/clientListe/Sortable-master/plugins/Swap/Swap.js +90 -0
  47. package/client/clientListe/Sortable-master/plugins/Swap/index.js +1 -0
  48. package/client/clientListe/Sortable-master/scripts/banner.js +8 -0
  49. package/client/clientListe/Sortable-master/scripts/build.js +17 -0
  50. package/client/clientListe/Sortable-master/scripts/esm-build.js +28 -0
  51. package/client/clientListe/Sortable-master/scripts/minify.js +11 -0
  52. package/client/clientListe/Sortable-master/scripts/test-compat.js +30 -0
  53. package/client/clientListe/Sortable-master/scripts/test.js +21 -0
  54. package/client/clientListe/Sortable-master/scripts/umd-build.js +15 -0
  55. package/client/clientListe/Sortable-master/src/Animation.js +175 -0
  56. package/client/clientListe/Sortable-master/src/BrowserInfo.js +12 -0
  57. package/client/clientListe/Sortable-master/src/EventDispatcher.js +57 -0
  58. package/client/clientListe/Sortable-master/src/PluginManager.js +87 -0
  59. package/client/clientListe/Sortable-master/src/Sortable.js +1971 -0
  60. package/client/clientListe/Sortable-master/src/utils.js +556 -0
  61. package/client/clientListe/Sortable-master/st/app.js +224 -0
  62. package/client/clientListe/Sortable-master/st/iframe/frame.html +32 -0
  63. package/client/clientListe/Sortable-master/st/iframe/index.html +49 -0
  64. package/client/clientListe/Sortable-master/st/logo.png +0 -0
  65. package/client/clientListe/Sortable-master/st/og-image.png +0 -0
  66. package/client/clientListe/Sortable-master/st/prettify/prettify.css +1 -0
  67. package/client/clientListe/Sortable-master/st/prettify/prettify.js +46 -0
  68. package/client/clientListe/Sortable-master/st/prettify/run_prettify.js +64 -0
  69. package/client/clientListe/Sortable-master/st/saucelabs.svg +1 -0
  70. package/client/clientListe/Sortable-master/st/theme.css +254 -0
  71. package/client/clientListe/Sortable-master/tests/Sortable.compat.test.js +39 -0
  72. package/client/clientListe/Sortable-master/tests/Sortable.test.js +386 -0
  73. package/client/clientListe/Sortable-master/tests/dual-list.html +34 -0
  74. package/client/clientListe/Sortable-master/tests/empty-list.html +30 -0
  75. package/client/clientListe/Sortable-master/tests/filter.html +27 -0
  76. package/client/clientListe/Sortable-master/tests/handles.html +27 -0
  77. package/client/clientListe/Sortable-master/tests/nested.html +67 -0
  78. package/client/clientListe/Sortable-master/tests/single-list.html +25 -0
  79. package/client/clientListe/Sortable-master/tests/style.css +18 -0
  80. package/client/clientListe/clientListe.html +148 -0
  81. package/client/clientListe/clientListe.js +1508 -0
  82. package/client/clientListe/clientListebundle.js +13164 -0
  83. package/client/clientListe/images/poubelle.png +0 -0
  84. package/client/clientListe/images/start.png +0 -0
  85. package/client/clientListe/images/stop.png +0 -0
  86. package/client/clientListe/images/submit.png +0 -0
  87. package/client/clientListe/sortable-theme-bootstrap.css +90 -0
  88. package/client/configurateur/configReact.js +273 -0
  89. package/client/configurateur/configReactbundle.js +295 -0
  90. package/client/configurateur/configurateur.css +95 -0
  91. package/client/configurateur/configurateur.html +48 -0
  92. package/client/configurateur/lib/jexcel.css +755 -0
  93. package/client/configurateur/lib/jexcel.js +14970 -0
  94. package/client/configurateur/lib/jsuites.css +2801 -0
  95. package/client/configurateur/lib/jsuites.js +11822 -0
  96. package/client/configurateur/lib/react-dom.production.min.js +239 -0
  97. package/client/configurateur/lib/react.production.min.js +32 -0
  98. package/client/configurateur/src/configReact.js +247 -0
  99. package/client/controleur/clientcontroleur.js +536 -0
  100. package/client/controleur/clientcontroleur.test.js +282 -0
  101. package/client/controleur/controleur.html +51 -0
  102. package/client/controleur/controleurbundle.js +565 -0
  103. package/client/controleur/stylecontroleur.css +236 -0
  104. package/client/controleurHH/controleurHH.html +71 -0
  105. package/client/controleurHH/controleurHH.js +252 -0
  106. package/client/controleurHH/styles/index.css +320 -0
  107. package/client/controleurHH/styles/material.css +11552 -0
  108. package/client/parametrage/paramReact.js +473 -0
  109. package/client/parametrage/paramReactbundle.js +500 -0
  110. package/client/parametrage/parametrage.css +111 -0
  111. package/client/parametrage/parametrage.html +163 -0
  112. package/client/parametrage/src/paramReact.js +459 -0
  113. package/client/score/hash.js +83 -0
  114. package/client/score/p5.min.js +3 -0
  115. package/client/score/parto1.js +1171 -0
  116. package/client/score/parto1bundle.js +1181 -0
  117. package/client/score/processing.min.js +431 -0
  118. package/client/score/score.html +15 -0
  119. package/client/score/score.js +34 -0
  120. package/client/simulateurListe/simulateurFork.js +750 -0
  121. package/client/simulateurListe/simulateurFork.mjs +681 -0
  122. package/client/simulateurListe/simulateurForkSansReorg.js +569 -0
  123. package/client/simulateurListe/simulateurListe.js +628 -0
  124. package/myReact/archive/Nodeemitvaluedlocal1.hh.js +52 -0
  125. package/myReact/archive/abort-parNode.js +79 -0
  126. package/myReact/archive/abroNode.js +169 -0
  127. package/myReact/archive/abroNode2.js +80 -0
  128. package/myReact/archive/atom.compile.hh.js +51 -0
  129. package/myReact/archive/await-countNode.js +67 -0
  130. package/myReact/archive/await-nowvalNode.js +44 -0
  131. package/myReact/archive/callHH.js +96 -0
  132. package/myReact/archive/emit-if2.hh.compiled.js +113 -0
  133. package/myReact/archive/every1Node.js +35 -0
  134. package/myReact/archive/if-runNode.js +74 -0
  135. package/myReact/archive/if1Node.js +43 -0
  136. package/myReact/archive/makeawait.js +0 -0
  137. package/myReact/archive/myReact.old.js +684 -0
  138. package/myReact/archive/orchestration.js +281 -0
  139. package/myReact/archive/orchestration1.js +132 -0
  140. package/myReact/archive/orchestration1.xml +465 -0
  141. package/myReact/archive/orchestration2.js +161 -0
  142. package/myReact/archive/orchestrationHH.mano.js +280 -0
  143. package/myReact/archive/orchestrationHHTest.js +428 -0
  144. package/myReact/archive/orchestrationHHTest.xml +234 -0
  145. package/myReact/archive/orchestrationHHTestRun.js +104 -0
  146. package/myReact/archive/orchestrationHHTestRun.xml +34 -0
  147. package/myReact/archive/orchestrationTest0.js +178 -0
  148. package/myReact/archive/orchestrationTest1.js +181 -0
  149. package/myReact/archive/orchestrationTest2.js +281 -0
  150. package/myReact/archive/run3pointsNode.js +59 -0
  151. package/myReact/archive/runNode.js +123 -0
  152. package/myReact/archive/runNode2.js +91 -0
  153. package/myReact/archive/testAwait1.js +141 -0
  154. package/myReact/archive/testAwait1.xml +86 -0
  155. package/myReact/archive/testEvery1.js +122 -0
  156. package/myReact/archive/testEvery1.xml +79 -0
  157. package/myReact/archive/testHH1.js +135 -0
  158. package/myReact/archive/testHH1.xml +86 -0
  159. package/myReact/archive/testHH1revu.js +104 -0
  160. package/myReact/archive/testHH2.js +122 -0
  161. package/myReact/archive/testHH2.xml +79 -0
  162. package/myReact/archive/testHH3.js +130 -0
  163. package/myReact/archive/testHH3.xml +86 -0
  164. package/myReact/archive/testHHabort.js +121 -0
  165. package/myReact/archive/testHHabort.xml +83 -0
  166. package/myReact/archive/testMakeawait.js +202 -0
  167. package/myReact/archive/testRun1.js +168 -0
  168. package/myReact/archive/testRun1.xml +142 -0
  169. package/myReact/archive/titi.js +28 -0
  170. package/myReact/archive/titi.xml +110 -0
  171. package/myReact/archive/toto.js +73 -0
  172. package/myReact/archive/toto.xml +198 -0
  173. package/myReact/archive/trap-await-parallelNode.js +123 -0
  174. package/myReact/inutiles/hiver2022.xml +804 -0
  175. package/myReact/inutiles/hopeNode.xml +459 -0
  176. package/myReact/inutiles/mars2022.xml +871 -0
  177. package/myReact/inutiles/mystique1.xml +318 -0
  178. package/myReact/inutiles/mystiqueOSC.xml +277 -0
  179. package/myReact/inutiles/opus5Node.xml +1271 -0
  180. package/myReact/inutiles/opus5NodeLinux.xml +1241 -0
  181. package/myReact/inutiles/orchestrationHH.xml +541 -0
  182. package/myReact/inutiles/orchestrationHH2.xml +547 -0
  183. package/myReact/inutiles/testHH.xml +95 -0
  184. package/myReact/inutiles/trouveLaPercuTenor.xml +349 -0
  185. package/myReact/myReact.js +744 -0
  186. package/myReact/myReact.min.js +1 -0
  187. package/myReact/orchestrationHH.js +311 -0
  188. package/myReact/orchestrationHH.mjs +436 -0
  189. package/myReact/orchestrationHH.mjs.map +1 -0
  190. package/package.json +46 -0
  191. package/serveur/OSCandMidi.mjs +361 -0
  192. package/serveur/computeScore.mjs +415 -0
  193. package/serveur/controleDAW.mjs +1149 -0
  194. package/serveur/defaultSession.csv +2 -0
  195. package/serveur/defaultSkiniParametres.js +119 -0
  196. package/serveur/gameOSC.mjs +96 -0
  197. package/serveur/groupeClientsSons.mjs +1014 -0
  198. package/serveur/ipConfig.json +24 -0
  199. package/serveur/ipConfig127.json +19 -0
  200. package/serveur/ipConfig75.json +17 -0
  201. package/serveur/ipConfigBH.json +19 -0
  202. package/serveur/ipConfigLocal.json +19 -0
  203. package/serveur/midiConfig.json +26 -0
  204. package/serveur/midiConfigBH.json +26 -0
  205. package/serveur/midiConfigVoid.json +3 -0
  206. package/serveur/midimix.mjs +570 -0
  207. package/serveur/saveParam.mjs +159 -0
  208. package/serveur/skiniParametres.good.js +132 -0
  209. package/serveur/skiniParametres.js +106 -0
  210. package/serveur/utilsHHSkini.hh.js +64 -0
  211. package/serveur/utilsSkini.mjs +137 -0
  212. package/serveur/websocketServer.mjs +2052 -0
  213. package/serveur/workerInterfaceZ.mjs +327 -0
  214. package/serveur/workerSynchro.mjs +49 -0
  215. package/skini.mjs +141 -0
@@ -0,0 +1,570 @@
1
+ /**
2
+ * @fileOverview
3
+ * <H3> CONTROLE DEPUIS LES COMMANDES MIDI OU OSC </H3>
4
+ * <BR>Ce programme est utilisé:
5
+ * <BR>1) Dans le cas d'Ableton, pour recevoir et traiter les commandes OSC venant de Processing qui sert de pont MIDI.
6
+ * Processing reçoit le MIDI qui envoie ces données MIDI de façon assez brute: NoteOn, NoteOff et ControlChange.
7
+ * <BR>2) Dans le cas de Bitwig, pour traité les message OSC envoyé directement par le controleur Bitwig.
8
+ * <BR>3) Dans le cas de Bitwig ou ABleton, pour traiter les messages MIDI envoyés directement pas la DAW.
9
+ * <BR><BR>On peut émettre des signaux HipHop d'ici.
10
+ * <BR>Le port de réception des commandes OSC est portWebSocket de la config IP
11
+ * <BR>Remarque: la chaine peut être complexe pour MIDIMIX:
12
+ * <BR>MIDIMIX =(midi)=> Processing =(OSC)=> Serveur =(OSC)=> Processing (VISU)
13
+ * @copyright (C) 2018-2024 Bertrand Petit-Hédelin
14
+ *
15
+ * This program is free software: you can redistribute it and/or modify
16
+ * it under the terms of the GNU General Public License as published by
17
+ * the Free Software Foundation, either version 3 of the License, or
18
+ * any later version.
19
+ *
20
+ * This program is distributed in the hope that it will be useful,
21
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
+ * GNU General Public License for more details.
24
+ *
25
+ * You should have received a copy of the GNU General Public License
26
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
27
+ *
28
+ * @author Bertrand Petit-Hédelin <bertrand@hedelin.fr>
29
+ * @version 1.3
30
+ */
31
+ "use strict"
32
+ import { createRequire } from 'module';
33
+ const require = createRequire(import.meta.url);
34
+ import * as dgram from "dgram";
35
+
36
+ var debug = false;
37
+ var debug1 = true;
38
+
39
+ var param;
40
+ var synchroLink = false;
41
+ var linkReadyTostart = false;
42
+ var websocketServer;
43
+ var socketOpen = false;
44
+
45
+ var _setTempoLink, _initMidiIN;
46
+ export {
47
+ _setTempoLink as setTempoLink,
48
+ _initMidiIN as initMidiIN
49
+ };
50
+
51
+ /**
52
+ * Set the parameters
53
+ * @param {array} list of parameters
54
+ */
55
+ export function setParameters(parameters) {
56
+ param = parameters;
57
+ }
58
+
59
+ /**
60
+ * Set the websocket server module
61
+ * @param {object} module
62
+ */
63
+ export function setWebSocketServer(socketServer) {
64
+ websocketServer = socketServer;
65
+ }
66
+
67
+ /**
68
+ * Give the status of Ableton link
69
+ * true if activated
70
+ * @returns {boolean} status
71
+ */
72
+ export function getAbletonLinkStatus() {
73
+ return synchroLink;
74
+ }
75
+
76
+ /** @namespace midimix */
77
+ /**
78
+ * Process the MIDI and OSC messages received from the DAW to send it to the orchestration.
79
+ * @memberof midimix
80
+ * @param {object} machineServeur
81
+ */
82
+ export function midimix(machineServeur) {
83
+ var par = require('./ipConfig');
84
+ var osc = require('osc-min');
85
+ var sock = dgram.createSocket('udp4');
86
+ var midiConfig = require("./midiConfig.json");
87
+
88
+ var previousNote = 0;
89
+ var previousNotes = [0, 0, 0];
90
+ var previousChannel = 0;
91
+ var previousTimeStamp = 0;
92
+
93
+ var note;
94
+ var canal;
95
+ var timeStamp;
96
+ var noteSkini;
97
+ let link;
98
+
99
+ // Pour la synchro via Ableton Link.
100
+ if (param.synchroLink !== undefined) {
101
+ if (param.synchroLink) synchroLink = true;
102
+ }
103
+
104
+ if (synchroLink && !socketOpen) {
105
+ console.log("INFO: Synchro Ableton Link");
106
+ const abletonlink = require('abletonlink');
107
+ link = new abletonlink();
108
+ let localBeat = 0;
109
+ let instantBeat = 0;
110
+ let instantPhase = 0;
111
+
112
+ link.startUpdate(10, (beat, phase, bpm) => {
113
+ instantBeat = Math.round(beat);
114
+ instantPhase = Math.round(phase*100);
115
+
116
+ // On envoie un tick à chaque changement de beat.
117
+ // Ce serait peut-être mieux d'utiliser la phase ?
118
+ if (localBeat !== instantBeat) {
119
+ if (debug) console.log("midimix.js: Synchro Link ", Math.round(beat), Math.round(phase), Math.round(bpm));
120
+
121
+ // On a besoin de la phase pour synchroniser les départs.
122
+ // On commence à envoyer des Tick après avoir reçu la phase 1.
123
+ // La numérotation de la phase commence à 1 dans node et non à 0 comme sur PureData.
124
+ if(!linkReadyTostart){
125
+ if(instantPhase === 100){
126
+ linkReadyTostart = true;
127
+ if(debug1) console.log("INFO: midimix: link ready");
128
+ }
129
+ return;
130
+ }
131
+ localBeat = instantBeat;
132
+ websocketServer.sendOSCTick();
133
+ }
134
+ });
135
+ }
136
+
137
+ /**
138
+ * To set the tempo when synchro using Ableton Link
139
+ * @function
140
+ * @param {number} tempo
141
+ * @memberof midimix
142
+ * @inner
143
+ */
144
+ function setTempoLink(tempo) {
145
+ if (link !== undefined) {
146
+ link.bpm = tempo;
147
+ if(debug) console.log("INFO: midimix.js: setTempolink:", tempo);
148
+ }
149
+ }
150
+ _setTempoLink = setTempoLink;
151
+
152
+ // Pour la synchro MIDI
153
+ var synchroMidi = false;
154
+ if (param.synchoOnMidiClock !== undefined) {
155
+ if (param.synchoOnMidiClock) synchroMidi = true;
156
+ }
157
+
158
+ // Pour commande direct de Skini en MIDI sans passer par une passerèle ====================
159
+ // Par défaut on communique en OSC avec la DAW ou la passerèle
160
+ var directMidi = false;
161
+ if (param.directMidiON !== undefined) {
162
+ if (param.directMidiON) directMidi = true;
163
+ }
164
+
165
+ if (synchroMidi && synchroLink) console.log("WARN: Two synchronisations activated MIDI and Link");
166
+
167
+ if (debug) console.log("========= directMidi dans midimix:", directMidi);
168
+
169
+ if (directMidi && midiConfig[0] !== undefined ) {
170
+ // Le require est fait ici car on doit pouvoir fonctionner en OSC sans MIDI du tout
171
+ // midi-node est dépendant de l'OS. Il faut installer le bon npm.
172
+ var midi = require('midi');
173
+
174
+ var midiInput = new midi.Input();
175
+ var midiSync = new midi.Input();
176
+
177
+ // Les controleurs
178
+ var controlers = [];
179
+ var controlerIndex;
180
+ var midiPortSync;
181
+ var midiPortClipFromDAW;
182
+ var tempoTickDuration = 0;
183
+
184
+ /**
185
+ * Update the list of MIDI controlers according the MIDI configuration file.
186
+ * @function
187
+ * @memberof midimix
188
+ * @inner
189
+ */
190
+ function getMidiPortControlers() {
191
+ for (var i = 0; i < midiConfig.length; i++) {
192
+ if (midiConfig[i].spec === "controler") {
193
+ var input = new midi.Input();
194
+ var controler = {
195
+ "input": input,
196
+ "name": midiConfig[i].name
197
+ }
198
+ controlers.push(controler);
199
+
200
+ if (debug) console.log("getMidiPortControlers: Midi" +
201
+ midiConfig[i].type + ", usage:" + midiConfig[i].spec +
202
+ ", bus: " + midiConfig[i].name + ", " + midiConfig[i].comment, controlers);
203
+ }
204
+ }
205
+ }
206
+
207
+ /**
208
+ * Get the index of a MIDI controler in te list of MIDI controlers
209
+ * of the MIDI configuration file.
210
+ * @function
211
+ * @memberof midimix
212
+ * @param {string} Midi port name
213
+ * @return {number} index
214
+ * @inner
215
+ */
216
+ function getControlerIndex(portName) {
217
+ for (var j = 0; j < midiInput.getPortCount(); ++j) {
218
+ if (midiInput.getPortName(j) === portName) {
219
+ if (debug) console.log("getControlerIndex: Midi", j);
220
+ return j;
221
+ }
222
+ }
223
+ return -1;
224
+ }
225
+
226
+ /**
227
+ * To process MIDI message comming from the MIDI controlers.
228
+ * @function
229
+ * @memberof midimix
230
+ * @inner
231
+ */
232
+ function createControlerMessageOn() {
233
+ for (var i = 0; i < controlers.length; i++) {
234
+ controlerIndex = getControlerIndex(controlers[i].name);
235
+ if (controlerIndex === -1) {
236
+ console.log("WARN: controler :", controlers[i].name, " does not exist");
237
+ continue;
238
+ }
239
+ controlers[i].input.openPort(controlerIndex);
240
+ controlers[i].input.ignoreTypes(false, false, false);
241
+ if (debug) console.log("create Controler listener : ",
242
+ controlers[i].input.getPortName(controlerIndex));
243
+
244
+ controlers[i].input.on('message', function (deltaTime, message) {
245
+ if (debug1) console.log('midimix.js: Input received : ' + message + ' d:' + deltaTime);
246
+
247
+ // Ici les actions sur commande MIDI
248
+ // On ne distingue pas les controleurs.
249
+
250
+ });
251
+ controlerIndex++;
252
+ }
253
+ }
254
+
255
+ /**
256
+ * Get the MIDI port used by the DAW for receiving the clips (patterns)
257
+ * command from Skini.
258
+ * @function
259
+ * @memberof midimix
260
+ * @return {number} index of the MIDI port
261
+ * @inner
262
+ */
263
+ function getMidiPortForClipFromDAW() {
264
+ for (var i = 0; i < midiConfig.length; i++) {
265
+ if (midiConfig[i].spec === "clipFromDAW") {
266
+ for (var j = 0; j < midiInput.getPortCount(); ++j) {
267
+ if (midiInput.getPortName(j) === midiConfig[i].name) {
268
+ if (debug) console.log("getPortForClipFromDAW: Midi" +
269
+ midiConfig[i].type + ", usage:" + midiConfig[i].spec +
270
+ ", bus: " + midiConfig[i].name + ", " + midiConfig[i].comment);
271
+ return j;
272
+ }
273
+ }
274
+ }
275
+ }
276
+ console.log("ERR: getPortForClipFromDAW: no Midi port for receiving from DAW");
277
+ return -1;
278
+ }
279
+
280
+ /**
281
+ * Get the MIDI port used by the DAW for sending the MIDI synchro.
282
+ * @function
283
+ * @memberof midimix
284
+ * @return {number} index of the MIDI port
285
+ * @inner
286
+ */
287
+ function getMidiPortForSyncFromDAW() {
288
+ for (var i = 0; i < midiConfig.length; i++) {
289
+ if (midiConfig[i].spec === "syncFromDAW") {
290
+ for (var j = 0; j < midiInput.getPortCount(); ++j) {
291
+ if (midiSync.getPortName(j) === midiConfig[i].name) {
292
+ if (debug) console.log("getMidiPortForSyncFromDAW: Midi" +
293
+ midiConfig[i].type + ", usage:" + midiConfig[i].spec +
294
+ ", bus: " + midiConfig[i].name + ", " + midiConfig[i].comment);
295
+ return j;
296
+ }
297
+ }
298
+ }
299
+ }
300
+ console.log("ERR: getMidiPortForSyncFromDAW: no Midi port for receiving sync from DAW");
301
+ return -1;
302
+ }
303
+
304
+ /**
305
+ * Initialize the MIDI ports for processing the MIDI messages/commands from DAW and
306
+ * controlers.
307
+ * Put two MIDI listeners one on NoteOn and one on Synchro.
308
+ * @function
309
+ * @memberof midimix
310
+ * @inner
311
+ */
312
+ function initMidiIN() {
313
+ midiPortSync = getMidiPortForSyncFromDAW();
314
+ midiPortClipFromDAW = getMidiPortForClipFromDAW();
315
+
316
+ getMidiPortControlers();
317
+ createControlerMessageOn();
318
+
319
+ midiInput.openPort(midiPortClipFromDAW);
320
+ midiInput.ignoreTypes(false, true, false);
321
+ //console.log("ClipToDaw: ", midiPortClipFromDAW, midiInput.getPortName(midiPortClipFromDAW));
322
+
323
+ midiSync.openPort(midiPortSync);
324
+ midiSync.ignoreTypes(false, false, false);
325
+ //console.log("midiSync: ", midiPortSync, midiSync.getPortName(midiPortSync));
326
+
327
+ // Traitement des commande Midi reçues d'Ableton Live
328
+ // pour les patterns lancés.
329
+ midiInput.on('message', function (deltaTime, message) {
330
+ // On ne traite que les noteON, de 1001 0000 (144) à 1001 1111 (159)
331
+ if (message[0] >= 144 && message[0] <= 159) {
332
+ if (debug) console.log('midimix.js: initMidiIN: Input recieved :' + message + ' d:' + deltaTime);
333
+ note = message[1];
334
+ canal = message[0] - 144;
335
+ //timeStamp = deltaTime;
336
+
337
+ // Ableton envoie les commandes MIDI en comptant depuis le canal 1 (et pas 0 comme d'autres contrôleurs)
338
+ // Il faut donc faire attention à la gestion des canaux MIDI en fonction du contrôleur.
339
+ noteSkini = note + (canal - 1) * 127;
340
+
341
+ // Ableton répéte 1 fois le message NoteON une première fois (deux envois) avec un léger décalage temporel.
342
+ // Si le pattern tourne, et qu'il est activé, Ableton envoie 4 commandes MIDI noteON avec le même timestamp.
343
+ // Le timestamp est proche de la micro-seconde.
344
+ if (isInPreviousNotes(noteSkini) && Math.round(deltaTime) === 0) {
345
+ //if (isInPreviousNotes(noteSkini) && previousTimeStamp === Math.round(timeStamp)){ // à peu près une seconde
346
+ if (debug) console.log("midimix.js: REPETITION : ", noteSkini, timeStamp, previousTimeStamp);
347
+ } else {
348
+ //previousTimeStamp = Math.round(timeStamp);
349
+
350
+ if (debug) console.log("midimix.js: noteSkini: ", noteSkini, note, canal);
351
+ if (debug) console.log("midimix.js: isInPreviousNotes:", isInPreviousNotes(noteSkini));
352
+
353
+ // Avec PUSH branché, Ableton Live envoie des notes négatives...
354
+ // dont je ne connais pas la signification
355
+ if (noteSkini > 0) {
356
+ insertInPreviousNotes(noteSkini);
357
+ if (debug) console.log("midimix.js: Note de pattern reçue d'Ableton:", noteSkini);
358
+ websocketServer.sendSignalFromDAW(noteSkini);
359
+ }
360
+ }
361
+ }
362
+ });
363
+
364
+ // Traitement des messages de synchro Midi (24 messages pour une noire)
365
+ let v0 = 0;
366
+ midiSync.on('message', function (deltaTime, message) {
367
+ tempoTickDuration++;
368
+ if (message[0] === 248) {
369
+ if (tempoTickDuration > 23) {
370
+ if (debug) console.log("midimix.js: midiSync.on:", Date.now() - v0, "ms");
371
+ //console.log('Sync recieved :' + message + ' d:' + deltaTime);
372
+ if (debug) console.log("midimix 1 : Tick", message[0]);
373
+ // Test pour éviter une "double synchro en OSC est en MIDI"
374
+ if (synchroMidi) {
375
+ websocketServer.sendOSCTick();
376
+ }
377
+ tempoTickDuration = 0;
378
+ if (debug) { v0 = Date.now(); }
379
+ }
380
+ }
381
+ });
382
+ }
383
+ _initMidiIN = initMidiIN;
384
+
385
+ initMidiIN();
386
+ } // Fin fonction si MIDI
387
+
388
+ /**
389
+ * Insert a node in the table previousNotes[] which is used
390
+ * to process the MIDI message send by Ableton Live.
391
+ * Ableton repeats the NoteON message once (two times) with a slight time delay.
392
+ * If the pattern is running, and it is activated, Ableton sends 4 MIDI noteON commands with the same timestamp.
393
+ * The timestamp is close to the micro-second.
394
+ * @function
395
+ * @memberof midimix
396
+ * @param {number} Skini Note
397
+ * @inner
398
+ */
399
+ function insertInPreviousNotes(laNote) {
400
+ for (var i = 1; i < previousNotes.length; i++) {
401
+ previousNotes[i - 1] = previousNotes[i];
402
+ }
403
+ previousNotes[previousNotes.length - 1] = laNote;
404
+ if (debug) console.log("midimix: insInPreviousNote: ", previousNotes);
405
+ };
406
+
407
+ /**
408
+ * Check if the Skini Note is in the previousNotes table.
409
+ * to process the MIDI message send by Ableton Live.
410
+ * @function
411
+ * @memberof midimix
412
+ * @param {number} Skini Note
413
+ * @inner
414
+ */
415
+ function isInPreviousNotes(laNote) {
416
+ for (var i = 0; i < previousNotes.length; i++) {
417
+ if (previousNotes[i] === laNote) return true;
418
+ }
419
+ return false;
420
+ };
421
+
422
+ /**
423
+ * Management of the UDP socket for OSC and OSC messages.
424
+ * @function
425
+ * @memberof midimix
426
+ * @param {number} Skini Note
427
+ * @inner
428
+ */
429
+ sock.close();
430
+
431
+ sock = dgram.createSocket("udp4", function (msg, rinfo) {
432
+ var error, message;
433
+ try {
434
+ message = osc.fromBuffer(msg); // Message OSC recu
435
+ //msgloc.type = message.address;
436
+ //msgloc.value1 = message.args[0].value; // C'est compliqué le parsing OSC
437
+ //ws.send(JSON.stringify(msgloc)); // Pas utile pour le moment
438
+ if (debug) {
439
+ console.log("midimix.js: socket reçoit OSC: [", message.address + " : " + message.args[0].value, "]");
440
+ }
441
+ switch (message.address) {
442
+
443
+ case "/AkaiControlerChange": // Emission des signaux en fonction des CC reçus
444
+ switch (message.args[0].value) {
445
+ case 62: // Ce CC de MIDIMIX est suivi de la configuration complète de la table...
446
+ machineServeur.inputAndReact("scene", 4); // Pour démo, pas utilisable en l'état
447
+ break;
448
+ default:
449
+ return;
450
+ }
451
+ break;
452
+
453
+ case "/AkaiNoteOff":
454
+ if (debug) console.log("midimix.js: Commande NoteOFF OSC:", message.args[0].value);
455
+ break;
456
+
457
+ case "/nanoKEY2NoteOff":
458
+ if (debug) console.log("midimix.js: Commande NoteOFF OSC:", message.args[0].value);
459
+ break;
460
+
461
+ case "/AbletonNoteOn":
462
+ case "/BitwigNoteOn":
463
+ case "/AkaiNoteOn": // Emission des signaux en fonction des notes Midi reçues
464
+ case "/nanoKEY2NoteOn":
465
+ if (debug) console.log("midimix.js: Commande NoteON OSC:", message.args[0].value);
466
+ switch (message.args[0].value) {
467
+
468
+ case 25:
469
+ websocketServer.sendSignalStartFromMIDI();
470
+ break;
471
+
472
+ case 26:
473
+ websocketServer.sendSignalStopFromMIDI();
474
+ break;
475
+
476
+ default:
477
+ websocketServer.sendSignalFromMIDI(message.args[0].value);
478
+ break;
479
+ }
480
+ break;
481
+
482
+ case "/MPK25NoteOn":
483
+ case "/Session1NoteOn":
484
+ break;
485
+
486
+ // Traitement des commandes MIDI reçues d'Ableton lorsqu'un clip est lancé.
487
+ // C'est un mécanisme utilisé pour traiter des "patterns pivots", cad qui peuvent être utilisés
488
+ // dans l'orchestration comme événements.
489
+ // Il y a ici un filtrage un peu particulier lié à la façon dont Ableton envoie les commandes MIDI
490
+ // à l'activation d'un clip.
491
+ case "/StartClipNoteOn":
492
+ note = parseInt(message.args[0].value);
493
+ canal = parseInt(message.args[1].value);
494
+ timeStamp = parseFloat(message.args[2].value); // String car pb avec les Floats
495
+ // Ableton envoie les commandes MIDI en comptant depuis le canal 1 (et pas 0 comme d'autres contrôleurs)
496
+ // Il faut donc faire attention à la gestion des canaux MIDI en fonction du contrôleur.
497
+ noteSkini = note + (canal - 1) * 127;
498
+
499
+ // Ableton répéte 1 fois le message NoteON une première fois (deux envois) avec un léger décalage temporel.
500
+ // Si le pattern tourne, et qu'il est activé, Ableton envoie 4 commandes MIDI noteON avec le même timestamp.
501
+ // En divisant le timestamp par 1 000 000, on est proche de la seconde. Le timestamp est proche de la micro-seconde.
502
+ if (isInPreviousNotes(noteSkini) && previousTimeStamp === Math.round(timeStamp / 1000000)) { // à peu près une seconde
503
+ if (debug) console.log("midimix.js: REPETITION : ", noteSkini, timeStamp, previousTimeStamp);
504
+ break;
505
+ }
506
+
507
+ previousTimeStamp = Math.round(timeStamp / 1000000);
508
+
509
+ if (debug) {
510
+ console.log("midimix.js: socket reçoit OSC: [", message.address + " : " +
511
+ message.args[0].value,
512
+ +message.args[1].value,
513
+ +message.args[2].value,
514
+ "]");
515
+ }
516
+
517
+ if (debug) console.log("midimix.js: noteSkini: ", noteSkini, note, canal);
518
+ if (debug) console.log("isInPreviousNotes:", isInPreviousNotes(noteSkini));
519
+
520
+ // Avec PUSH branché, Ableton Live envoie des notes négatives...
521
+ // dont je ne connais pas la signification
522
+ if (noteSkini > 0) {
523
+ insertInPreviousNotes(noteSkini);
524
+ websocketServer.sendSignalFromDAW(noteSkini);
525
+ }
526
+
527
+ break;
528
+
529
+ case "/StopClipNoteOff":
530
+ break;
531
+
532
+ case "/ClipControlerChange":
533
+ if (debug) console.log("Valeur du CC=", message.args[1].value);
534
+ break;
535
+
536
+ case "/videoNoteOn":
537
+ websocketServer.sendSignalFromMidiMix(message.args[0].value);
538
+ break;
539
+
540
+ case "/AbletonTick":
541
+ case "/BitwigTick":
542
+ if (debug) console.log("midimix 2: bitwig tick: ", message.args[0].value);
543
+ // Test pour éviter une "double synchro en OSC et en MIDI ou Link, si on oublie
544
+ // de désactiver l'une ou l'autre dans la DAW.
545
+ if (!synchroMidi && !synchroLink) {
546
+ websocketServer.sendOSCTick();
547
+ }
548
+ break;
549
+
550
+ default:
551
+ console.log("midimix.js: socket reçoit OSC: [", message.address + " : " + (message.args[0].value), "]");
552
+ break;
553
+ }
554
+ return; // console.log(osc.fromBuffer(msg));
555
+ } catch (error) {
556
+ console.log("midimix.js: ERR dans réception OSC :", message.args, error);
557
+ return;
558
+ }
559
+ });
560
+
561
+ sock.on('listening', function () {
562
+ var address = sock.address();
563
+ if (debug1) console.log('INFO: midimix.js: UDP Server listening on ' + address.address + ":" + address.port);
564
+ });
565
+
566
+ if (!socketOpen) {
567
+ sock.bind(par.InPortOSCMIDIfromDAW, par.serverIPAddress);
568
+ socketOpen = true;
569
+ }
570
+ }