From 0f68a377dacac90ec0af07c75346ff2531694026 Mon Sep 17 00:00:00 2001 From: Dooho Yi Date: Thu, 9 Jul 2020 18:26:07 +0900 Subject: [PATCH] new init 3 --- .gitignore | 4 + .tern-port | 1 - index.js | 65 +- package-lock.json | 2 +- package.json | 2 +- public/sample/.tern-port | 1 - public/sample/audio/{고요1.mp3 => 01.mp3} | Bin public/sample/audio/{고요10.mp3 => 02.mp3} | Bin public/sample/audio/{고요11.mp3 => 03.mp3} | Bin public/sample/audio/{고요12.mp3 => 04.mp3} | Bin public/sample/audio/{고요13.mp3 => 05.mp3} | Bin public/sample/audio/{고요14.mp3 => 06.mp3} | Bin public/sample/audio/{고요2.mp3 => 07.mp3} | Bin public/sample/audio/고요3.mp3 | Bin 10588 -> 0 bytes public/sample/audio/고요4.mp3 | Bin 10588 -> 0 bytes public/sample/audio/고요5.mp3 | Bin 10588 -> 0 bytes public/sample/audio/고요6.mp3 | Bin 10588 -> 0 bytes public/sample/audio/고요7.mp3 | Bin 10588 -> 0 bytes public/sample/audio/고요8.mp3 | Bin 10588 -> 0 bytes public/sample/audio/고요9.mp3 | Bin 10588 -> 0 bytes public/sample/imgs/logo.png | Bin 0 -> 113154 bytes public/sample/index.js | 579 +- public/sample/lib/nexus-ui.js | 9369 ++++++++++++++++++ receiver/package-lock.json | 1494 --- receiver/package.json | 21 - receiver/receiver.js | 169 - 26 files changed, 9480 insertions(+), 2227 deletions(-) delete mode 100644 .tern-port delete mode 100644 public/sample/.tern-port rename public/sample/audio/{고요1.mp3 => 01.mp3} (100%) rename public/sample/audio/{고요10.mp3 => 02.mp3} (100%) rename public/sample/audio/{고요11.mp3 => 03.mp3} (100%) rename public/sample/audio/{고요12.mp3 => 04.mp3} (100%) rename public/sample/audio/{고요13.mp3 => 05.mp3} (100%) rename public/sample/audio/{고요14.mp3 => 06.mp3} (100%) rename public/sample/audio/{고요2.mp3 => 07.mp3} (100%) delete mode 100644 public/sample/audio/고요3.mp3 delete mode 100644 public/sample/audio/고요4.mp3 delete mode 100644 public/sample/audio/고요5.mp3 delete mode 100644 public/sample/audio/고요6.mp3 delete mode 100644 public/sample/audio/고요7.mp3 delete mode 100644 public/sample/audio/고요8.mp3 delete mode 100644 public/sample/audio/고요9.mp3 create mode 100644 public/sample/imgs/logo.png create mode 100644 public/sample/lib/nexus-ui.js delete mode 100644 receiver/package-lock.json delete mode 100644 receiver/package.json delete mode 100644 receiver/receiver.js diff --git a/.gitignore b/.gitignore index 598ed88..1ac55a2 100644 --- a/.gitignore +++ b/.gitignore @@ -62,3 +62,7 @@ typings/ #osx .DS_Store + +#atom +.tern-project +.tern-port diff --git a/.tern-port b/.tern-port deleted file mode 100644 index e3615ea..0000000 --- a/.tern-port +++ /dev/null @@ -1 +0,0 @@ -42697 \ No newline at end of file diff --git a/index.js b/index.js index e2d9ccb..993b63c 100644 --- a/index.js +++ b/index.js @@ -1,56 +1,14 @@ -//NOTE: SERVER CONFIGURATION has 2 options. ENABLE 1 of 2 options - -// //NOTE: option (1) - https server (443) + redirection 80 to 443 -// -// //prepare credentials & etc -// var fs = require('fs'); -// var https = require('https'); -// var privateKey = fs.readFileSync('/etc/letsencrypt/live/choir.run/privkey.pem', 'utf8'); -// var certificate = fs.readFileSync('/etc/letsencrypt/live/choir.run/fullchain.pem', 'utf8'); -// var credentials = { -// key: privateKey, -// cert: certificate -// }; -// -// //https WWW server @ port 443 -// var express = require('express'); -// var app = express(); -// var httpsWebServer = https.createServer(credentials, app).listen(443, function() { -// console.log('[express] listening on *:443'); -// }); -// -// //http Redirection server @ port 80 -// // ==> Don't get why this works.. all others not. ==> https://stackoverflow.com/a/23283173 -// var http = require('http'); -// var httpApp = express(); -// var httpRouter = express.Router(); -// httpApp.use('*', httpRouter); -// httpRouter.get('*', function(req, res) { -// var host = req.get('Host'); -// // replace the port in the host -// host = host.replace(/:\d+$/, ":" + app.get('port')); -// // determine the redirect destination -// var destination = ['https://', host, req.url].join(''); -// return res.redirect(destination); -// }); -// var httpServer = http.createServer(httpApp); -// httpServer.listen(80); -// -// //https socket.io server @ port 443 (same port as WWW service) -// var io = require('socket.io')(httpsWebServer, { -// 'pingInterval': 1000, -// 'pingTimeout': 3000 -// }); - -//NOTE: option (2) - simple http dev server (8080) - +//NOTE: SERVER CONFIGURATION for heroku.. var http = require('http'); var express = require('express'); var app = express(); var httpServer = http.createServer(app); -httpServer.listen(process.env.PORT || 8080); +httpServer.listen(process.env.PORT || 5000); +// heroku will auto-assign a port number: process.env.PORT +// heroku local will serve the app @ port == 5000, by default (this is heroku's preference) +// regular node index.js will serve the app @ port == 5000, as description above. -//http socket.io server @ port 8080 (same port as WWW service) +//http socket.io server (same port as WWW service) var io = require('socket.io')(httpServer, { 'pingInterval': 1000, 'pingTimeout': 3000 @@ -78,17 +36,6 @@ io.on('connection', function(socket) { console.log('sound.group :' + sound.group); }); - //on 'pan' - socket.on('pan', function(pan) { - - //relay the message to everybody EXCEPT the sender - socket.broadcast.emit('pan', pan); - - //DEBUG - console.log('pan.width :' + pan.width); - console.log('pan.speed :' + pan.speed); - }); - //on 'clap' --> relay the message to everybody INCLUDING sender socket.on('clap', function(clap) { diff --git a/package-lock.json b/package-lock.json index 1af6026..65ac358 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "scroll-link-server", + "name": "sound-mixing-bowl-server", "version": "1.0.0", "lockfileVersion": 1, "requires": true, diff --git a/package.json b/package.json index c550f28..8569a8e 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "scroll-link-server", + "name": "sound-mixing-bowl-server", "version": "1.0.0", "description": "", "main": "app.js", diff --git a/public/sample/.tern-port b/public/sample/.tern-port deleted file mode 100644 index 59b3b77..0000000 --- a/public/sample/.tern-port +++ /dev/null @@ -1 +0,0 @@ -42761 \ No newline at end of file diff --git a/public/sample/audio/고요1.mp3 b/public/sample/audio/01.mp3 similarity index 100% rename from public/sample/audio/고요1.mp3 rename to public/sample/audio/01.mp3 diff --git a/public/sample/audio/고요10.mp3 b/public/sample/audio/02.mp3 similarity index 100% rename from public/sample/audio/고요10.mp3 rename to public/sample/audio/02.mp3 diff --git a/public/sample/audio/고요11.mp3 b/public/sample/audio/03.mp3 similarity index 100% rename from public/sample/audio/고요11.mp3 rename to public/sample/audio/03.mp3 diff --git a/public/sample/audio/고요12.mp3 b/public/sample/audio/04.mp3 similarity index 100% rename from public/sample/audio/고요12.mp3 rename to public/sample/audio/04.mp3 diff --git a/public/sample/audio/고요13.mp3 b/public/sample/audio/05.mp3 similarity index 100% rename from public/sample/audio/고요13.mp3 rename to public/sample/audio/05.mp3 diff --git a/public/sample/audio/고요14.mp3 b/public/sample/audio/06.mp3 similarity index 100% rename from public/sample/audio/고요14.mp3 rename to public/sample/audio/06.mp3 diff --git a/public/sample/audio/고요2.mp3 b/public/sample/audio/07.mp3 similarity index 100% rename from public/sample/audio/고요2.mp3 rename to public/sample/audio/07.mp3 diff --git a/public/sample/audio/고요3.mp3 b/public/sample/audio/고요3.mp3 deleted file mode 100644 index ee6bc3e5d02b038902559530fc8d9a53c806dbc9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10588 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 L4UqibQ0spHQ7TFD diff --git a/public/sample/audio/고요4.mp3 b/public/sample/audio/고요4.mp3 deleted file mode 100644 index ee6bc3e5d02b038902559530fc8d9a53c806dbc9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10588 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 L4UqibQ0spHQ7TFD diff --git a/public/sample/audio/고요5.mp3 b/public/sample/audio/고요5.mp3 deleted file mode 100644 index ee6bc3e5d02b038902559530fc8d9a53c806dbc9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10588 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 L4UqibQ0spHQ7TFD diff --git a/public/sample/audio/고요6.mp3 b/public/sample/audio/고요6.mp3 deleted file mode 100644 index ee6bc3e5d02b038902559530fc8d9a53c806dbc9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10588 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 L4UqibQ0spHQ7TFD diff --git a/public/sample/audio/고요7.mp3 b/public/sample/audio/고요7.mp3 deleted file mode 100644 index ee6bc3e5d02b038902559530fc8d9a53c806dbc9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10588 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 L4UqibQ0spHQ7TFD diff --git a/public/sample/audio/고요8.mp3 b/public/sample/audio/고요8.mp3 deleted file mode 100644 index ee6bc3e5d02b038902559530fc8d9a53c806dbc9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10588 zcmdsdXHXPvv}O-E=P)G6I1E8@5|A*!5F}?wk|ijTgG2#`AW4KlK+=GKAP9&bNdXZ_ zl0gs=Mvx?mNKz1bd-(3%+J9TOcI$4{cGcAU=sxdz-se0gc7rEb?!f=%vb}NB3wnee z`XK;7)B&KUXJzH$;t~)*AP|=>$;->Ds%mLz>Fb-Cnp#^sIy$GFJ|WUOR{_{EK@Sv3fyRH{`2Y4FJZVG$bkKQY;{bpH zvcgXQfRRSyFSwAzQgn2#i~yO-4`FAwKg4H`f2YMv@(a+#UIPEUzGbOWoH{iBHhdv* zjQij}sK+74D^4sC_E+46Q&;2RAcFRWZsu#+ww!+-ADdohTKX1YQsQ>^UG6;xao2H< zN&xnXc-ZswK?N1P_&->opL+>(l6}NUaE_u1NN8iebv24@+aV61_2wlka**jdY?5do zhtz2c<*WNskyvV~sv({U-SG{U$S5&?YFesG!eXa1$DO7r%;Zl8r{ z-#fGZieoBnO~>@wdnyI`<%@_J4e{8J_lJf{E&zYVa2ek|e`qqem27c{EHB_m?{XW6 zc@_ETH9;0UGQNuQ(v6K0?wN7YZ5gffwBQktK?3SDZM;IdpShZqHDr|1mzX8jZx4$$ zlt2O}!^6_B-0So_zz?pYk3NRV#NWk7S0D88(7hMgaE&8=1D*w5DH`2nbr@8QPkti# zfv^i`_xKVv!Shp#AVXC`YN|^Dyq7a|h{A=DsIM`V(q`IT;Bzi*9xO+Ji3;W2UNZPz zQ-UCM=&-k_ygiVRd2PfhvAvKe5Ur$l5#YN~%I97>_7faAcHGj2nYi^TPo?lMpdJW* zB?x_8YOmI}4e=-QN@kgrE&5n7BXJMz#cC8!Ohp9W0xr=v#UA2nXCrf5T0AWbzFKs? zMMW-}_{2h@CpOv_y*{PdG#7t*8>{@_2#w8f_6zn^Vl=Af3!mP7Ag=_F!+E+?lOLDE z=k2W~d}W?;IOdB_PH@PBC#I-B8F+bFeJqSU?$RSE!U-k;We z^Iw@07t{_tekf9x0jAh3Z=y5_2>#Zs*@Oeod1lqz(2xfiWZp~JeH^qfU-x5;84PNB zX;U6Gs93=fMgmYJ4E_cEF=H(~@rYK`dXSAulR=ZT-now*ew!*-in0=~e&#V*X0d2e z9+1V~I5d)Iy9UxZMM~;$mkg}MUG(N75z!A{H>V;e9N|xix~C__*&1>0rJJF;B>yPv zH)!<}+Yaz+kepo@ZtJL-QO_*1txM7Rr_FTV8rkI4f!?_V$(?J1fQlYGLjhUA6GUkJf0`dr>++$ZWM30@{EG_|1|blBW#A7Y z`Wc86dsTPPQ-Jnw@_0O_3q>qNy|OzEkhW~77|0{oc;{KGR^#24KpCmyovby9Zom$x zm7Qu&?HD=!HmsatAr^f@D-W|h81;m(Hh3Ie_44wV&F8K?QZsm~tA(H?b-_KdnrgWP zdBh`;hKdS@EoIEG9amI7isjGD4DMX$TLo`t!?EDu>bxaC%X@?vwJh8r&mw7FW5mZ* z23=4dlDil;KBdDc&8KaxER!%!4tSYRu8MbDCY;%6K3;+`(p761t zDtx&2{2zYL=YM;OSR1aKZ}K-@wr}2!QTmRs2`1gcrKOLb0K#qt{$sc<7Gi=T9mN+2 zg#O}nP7NrQ{!m?^fYIZxGioy^0o>{IhlfaioybqgP4Lx8`{tVJc*h^jEJMF!o-6)~ zD)=&F_PfX+c0Urh9J(8bv?FWl)`Ggo_%o#qMnkT#;B1AG8YuyF+Q|=V3O-TUZX9m7JQjY<~+ov$5v(JkInK$>FI|mNWu<#v9Cg{E!`s+ z^QHw1G3;0*j$5F>G`;jqoRSv>BL|Q$&8v8oVIZ~s1?@&qUh~6|w;IF9_8W4A1Smjo zXX*1>>w)cil>35iuLc<9i<4;`ld>8;mwBBHcW%B|@YuPrs>2$@k(HCRwWVi55LvkS z@s}{;C~mf@&Yh~R+FN~HP#slD_oX*(PUcTM`X~L*)RhQs`#C;SP$*0dWi=}JAG>hPLCS8OcgBV@L$;7C+cGI z+)O;ak2KYXSNTo%6lWJwk_;Z3jA_!A37o}Rx;Kdqko2P1tORtt&YZ!~*d0Y&u8vC( ziMe?2p_k$HhivhEbU33uI}@ZlISOwec5(Cyy>5)DNVBJDZ^pPOEhCvZ?F`{Cf7=S~ zR2I!YWWV8*ZeKSpb$@HUo(-n!m?_G5#$bGm+c#}zjJTr%XGknTp zM~$+o&Cbq#R{JD4MDIL;e10ojhf>b44AZ_)Wg4dTO?EcVkxb=+%kmGi?)95k6n9hM zfm~L`VHeoh6# z!^G;wrdYdV+(8XyIJ#(m=jafUgRbL8b+sd_!b-SRJsTa33UcXSS1O8sqB%^shzA+v zDkePt{{80mi-TocXfHj}`CKHpDRgUd;7h-`*vK1}A58BoDv|;;F|rk;h)MJc@$pnl zx`o=@Td#YT&bmR1k9ItiSrNyw1j)0plS}Q6#_!Q6ne<}ylu*l=#7tE#5I}$eV_K*l7GMdK=Q~gN6vCTq8Wc+~Ky}3k zO8JE4JEAk4hW*9nwhvDV+9sYx)Sz%m#+_Z8q8j}I=>TaKUAbt4;=4OmzuHHB`}N1V zxf{^rPR<5;aYB^~_V>2u4=x8vx?419LML2 z*?FzP{^ugwEm3wn7wRfM4Y^5$YWbe9=rYB3-`#1aMsqgG0K-S|lByuV9p-jGaHaow?+YIKm*AEL zKnbTueUPpC(SOZ29W!)cDCIWY+gf3jE0OllgOH!ubf_8nhMJ^YS_^L(#VfkT$5misohGt{7dZ7{`|+mjwML$R5Wxi@cG=) z4aaPwz)NeD#Y|O|Txg0eL~!Hh_@sDM36BCXBmnbIn84hcANs}&{g!a<#ES)OPIf_n8EoPN#T;HkF{bj0uH%sOpcG0o}bYcf?* zV&cqhtxv!Gj^aKUTM2lUdO@0^96?J;5_biR@dL=Rn4+Zb>&#Qt6VrBI-WO_rtM#R- zdki=A`aDIRWZ*lXIsvBGt3ab~0k|HJN6&LY6(a|E=a&H(7k+cw%8lrr5KwdW^0OI~ z!Lu$A6#Z2=n;rG$Df$l`6 z31uyVYWwp@3og~0yvVGFslC1%l*szSHb|v7vQ%hpJ%hoVuG6mLh;mZCE09NN)qabokntP9p zf`yR>UOuE$VN9H_lXI)y0E|7EOs2SS^*c$Dj?ctN^}sjHQ5!A-v$r$wF~Be(#)++` zXafR!WVtW|f!VLhzC!NZC$ur7!%W(fBGS9_M=sgTG&ohq3DRuim4%8nxMBpaR(ULC z3AoCRb5H|FSNKg&zGN(V&>xLCrylt5c141ZwhoL**3{H|_o@a*Vrs5Fk#XQZYN?RI z)Ps~P+4j1N7IjLpGKQsF0@{>vbbt26+m^s1%Ljg%>xG?-BrcZB2QzW35AN6kWUUZw zATEkN_Y;haPuTIfF4Va|+7JcT@z#5~pi?08G>XIr&P$a>sl84C?#;-DYGks19m}ym zl4MsEx!V}4AW9QSRBaV1O2C5`zGxY$v8x25p3>p9lno)HVvyULL4d#kDV|mYO8I=9 za>7PH+VqQrud(KTo_=>s=aqHHx-ao@WQXCYQu>^=?HjV~ma*wa1G9#K1kDb>otf=0 zy88hs)NH%g>ny;KJmEYoEdFn-|2l~SoG+I z&1r=(;trWgX4qL4z-0~oxiIpCpPP*J1_w`?$=t2&Kc)rcbRCt>>E?*e+a+ z-JYv#FZ5=T-P5uCg)=|VcdnP9@N%59E*sZHycsem8IOg^ovqY+JdTX!Ig#HM>nTnJ z+Bt*79_Zu3zsq|f;!T+~(0+7`M4gi2$|cbJ?UA^?KhnAVL-er~0ISEGEsjiZ>II6j zJ`mKS5n6PUV7o4XK#0Q~M_}xSItynL$4Mq>s@`eGN4Ax5z=@@KG=A#YaO(zcuS&R-T{jy^95df? zhBgSc{|8Ca|MgTwe@a65rLbFs6Gk^hTpm!v-k0}w0Q1cNl`;GJP}ToXw{=siB=*vf zHxn+sNA|%9%>1SYZQ@j8$|L1wHI)VM@Myp5;mm=yQOeWeg4>zj*?yR(Y%m)_NyCra z&fVQ3a57csqRT{-H@;jljE;zpqW7k0<4-7Be!RV*l1Q5yB^n)C;k^#~27!`x>BLk? z7d5CtkN8>59ajomrXknpE|WKQHrcEJ7is7MnJks0?)_oCLsZWv-uZ?f>b*@-n;Cd* z$msy?aEXih+5mAZsXsqt)EK_{lJm%e5uftYsI!pk<&UEmAi@mnCMjt`#sk4y6Drqy zu$tb!3yWO;n0+a5<{(1&`!Zgz{_e)1Tz3Pl>uX;u{2?6C24#S`Dy$N|)V$mav<#gg z7?Ao0(dCZeoBES`MdI)bX1*_PreSbZgFeWiZi(4N^n8iiU0U3QxO+mr58beqZFIL>EAP5lL zC3VJuWLKei>GX|qErzMAcC!PEULKp$X?seib+whOT@QZ!=nfy>*JV$xdp08R zoG~SlCua;f&>fWtm}{#!mu<@HRePjyJ%d{9D50yKsC z;~3UWR&AZy;%hCducEcaO6PVh3llUh9W$08C*O_|jQS^I7o!dhjd?MW$(t4g5EkdNV#F_pX@ez1SL%__4DD8C)MqH+RnJ6D%}QIWnp>U9 zPZm?Sil^t+unmJ+P16hkjQdGMcu$gCD@_p$gN{|))JRZC^EOPLLO&5IAe?m=h>sfo2eTR&Lf5xJU8mbrZ|D5_zDjwJ&wQyi7tWQ z%_p_F{GuYZ;3>_Qr?YR_n%(X*Q{wVC5-*pe_H+f2=Lo!X*xu2R7hqGx*M?S1y|&Kw z8t0)RdlLtUf-j~H_(jFL{HNE`CU4!gT4q$@qoq+on|q`C9!qK>+ay9s z&xEzi%;ZEwR7;N6gbd3GuBRB=@~G9Vkg-VSrt0z!&O)gs&YL)EmCsN4dH~oF+$Foj z!Quo>Y0N~~NFeD}#uw3ucW`LdBlmUQ0&+UC8}|_|G)|@Oc!UT+gp9V4$mHy^nIRgW ze-SMz(fD1`v$TIcy^8&-|C83zk?TG`u`(pgiAl-o`^`rk@19$hGNNk}64n^P&Xn!D zO+OEvXeVAG$x6DR%TS3Fb7Sin<%&ujC zH;1ZH!tcL+FPe|4E7HEem8Fz`EMmZM<{J>P{}^96J4>ccYa!X2crgDfRUzJO=f16q z0aU%;6`iXaU;9|h!$9OYD3{oacCoWs#Ds}j*4Doed+7|>^z52E`=M5GVN061K=VU` z{TeN%H9-Oh-!kytSB9`eycj6}ilhLHY=Y-J^1SCE7_~3M=L1w%j{W(*{@CWF_^g&} z+OV zid~sI96&IO!x^xQjm&Vr4`+&%X5NUZ#}_yxrv}*e`K`8b?e74f_3aq=OC`oo<+eHj zgx?wXw>k!Jfa|yHfT$awy-W6xRm26jwLHa(gKC6c#%ykLRhG^6kA1$#+XJdP`bTzG zHeZ#1Iq8`>wV3xc^H!tmHeptCC64T4<1^W*yh9#dYFEp&=P*Ar1r?aGtxF?Yg;8>py*^CVXX4w`);$t*E?%3 zkyoNRZpA(=j&0a$bINO<&S}3(|6oV&wU!_440L`dR6|8Gnpo}uD}6$Db;Z3-L?dOB zC@-QnepY=Z%ZnooLDchk{A`gt1PC!AM*(+AZODAwc?AsEQ3M{2=0AG zhu`?OnwO{L2!e7dDV_uB>mU#WglQlqJQuYsM+d4P=D0^`4>(ZDZ#8wpg>gx4>Qf6# z`vXf*anf~5UVi5ByH1>20{=84cOp{s9)SOcjHWgQacCc)~UsKoG3adVG|$WI-~p`1lmskg*haCcNKk{fw1G&_|7 zY`Pq=lY2tRqD}q7a>Cx-v!vpCsXjfN)EW1%_0KPUPS}@FXqB7+UkooZWMdYdF7Tt; z%PSNbuL?hU>|1iN$lr##^tX&3vyjmgs+=fp&LPh6m-8v_evB9(G3b(g+q5l`Q;3E# zj!573oAC?Kypq)nQMWNPEYtnyiBD-(lJ#X7eoRwB7`*dxrY9H|M_ zFW>vJ)e(U9uTBJ?B1X7LEl1vMOt~z3OF6NKk$&>nukXs)2e*$6Rj;=4N&#NK?5mf3 zw5!Xo_r*#?;rNWU?1%go+U#*e0xq0=x+q{3HN=jbx@UJ7ajmbsJoKLrVLzrS)7JZ& zwmc3Cc57pBp$8AgE~%EW=rCN)8(n0}y#yYE;F1B7(Ye*@xg(6+cY3kv^zhU*aeDYp zo^{#}aUq-ex1|cdw4sb zp*~m5?H6!9oVacN#kY?%v^1z`21ux44;rBkOW3cFNhU{Mrq>K-+jmj7*v-NoiB~0~ zhsEcrA9)wd{0dY4$AJd@7iAb(;~yzjv1oRJ_KRxb;Xpqs57?7x;Cx;2rIkcn?5?Xz zz%elem1V>Nn{nHv&t~-k@iMNKDZOJa=T{kI>iwP7Ljte32^O@?#Nw`ll6_uwPbj9H zsh|6=zC1eI-}H3eKRpW>O6`Ru6*}RbY?b-TL2Yq0It`H`;NABn{mZa&l?TqZ`Du7D zUl~cAl}Tc;@yT2IkR|FFzMgKr4G0AHbvpbVy>k#0yrCE;xJ!1U{GwUJ6)kB1@O%RW{8FJ$N#kXYCWy^?HU?ZG5!q zMSh#G8{b!P_#h9}ioy@p3<0{j^yd|73oqJD5xopXK$y_>Xp)luNJ14nIWXIb!d0!{ z^~(c2@FdEoc3RZK$FEjuOm0o?Va+?3-W5BWf-S2Xk7=VGI&B#~7ySq5hiTZ-FnRyO zSL*SQmk2lB$sg@85-owl)QRsh(>QAR&yCf~1F*A^{heze3S~>UaIP&Yt-IcwceJd@ ziFx7f8+;5GY#Gt}l_6IMOn_eb_G=EqAtuODP-+8$dt`rLNJ5Nz-{b)e^{0;?I3+Pl z?#8{I-vVIIp1xO;2|CCc#>TFVBo29s(Xk>urF9F%CVWyyZ4T#EJZfVV&%juH(;?jB z05_r%MVmuA{`8@UqRPX3xmINk%iSey3C6nye9xQ90UggbEvcp-Yl&i`ZP-qY=^tJGpo3%`1N|2idCe4y?i0) zYBl`m;pOb<22lbC&=eD=MX2Mjnq%-uC?>o!D-&`ddF3)&{FMeq-$z0s6br6)0}(-l zNsL!a5yT4?DvnSJV3VLRHm$&)%yf z#b5RCt&okZG1XwS!lY)yn4*`r3ZW_BXf_hYSYSK3^fyH+uVMu}`+HfFA<-M*CqOll zzq)6f^gHQUQ*8dO;c%ZZK5L!=i=LorZ4kIX=>NfP;0c5KVkYz*-T(SY9n=Znpzoac004T& L4UqibQ0spHQ7TFD diff --git a/public/sample/audio/고요9.mp3 b/public/sample/audio/고요9.mp3 deleted file mode 100644 index ee6bc3e5d02b038902559530fc8d9a53c806dbc9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10588 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 L4UqibQ0spHQ7TFD diff --git a/public/sample/imgs/logo.png b/public/sample/imgs/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..74164f4d64e6a3c27e43394ef5bd2a6a17ad030b GIT binary patch literal 113154 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 SASJ!t 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 literal 0 HcmV?d00001 diff --git a/public/sample/index.js b/public/sample/index.js index 65f2d0d..14be105 100644 --- a/public/sample/index.js +++ b/public/sample/index.js @@ -4,18 +4,24 @@ $(document).ready(function() { - //common metrics + //networking - socket.io + var socket = io('https://sound-mix.herokuapp.com'); + + //metrics related to 'view size' + // 'coarse' var vs = view.size; var vsw = vs.width; var vsh = vs.height; + // 'fine' var vss = view.size / 10; var vssw = vss.width; var vssh = vss.height; - //pre-load resources + //pre-load resources (images + audios) Promise.all([ + //imgs - RasterImport_size1('./imgs/phonehand.png'), + RasterImport_size1('./imgs/logo.png'), SVGImport_size1('./imgs/arrow-circle-right.svg'), SVGImport_size1('./imgs/arrow-circle-left.svg'), SVGImport_size1('./imgs/hand-point-right-regular.svg'), @@ -24,28 +30,23 @@ $(document).ready(function() { SVGImport_size1('./imgs/minus.svg'), SVGImport_size1('./imgs/faster.svg'), SVGImport_size1('./imgs/slower.svg'), + //clap AudioImport_p5("./audio/clap@2/" + ("0" + getRandomInt(1, 2)).slice(-2) + ".mp3"), - //beach_sounds page 1 ==> 7 - AudioImport("./audio/검은산_다급.mp3"), - AudioImport("./audio/검은산_뚜루.mp3"), - AudioImport("./audio/검은산_부엉.mp3"), - AudioImport("./audio/검은산_불안.mp3"), - AudioImport("./audio/검은산_쏟아짐.mp3"), - AudioImport("./audio/고요6.mp3"), - AudioImport("./audio/고요7.mp3"), - //beach_sounds page 2 ==> 7 - AudioImport("./audio/기정_과자봉지소리.mp3"), - AudioImport("./audio/기정_라디오.mp3"), - AudioImport("./audio/기정_물소리(붓).mp3"), - AudioImport("./audio/기정_악기.mp3"), - AudioImport("./audio/고요12.mp3"), - AudioImport("./audio/고요13.mp3"), - AudioImport("./audio/고요14.mp3"), + + //sounds page ==> 7 + AudioImport("./audio/01.mp3"), + AudioImport("./audio/02.mp3"), + AudioImport("./audio/03.mp3"), + AudioImport("./audio/04.mp3"), + AudioImport("./audio/05.mp3"), + AudioImport("./audio/06.mp3"), + AudioImport("./audio/07.mp3"), // ]).then(function(imports) { + //imgs - var phonehand = imports[0]; + var logo = imports[0]; var anext = imports[1]; var aprev = imports[2]; var hand = imports[3]; @@ -54,52 +55,40 @@ $(document).ready(function() { var minus = imports[6]; var faster = imports[7]; var slower = imports[8]; + //clap var clap = imports[9]; - //beach list - //NOTE: beware! same key is not allowed!! every keys should have different name!! - var beach_sounds = { - '검은산_다급': imports[10], - '검은산_뚜루': imports[11], - '검은산_부엉': imports[12], - '검은산_불안': imports[13], - '검은산_쏟아짐': imports[14], - '고요6': imports[15], - '_소리의_퍼짐______소리의_움직임_1': imports[16], - '기정_과자봉지소리': imports[17], - '기정_라디오': imports[18], - '기정_물소리(붓)': imports[19], - '기정_악기': imports[20], - '고요12': imports[21], - '고요13': imports[22], - '_소리의_퍼짐______소리의_움직임_2': imports[23], + + //audio-files dictionary {key: value} + //N.B.: Duplicate keys are not allowed! + // i.e. if '01' appearing twice will be a problem. + var sounds = { + '01': imports[10], + '02': imports[11], + '03': imports[12], + '04': imports[13], + '05': imports[14], + '06': imports[15], + '07': imports[16], }; - //NOTE: beware! same key is not allowed!! every keys should have different name!! - var beach_players = { - '검은산_다급': [], - '검은산_뚜루': [], - '검은산_부엉': [], - '검은산_불안': [], - '검은산_쏟아짐': [], - '고요6': [], - '_소리의_퍼짐______소리의_움직임_1': [], - '기정_과자봉지소리': [], - '기정_라디오': [], - '기정_물소리(붓)': [], - '기정_악기': [], - '고요12': [], - '고요13': [], - '_소리의_퍼짐______소리의_움직임_2': [], + //audio-players' bank + var players = { + '01': [], + '02': [], + '03': [], + '04': [], + '05': [], + '06': [], + '07': [], }; //screen changer - var nscreen = 4; + var nscreen = 3; var screens = []; var screen_names = {}; screen_names['start'] = 1; screen_names['check'] = 2; - screen_names['beach1'] = 3; - screen_names['beach2'] = 4; + screen_names['sound'] = 3; var curscreen; for (var idx = 0; idx < nscreen; idx++) { screens.push(new Layer()); @@ -118,12 +107,10 @@ $(document).ready(function() { if (idx == page - 1) { screens[idx].bringToFront(); top.bringToFront(); - $('.objstring').eq(idx).css('z-index', 1); // screens[idx].activate(); } else { screens[idx].sendToBack(); - $('.objstring').eq(idx).css('z-index', -1); } } //pagination buttons @@ -172,11 +159,6 @@ $(document).ready(function() { //top layer var top = new Layer(); // new Layer() will be automatically activated at the moment. - //networking - socket.io - //var socket = io('http://192.168.42.20:8080'); - //var socket = io('http://sound-mix.herokuapp.com:8080'); - var socket = io('https://sound-mix.herokuapp.com'); - //net. connection marker var netstat = new Path.Circle({ center: view.bounds.topRight + [-vssw / 2, +vssw / 2], @@ -263,7 +245,7 @@ $(document).ready(function() { //title - text new PointText({ point: titlebox.bounds.center, - content: ' 사운드-랩 § soundLab ', + content: '✧*。٩(ˊᗜˋ*)و✧*。', fillColor: 'white', fontFamily: 'AppleGothic, Sans-serif', fontWeight: 'bold', @@ -271,10 +253,10 @@ $(document).ready(function() { }).fitBounds(titlebox.bounds); //hello, screen. - phonehand.addTo(project); - phonehand.scale(vsw / 1.5); - phonehand.position = view.center; - //phonehand.position.y -= vssh; + logo.addTo(project); + logo.scale(vsw / 1.5); + logo.position = view.center; + //logo.position.y -= vssh; //screen #2 - check changeScreen(2); @@ -331,7 +313,7 @@ $(document).ready(function() { var cur_pan_width = 0; var cur_pan_speed = 0; - //screen #3 - beach page #1 + //screen #3 - sound page changeScreen(3); new Path.Rectangle([0, 0], vs).fillColor = '#555'; @@ -371,30 +353,16 @@ $(document).ready(function() { ], onMouseDown: function(event) { var par = this.parent; - //NOTE: this DOES NOT sync between web-clients! <-- TBD, yet NOT-IMPLEMENTED ! - if (par._key == '_소리의_퍼짐______소리의_움직임_1' || par._key == '_소리의_퍼짐______소리의_움직임_2') { - //pan_width: (+) - if (cur_pan_width_idx < (pan_width_pool.length - 1)) { - cur_pan_width_idx++; - } - cur_pan_width = pan_width_pool[cur_pan_width_idx]; - par._socket.emit('pan', { - width: cur_pan_width, - speed: cur_pan_speed - }); - par.children.playcounter.content = '' + (cur_pan_width_idx + 1); - } else { - par._players.push(par._player.start()._source); // start playbacks and collect their '_source's.. - par._playcount++; - par.children.playcounter.content = '' + par._playcount; - par.children.speedcounter.content = Number.parseFloat(1).toFixed(1); - // - par._socket.emit('sound', { - name: par._key, - action: 'start', - group: 'beach' - }); - } + par._players.push(par._player.start()._source); // start playbacks and collect their '_source's.. + par._playcount++; + par.children.playcounter.content = '' + par._playcount; + par.children.speedcounter.content = Number.parseFloat(1).toFixed(1); + // + par._socket.emit('sound', { + name: par._key, + action: 'start', + group: 'mix-bowl' + }); } }), //playcounterbox @@ -429,34 +397,20 @@ $(document).ready(function() { ], onMouseDown: function() { var par = this.parent; - //NOTE: this DOES NOT sync between web-clients! <-- TBD, yet NOT-IMPLEMENTED ! - if (par._key == '_소리의_퍼짐______소리의_움직임_1' || par._key == '_소리의_퍼짐______소리의_움직임_2') { - //pan_width : (-) - if (cur_pan_width_idx > 0) { - cur_pan_width_idx--; - } - cur_pan_width = pan_width_pool[cur_pan_width_idx]; - par._socket.emit('pan', { - width: cur_pan_width, - speed: cur_pan_speed - }); - par.children.playcounter.content = '' + (cur_pan_width_idx + 1); - } else { - if (par._players.length > 0) { - (par._players.shift()).stop(); - par._playcount--; - par.children.playcounter.content = '' + par._playcount; - } - if (par._players.length == 0) { - par.children.speedcounter.content = Number.parseFloat(1).toFixed(1); - } - // - par._socket.emit('sound', { - name: par._key, - action: 'stop', - group: 'beach' - }); + if (par._players.length > 0) { + (par._players.shift()).stop(); + par._playcount--; + par.children.playcounter.content = '' + par._playcount; } + if (par._players.length == 0) { + par.children.speedcounter.content = Number.parseFloat(1).toFixed(1); + } + // + par._socket.emit('sound', { + name: par._key, + action: 'stop', + group: 'mix-bowl' + }); } }), //faster button @@ -479,30 +433,16 @@ $(document).ready(function() { ], onMouseDown: function() { var par = this.parent; - //NOTE: this DOES NOT sync between web-clients! <-- TBD, yet NOT-IMPLEMENTED ! - if (par._key == '_소리의_퍼짐______소리의_움직임_1' || par._key == '_소리의_퍼짐______소리의_움직임_2') { - //pan_speed: (+) - if (cur_pan_speed_idx < (pan_speed_pool.length - 1)) { - cur_pan_speed_idx++; - } - cur_pan_speed = pan_speed_pool[cur_pan_speed_idx]; - par._socket.emit('pan', { - width: cur_pan_width, - speed: cur_pan_speed - }); - par.children.speedcounter.content = '' + cur_pan_speed_idx; - } else { - if (par._players.length > 0) { - par._players[par._players.length - 1].playbackRate.value += 0.2; - par.children.speedcounter.content = Number.parseFloat(par._players[par._players.length - 1].playbackRate.value).toFixed(1); - } - // - par._socket.emit('sound', { - name: par._key, - action: 'faster', - group: 'beach' - }); + if (par._players.length > 0) { + par._players[par._players.length - 1].playbackRate.value += 0.2; + par.children.speedcounter.content = Number.parseFloat(par._players[par._players.length - 1].playbackRate.value).toFixed(1); } + // + par._socket.emit('sound', { + name: par._key, + action: 'faster', + group: 'mix-bowl' + }); } }), //speedcounterbox @@ -539,40 +479,26 @@ $(document).ready(function() { ], onMouseDown: function() { var par = this.parent; - //NOTE: this DOES NOT sync between web-clients! <-- TBD, yet NOT-IMPLEMENTED ! - if (par._key == '_소리의_퍼짐______소리의_움직임_1' || par._key == '_소리의_퍼짐______소리의_움직임_2') { - //pan_speed: (-) - if (cur_pan_speed_idx > 0) { - cur_pan_speed_idx--; + if (par._players.length > 0) { + var val = par._players[par._players.length - 1].playbackRate.value; + if (val > 0.2) { + par._players[par._players.length - 1].playbackRate.value = val - 0.2; } - cur_pan_speed = pan_speed_pool[cur_pan_speed_idx]; - par._socket.emit('pan', { - width: cur_pan_width, - speed: cur_pan_speed - }); - par.children.speedcounter.content = '' + cur_pan_speed_idx; - } else { - if (par._players.length > 0) { - var val = par._players[par._players.length - 1].playbackRate.value; - if (val > 0.2) { - par._players[par._players.length - 1].playbackRate.value = val - 0.2; - } - par.children.speedcounter.content = Number.parseFloat(par._players[par._players.length - 1].playbackRate.value).toFixed(1); - } - // - par._socket.emit('sound', { - name: par._key, - action: 'slower', - group: 'beach' - }); + par.children.speedcounter.content = Number.parseFloat(par._players[par._players.length - 1].playbackRate.value).toFixed(1); } + // + par._socket.emit('sound', { + name: par._key, + action: 'slower', + group: 'mix-bowl' + }); } }) ], _socket: socket, - _key: Object.keys(beach_sounds)[idx], - _player: beach_sounds[Object.keys(beach_sounds)[idx]], - _players: beach_players[Object.keys(beach_players)[idx]], + _key: Object.keys(sounds)[idx], + _player: sounds[Object.keys(sounds)[idx]], + _players: players[Object.keys(players)[idx]], _playcount: 0, _init: function() { this._player.loop = true; @@ -593,7 +519,7 @@ $(document).ready(function() { //socket io event handling.. var that = this; this._socket.on('sound', function(msg) { - if (msg.group == 'beach' && msg.name == that._key) { + if (msg.group == 'mix-bowl' && msg.name == that._key) { if (msg.action == 'start') { that._players.push(that._player.start()._source); // start playbacks and collect their '_source's.. that._playcount++; @@ -630,314 +556,7 @@ $(document).ready(function() { //label new PointText({ point: c.firstChild.bounds.topLeft + [0, -5], - content: Object.keys(beach_sounds)[idx], - fontSize: vssw * 0.55, - fontWeight: 'bold', - fillColor: 'white' - }); - } - } - - //screen #4 - beach page #2 - changeScreen(4); - new Path.Rectangle([0, 0], vs).fillColor = '#555'; - - //title - text - new PointText({ - point: [vssw * 2, vssw * 1], - content: ' 믹스 #2 ', - fillColor: 'white', - fontFamily: 'AppleGothic, Sans-serif', - fontWeight: 'bold', - fontSize: '3em' - }).fitBounds(titlebox.bounds); - - // - for (var row = 0; row < 7; row++) { - for (var col = 0; col < 1; col++) { - var idx = row * 1 + col + 7; - - //play/stop/playcount/faster/slower button (networked between groups) - var c = new Group({ - children: [ - //play button - new Group({ - name: 'play_btn', - children: [ - new Path.Rectangle({ - point: [vssw * 0.8, row * vssw * 1.4 + vssw * 3.5], - radius: vssw * 0.4, - size: [vssw * 1.5, vssw * 0.7], - fillColor: new Color({ - hue: getRandom(20, 60), - saturation: 1, - brightness: 1 - }), - }), - plus.clone() - ], - onMouseDown: function(event) { - var par = this.parent; - //NOTE: this DOES NOT sync between web-clients! <-- TBD, yet NOT-IMPLEMENTED ! - if (par._key == '_소리의_퍼짐______소리의_움직임_1' || par._key == '_소리의_퍼짐______소리의_움직임_2') { - //pan_width: (+) - if (cur_pan_width_idx < (pan_width_pool.length - 1)) { - cur_pan_width_idx++; - } - cur_pan_width = pan_width_pool[cur_pan_width_idx]; - par._socket.emit('pan', { - width: cur_pan_width, - speed: cur_pan_speed - }); - par.children.playcounter.content = '' + (cur_pan_width_idx + 1); - } else { - par._players.push(par._player.start()._source); // start playbacks and collect their '_source's.. - par._playcount++; - par.children.playcounter.content = '' + par._playcount; - par.children.speedcounter.content = Number.parseFloat(1).toFixed(1); - // - par._socket.emit('sound', { - name: par._key, - action: 'start', - group: 'beach' - }); - } - } - }), - //playcounterbox - new Path.Rectangle({ - name: 'playcounterbox', - point: [vssw * 2.3, row * vssw * 1.4 + vssw * 3.5], - size: [vssw * 0.6, vssw * 0.8], - }), - //playcounter - new PointText({ - name: 'playcounter', - content: '' + 0, - fillColor: 'white', - fontSize: '2em', - fontWeight: 'bold' - }), - //stop button - new Group({ - name: 'stop_btn', - children: [ - new Path.Rectangle({ - point: [vssw * 2.9, row * vssw * 1.4 + vssw * 3.5], - radius: vssw * 0.4, - size: [vssw * 1.6, vssw * 0.7], - fillColor: new Color({ - hue: getRandom(120, 180), - saturation: 1, - brightness: 1 - }), - }), - minus.clone() - ], - onMouseDown: function() { - var par = this.parent; - //NOTE: this DOES NOT sync between web-clients! <-- TBD, yet NOT-IMPLEMENTED ! - if (par._key == '_소리의_퍼짐______소리의_움직임_1' || par._key == '_소리의_퍼짐______소리의_움직임_2') { - //pan_width : (-) - if (cur_pan_width_idx > 0) { - cur_pan_width_idx--; - } - cur_pan_width = pan_width_pool[cur_pan_width_idx]; - par._socket.emit('pan', { - width: cur_pan_width, - speed: cur_pan_speed - }); - par.children.playcounter.content = '' + (cur_pan_width_idx + 1); - } else { - if (par._players.length > 0) { - (par._players.shift()).stop(); - par._playcount--; - par.children.playcounter.content = '' + par._playcount; - } - if (par._players.length == 0) { - par.children.speedcounter.content = Number.parseFloat(1).toFixed(1); - } - // - par._socket.emit('sound', { - name: par._key, - action: 'stop', - group: 'beach' - }); - } - } - }), - //faster button - new Group({ - name: 'faster_btn', - children: [ - new Path.Rectangle({ - point: [vssw * 5.0, row * vssw * 1.4 + vssw * 3.5], - radius: vssw * 0.4, - size: [vssw * 1.6, vssw * 0.7], - strokeColor: new Color({ - hue: getRandom(20, 60), - saturation: 1, - brightness: 1 - }), - strokeWidth: vssw * 0.03, - fillColor: "#555" - }), - faster.clone() - ], - onMouseDown: function() { - var par = this.parent; - //NOTE: this DOES NOT sync between web-clients! <-- TBD, yet NOT-IMPLEMENTED ! - if (par._key == '_소리의_퍼짐______소리의_움직임_1' || par._key == '_소리의_퍼짐______소리의_움직임_2') { - //pan_speed: (+) - if (cur_pan_speed_idx < (pan_speed_pool.length - 1)) { - cur_pan_speed_idx++; - } - cur_pan_speed = pan_speed_pool[cur_pan_speed_idx]; - par._socket.emit('pan', { - width: cur_pan_width, - speed: cur_pan_speed - }); - par.children.speedcounter.content = '' + cur_pan_speed_idx; - } else { - if (par._players.length > 0) { - par._players[par._players.length - 1].playbackRate.value += 0.2; - par.children.speedcounter.content = Number.parseFloat(par._players[par._players.length - 1].playbackRate.value).toFixed(1); - } - // - par._socket.emit('sound', { - name: par._key, - action: 'faster', - group: 'beach' - }); - } - } - }), - //speedcounterbox - new Path.Rectangle({ - name: 'speedcounterbox', - point: [vssw * 6.6, row * vssw * 1.4 + vssw * 3.5], - size: [vssw * 0.6, vssw * 0.8], - }), - //speedcounter - new PointText({ - name: 'speedcounter', - content: '' + 0, - fillColor: 'white', - fontSize: '2em', - fontWeight: 'bold' - }), - //slower button - new Group({ - name: 'slower_btn', - children: [ - new Path.Rectangle({ - point: [vssw * 7.8, row * vssw * 1.4 + vssw * 3.5], - radius: vssw * 0.4, - size: [vssw * 1.6, vssw * 0.7], - strokeColor: new Color({ - hue: getRandom(120, 180), - saturation: 1, - brightness: 1 - }), - strokeWidth: vssw * 0.03, - fillColor: "#555" - }), - slower.clone() - ], - onMouseDown: function() { - var par = this.parent; - //NOTE: this DOES NOT sync between web-clients! <-- TBD, yet NOT-IMPLEMENTED ! - if (par._key == '_소리의_퍼짐______소리의_움직임_1' || par._key == '_소리의_퍼짐______소리의_움직임_2') { - //pan_speed: (-) - if (cur_pan_speed_idx > 0) { - cur_pan_speed_idx--; - } - cur_pan_speed = pan_speed_pool[cur_pan_speed_idx]; - par._socket.emit('pan', { - width: cur_pan_width, - speed: cur_pan_speed - }); - par.children.speedcounter.content = '' + cur_pan_speed_idx; - } else { - if (par._players.length > 0) { - var val = par._players[par._players.length - 1].playbackRate.value; - if (val > 0.2) { - par._players[par._players.length - 1].playbackRate.value = val - 0.2; - } - par.children.speedcounter.content = Number.parseFloat(par._players[par._players.length - 1].playbackRate.value).toFixed(1); - } - // - par._socket.emit('sound', { - name: par._key, - action: 'slower', - group: 'beach' - }); - } - } - }) - ], - _socket: socket, - _key: Object.keys(beach_sounds)[idx], - _player: beach_sounds[Object.keys(beach_sounds)[idx]], - _players: beach_players[Object.keys(beach_players)[idx]], - _playcount: 0, - _init: function() { - this._player.loop = true; - this._player.retrigger = true; - // set icons - this.children.play_btn.children[1].fitBounds(this.children.play_btn.children[0].bounds); - this.children.play_btn.children[1].fillColor = "#555"; - this.children.stop_btn.children[1].fitBounds(this.children.stop_btn.children[0].bounds); - this.children.stop_btn.children[1].fillColor = "#555"; - this.children.faster_btn.children[1].fitBounds(this.children.faster_btn.children[0].bounds); - this.children.faster_btn.children[1].fillColor = "orange"; - this.children.slower_btn.children[1].fitBounds(this.children.slower_btn.children[0].bounds); - this.children.slower_btn.children[1].fillColor = "lime"; - // positioning numberboxes... - this.children.playcounter.fitBounds(this.children.playcounterbox.bounds); - this.children.speedcounter.fitBounds(this.children.speedcounterbox.bounds); - this.children.speedcounter.content = Number.parseFloat(1).toFixed(1); - //socket io event handling.. - var that = this; - this._socket.on('sound', function(msg) { - if (msg.group == 'beach' && msg.name == that._key) { - if (msg.action == 'start') { - that._players.push(that._player.start()._source); // start playbacks and collect their '_source's.. - that._playcount++; - that.children.playcounter.content = '' + that._playcount; - that.children.speedcounter.content = Number.parseFloat(1).toFixed(1); - } else if (msg.action == 'stop') { - if (that._players.length > 0) { - (that._players.shift()).stop(); - that._playcount--; - that.children.playcounter.content = '' + that._playcount; - } - if (that._players.length == 0) { - that.children.speedcounter.content = Number.parseFloat(1).toFixed(1); - } - } else if (msg.action == 'faster') { - if (that._players.length > 0) { - that._players[that._players.length - 1].playbackRate.value += 0.2; - that.children.speedcounter.content = Number.parseFloat(that._players[that._players.length - 1].playbackRate.value).toFixed(1); - } - } else if (msg.action == 'slower') { - if (that._players.length > 0) { - var val = that._players[that._players.length - 1].playbackRate.value; - if (val > 0.2) { - that._players[that._players.length - 1].playbackRate.value -= 0.2; - } - that.children.speedcounter.content = Number.parseFloat(that._players[that._players.length - 1].playbackRate.value).toFixed(1); - } - } - } - }); - } - }); - c._init(); - //label - new PointText({ - point: c.firstChild.bounds.topLeft + [0, -5], - content: Object.keys(beach_sounds)[idx], + content: Object.keys(sounds)[idx], fontSize: vssw * 0.55, fontWeight: 'bold', fillColor: 'white' diff --git a/public/sample/lib/nexus-ui.js b/public/sample/lib/nexus-ui.js new file mode 100644 index 0000000..2c1e049 --- /dev/null +++ b/public/sample/lib/nexus-ui.js @@ -0,0 +1,9369 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["Nexus"] = factory(); + else + root["Nexus"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; +/******/ +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.loaded = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + + var NexusUI = _interopRequire(__webpack_require__(1)); + + module.exports = NexusUI; + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { "default": obj }; }; + + var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + exports.colors = colors; + exports.context = context; + exports.clock = clock; + Object.defineProperty(exports, "__esModule", { + value: true + }); + "use strict"; + + var Interfaces = _interopRequire(__webpack_require__(2)); + + var math = _interopRequire(__webpack_require__(5)); + + var Rack = _interopRequire(__webpack_require__(38)); + + var Tune = _interopRequire(__webpack_require__(40)); + + var Transform = _interopRequireWildcard(__webpack_require__(39)); + + var Counter = __webpack_require__(28); + var Radio = __webpack_require__(41); + var Drunk = __webpack_require__(27); + var Sequence = __webpack_require__(26); + var Matrix = __webpack_require__(25); + + var WAAClock = _interopRequire(__webpack_require__(42)); + + var Interval = _interopRequire(__webpack_require__(29)); + + /** + NexusUI => created as Nexus + */ + + var NexusUI = (function () { + function NexusUI(context) { + _classCallCheck(this, NexusUI); + + for (var key in Interfaces) { + this[key] = Interfaces[key]; + } + + for (var key in math) { + this[key] = math[key]; + } + + var Core = { + Rack: Rack + }; + + var Models = { + Counter: Counter, + Radio: Radio, + Drunk: Drunk, + Sequence: Sequence, + Matrix: Matrix + }; + + for (var key in Models) { + this[key] = Models[key]; + } + + for (var key in Core) { + this[key] = Core[key]; + } + + var DefaultContext = window.AudioContext || window.webkitAudioContext; + this._context = context || new DefaultContext(); + + this.tune = new Tune(); + this.note = this.tune.note.bind(this.tune); + + this.clock = new WAAClock(this._context); + this.clock.start(); + this.Interval = Interval; + + this.colors = { + accent: "#2bb", + fill: "#eee", + light: "#fff", + dark: "#333", + mediumLight: "#ccc", + mediumDark: "#666" + }; + + this.transform = Transform; + this.add = Transform.add; + + this.Add = {}; + for (var key in Interfaces) { + this.Add[key] = Transform.add.bind(this, key); + } + + /* create default component size */ + /* jshint ignore:start */ + var existingStylesheets = document.getElementsByTagName("style"); + var defaultSizeDeclaration = "[nexus-ui]{height:5000px;width:5000px}"; + var defaultStyleNode = document.createElement("style"); + defaultStyleNode.type = "text/css"; + defaultStyleNode.innerHTML = defaultSizeDeclaration; + if (existingStylesheets.length > 0) { + var parent = existingStylesheets[0].parentNode; + parent.insertBefore(defaultStyleNode, existingStylesheets[0]); + } else { + document.write(""); + } + /* jshint ignore:end */ + } + + _createClass(NexusUI, { + context: { + get: function () { + return this._context; + }, + set: function (ctx) { + this.clock.stop(); + this._context = ctx; + this.clock = new WAAClock(this.context); + this.clock.start(); + } + } + }); + + return NexusUI; + })(); + + var Nexus = new NexusUI(); + + function colors() { + return Nexus.colors; + } + + function context() { + return Nexus.context; + } + + function clock() { + return Nexus.clock; + } + + exports["default"] = Nexus; + +/***/ }), +/* 2 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + module.exports = { + Position: __webpack_require__(3), + Slider: __webpack_require__(14), + Toggle: __webpack_require__(15), + /* Range: require('./rangeslider'), + Waveform: require('./waveform'), */ + Button: __webpack_require__(16), + TextButton: __webpack_require__(18), + RadioButton: __webpack_require__(19), + Number: __webpack_require__(20), + Select: __webpack_require__(21), + Dial: __webpack_require__(22), + Piano: __webpack_require__(23), + Sequencer: __webpack_require__(24), + Pan2D: __webpack_require__(30), + Tilt: __webpack_require__(31), + Multislider: __webpack_require__(32), + Pan: __webpack_require__(33), + Envelope: __webpack_require__(34), + Spectrogram: __webpack_require__(35), + Meter: __webpack_require__(36), + Oscilloscope: __webpack_require__(37) + }; + +/***/ }), +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + + + "use strict"; + + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { "default": obj }; }; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + + var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var svg = __webpack_require__(4); + var Interface = __webpack_require__(6); + var Step = __webpack_require__(11); + + var Interaction = _interopRequireWildcard(__webpack_require__(12)); + + /** + * Position + * + * @description Two-dimensional touch slider. + * + * @demo + * + * @example + * var position = new Nexus.Position('#target') + * + * @example + * var position = new Nexus.Position('#target',{ + * 'size': [200,200], + * 'mode': 'absolute', // "absolute" or "relative" + * 'x': 0.5, // initial x value + * 'minX': 0, + * 'maxX': 1, + * 'stepX': 0, + * 'y': 0.5, // initial y value + * 'minY': 0, + * 'maxY': 1, + * 'stepY': 0 + * }) + * + * @output + * change + * Fires any time the interface's value changes.
+ * The event data is an object with x and y properties containing the x and y values of the interface. + * + * @outputexample + * position.on('change',function(v) { + * console.log(v); + * }) + * + * + */ + + var Position = (function (_Interface) { + function Position() { + _classCallCheck(this, Position); + + var options = ["value"]; + + var defaults = { + size: [200, 200], + mode: "absolute", + minX: 0, + maxX: 1, + stepX: 0, + x: 0.5, + minY: 0, + maxY: 1, + stepY: 0, + y: 0.5 + }; + + _get(Object.getPrototypeOf(Position.prototype), "constructor", this).call(this, arguments, options, defaults); + + this._x = new Step(this.settings.minX, this.settings.maxX, this.settings.stepX, this.settings.x); + this._y = new Step(this.settings.minY, this.settings.maxY, this.settings.stepY, this.settings.y); + + this.position = { + x: new Interaction.Handle(this.settings.mode, "horizontal", [0, this.width], [this.height, 0]), + y: new Interaction.Handle(this.settings.mode, "vertical", [0, this.width], [this.height, 0]) + }; + this.position.x.value = this._x.normalized; + this.position.y.value = this._y.normalized; + + this.init(); + this.render(); + } + + _inherits(Position, _Interface); + + _createClass(Position, { + buildInterface: { + value: function buildInterface() { + + this.knob = svg.create("circle"); + this.element.appendChild(this.knob); + } + }, + sizeInterface: { + value: function sizeInterface() { + + this.position.x.resize([0, this.width], [this.height, 0]); + this.position.y.resize([0, this.width], [this.height, 0]); + + this._minDimension = Math.min(this.width, this.height); + + this.knobRadius = { + off: ~ ~(this._minDimension / 100) * 5 + 5 }; + this.knobRadius.on = this.knobRadius.off * 2; + + this.knob.setAttribute("cx", this.width / 2); + this.knob.setAttribute("cy", this.height / 2); + this.knob.setAttribute("r", this.knobRadius.off); + } + }, + colorInterface: { + value: function colorInterface() { + this.element.style.backgroundColor = this.colors.fill; + this.knob.setAttribute("fill", this.colors.accent); + } + }, + render: { + value: function render() { + if (this.clicked) { + // this.knobRadius = 30; + this.knob.setAttribute("r", this.knobRadius.on); + } else { + // this.knobRadius = 15; + this.knob.setAttribute("r", this.knobRadius.off); + } + + this.knobCoordinates = { + x: this._x.normalized * this.width, + y: this.height - this._y.normalized * this.height + }; + + this.knob.setAttribute("cx", this.knobCoordinates.x); + this.knob.setAttribute("cy", this.knobCoordinates.y); + } + }, + click: { + value: function click() { + this.position.x.anchor = this.mouse; + this.position.y.anchor = this.mouse; + this.move(); + } + }, + move: { + value: function move() { + if (this.clicked) { + this.position.x.update(this.mouse); + this.position.y.update(this.mouse); + this._x.updateNormal(this.position.x.value); + this._y.updateNormal(this.position.y.value); + this.emit("change", { + x: this._x.value, + y: this._y.value + }); + this.render(); + } + } + }, + release: { + value: function release() { + this.render(); + } + }, + x: { + + /** + * The interface's x value. When set, it will automatically adjust to fit min/max/step settings of the interface. + * @type {object} + * @example position.x = 0.5; + */ + + get: function () { + return this._x.value; + }, + set: function (value) { + this._x.update(value); + this.emit("change", { + x: this._x.value, + y: this._y.value + }); + this.render(); + } + }, + y: { + + /** + * The interface's y values. When set, it will automatically adjust to fit min/max/step settings of the interface. + * @type {object} + * @example position.x = 0.5; + */ + + get: function () { + return this._y.value; + }, + set: function (value) { + this._y.update(value); + this.emit("change", { + x: this._x.value, + y: this._y.value + }); + this.render(); + } + }, + normalized: { + get: function () { + return { + x: this._x.normalized, + y: this._y.normalized + }; + } + }, + minX: { + + /** + * The lower limit of value on the x axis + * @type {object} + */ + + get: function () { + return this._x.min; + }, + set: function (v) { + this._x.min = v; + this.render(); + } + }, + minY: { + + /** + * The lower limit of value on the y axis + * @type {object} + */ + + get: function () { + return this._y.min; + }, + set: function (v) { + this._y.min = v; + this.render(); + } + }, + maxX: { + + /** + * The upper limit of value on the x axis + * @type {object} + */ + + get: function () { + return this._x.max; + }, + set: function (v) { + this._x.max = v; + this.render(); + } + }, + maxY: { + + /** + * The upper limit of value on the y axis + * @type {object} + */ + + get: function () { + return this._y.max; + }, + set: function (v) { + this._y.max = v; + this.render(); + } + }, + stepX: { + + /** + * The incremental step of values on the x axis + * @type {object} + */ + + get: function () { + return this._x.step; + }, + set: function (v) { + this._x.step = v; + this.render(); + } + }, + stepY: { + + /** + * The incremental step of values on the y axis + * @type {object} + */ + + get: function () { + return this._y.step; + }, + set: function (v) { + this._y.step = v; + this.render(); + } + }, + mode: { + + /** + Absolute mode (position's value jumps to mouse click position) or relative mode (mouse drag changes value relative to its current position). Default: "absolute". + @type {string} + @example position.mode = "relative"; + */ + + get: function () { + return this.position.x.mode; + }, + set: function (v) { + this.position.x.mode = v; + this.position.y.mode = v; + } + } + }); + + return Position; + })(Interface); + + module.exports = Position; + +/***/ }), +/* 4 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var math = __webpack_require__(5); + + module.exports = { + + create: function (type) { + return document.createElementNS("http://www.w3.org/2000/svg", type); + }, + + arc: function (x, y, radius, startAngle, endAngle) { + + var start = math.toCartesian(radius, endAngle); + var end = math.toCartesian(radius, startAngle); + + var largeArcFlag = endAngle - startAngle <= 180 ? "0" : "1"; + + var d = ["M", start.x + x, start.y + y, "A", radius, radius, 0, largeArcFlag, 0, end.x + x, end.y + y].join(" "); + + return d; + }, + + radialGradient: function (defs, numberOfStops) { + + var id = "gradient" + math.ri(100000000000); + var stops = []; + + var gradient = document.createElementNS("http://www.w3.org/2000/svg", "radialGradient"); + gradient.setAttribute("id", id); + gradient.setAttribute("cx", "50%"); + gradient.setAttribute("cy", "50%"); + gradient.setAttribute("r", "50%"); + + defs.appendChild(gradient); + + for (var i = 0; i < numberOfStops; i++) { + var _stop = document.createElementNS("http://www.w3.org/2000/svg", "stop"); + _stop.setAttribute("id", "stop" + i); + //stop.setAttribute('offset', '70%'); + //stop.setAttribute('stop-color', 'White'); + gradient.appendChild(_stop); + stops.push(_stop); + } + + return { + id: id, + stops: stops, + element: gradient + }; + } + + }; + +/***/ }), +/* 5 */ +/***/ (function(module, exports) { + + "use strict"; + + /** + * Limit a number to within a minimum and maximum + * @param {number} value Input value + * @param {number} min Lower limit + * @param {number} max Upper limit + * @return {number} The input value constrained within the lower and upper limits + * @example + * Nexus.clip(11,0,10) // returns 10 + * Nexus.clip(-1,0,10) // returns 0 + * Nexus.clip(5,0,10) // returns 5 + */ + + exports.clip = function (value, min, max) { + return Math.min(Math.max(value, min), max); + }; + + exports.normalize = function (value, min, max) { + return (value - min) / (max - min); + }; + + /** + * Scale a value from one range to another range. + * @param {number} inNum Input value + * @param {number} inMin Input range minimum + * @param {number} inMax Input range maximum + * @param {number} outMin Output range minimum + * @param {number} outMax Output range maximum + * @return {number} The input value scaled to its new range + * @example + * Nexus.scale(0.5,0,1,0,10) // returns 5 + * Nexus.scale(0.9,0,1,1,0) // returns 0.1 + */ + exports.scale = function (inNum, inMin, inMax, outMin, outMax) { + if (inMin === inMax) { + return outMin; + } + return (inNum - inMin) * (outMax - outMin) / (inMax - inMin) + outMin; + }; + + exports.toPolar = function (x, y) { + var r = Math.sqrt(x * x + y * y); + + var theta = Math.atan2(y, x); + if (theta < 0) { + theta = theta + 2 * Math.PI; + } + return { radius: r, angle: theta }; + }; + + exports.toCartesian = function (radius, angle) { + var cos = Math.cos(angle); + var sin = Math.sin(angle); + return { x: radius * cos, y: radius * sin * -1 }; + }; + /* + exports.polarToCartesian(centerX, centerY, radius, angleInDegrees) { + var angleInRadians = (angleInDegrees-90) * Math.PI / 180.0; + + return { + x: centerX + (radius * Math.cos(angleInRadians)), + y: centerY + (radius * Math.sin(angleInRadians)) + }; + } */ + + exports.prune = function (data, scale) { + return parseFloat(data.toFixed(scale)); + }; + + exports.invert = function (inNum) { + return exports.scale(inNum, 1, 0, 0, 1); + }; + + /** + * Convert a MIDi note number to a frequency value in equal temperament. + * @param {number} midi MIDI note value + * @return {number} Frequence value + * @example + * Nexus.mtof(60) // returns the frequency number of Middle C + */ + exports.mtof = function (midi) { + return Math.pow(2, (midi - 69) / 12) * 440; + }; + + /** + * Interpolate between two numbers + * @param {number} loc Interpolation index (0-1) + * @param {number} min Lower value + * @param {number} max Upper value + * @return {number} Interpolated value + * @example + * Nexus.interp(0.5,2,4) // returns 3 + * Nexus.interp(0.1,0,10) // returns 1 + */ + exports.interp = function (loc, min, max) { + return loc * (max - min) + min; + }; + + /** + * Return a random choice from a list of arguments + * @return {various} One random argument + * @example + * Nexus.pick(1,2,3,4) // returns 1, 2, 3, or 4 + * Nexus.pick(function1,function2) // returns either function1 or function2 + */ + exports.pick = function () { + return arguments[~ ~(Math.random() * arguments.length)]; + }; + + /** + * Returns an octave multiplier for frequency values + * @param {number} num Relative octave number (e.g. -1 for one octave down, 1 for one octave up) + * @return {number} Octave multiplier + * @example + * Nexus.octave(-1) // returns 0.5 + * Nexus.octave(0) // returns 1 + * Nexus.octave(1) // returns 2 + * Nexus.octave(2) // returns 4 + */ + exports.octave = function (num) { + return Math.pow(2, num); + }; + + /** + * Random integer generator. If no second argument is given, will return random integer from 0 to bound1. + * @param {number} bound1 Minimum random value + * @param {number} bound2 Maximum random value + * @return {number} Random integer between lower and upper boundary + * @example + * Nexus.ri(10) // returns random int from 0 to 10 + * Nexus.ri(20,2000) // returns random int from 20 to 2000 + */ + exports.ri = function (bound1, bound2) { + if (!bound2) { + bound2 = bound1; + bound1 = 0; + } + var low = Math.min(bound1, bound2); + var high = Math.max(bound1, bound2); + return Math.floor(Math.random() * (high - low) + low); + }; + + /** + * Random float number generator. If no second argument is given, will return random float from 0 to bound1. + * @param {number} bound1 Minimum random value + * @param {number} bound2 Maximum random value + * @return {number} Random float between lower and upper boundary + * @example + * Nexus.rf(1) // returns random float from 0 to 1 + * Nexus.rf(1,2) // returns random float from 1 to 2 + */ + exports.rf = function (bound1, bound2) { + if (!bound2) { + bound2 = bound1; + bound1 = 0; + } + var low = Math.min(bound1, bound2); + var high = Math.max(bound1, bound2); + return Math.random() * (high - low) + low; + }; + + exports.cycle = function (input, min, max) { + input++; + if (input >= max) { + input = min; + } + return input; + }; + + /** + * Average an array of numbers + * @param {Array} data Array of numbers to average + * @return {number} Average of the input data + * @example + * Nexus.average([0,2,4,6,8,10]) // returns 5 + */ + exports.average = function (data) { + var total = 0; + for (var i = 0; i < data.length; i++) { + total += data[i]; + } + return total / data.length; + }; + + /** + * Get the distance from one (x,y) point to another (x,y) point + * @param {number} x1 x of first point + * @param {number} y1 y of first point + * @param {number} x2 x of second point + * @param {number} y2 y of second poiny + * @return {number} Distance + * @example + * Nexus.distance(0,0,3,4) // returns 5 + */ + exports.distance = function (x1, y1, x2, y2) { + var a = x1 - x2; + var b = y1 - y2; + return Math.sqrt(a * a + b * b); + }; + + exports.gainToDB = function (gain) { + return 20 * Math.log10(gain); + }; + + /** + * Flip a coin, returning either 0 or 1 according to a probability + * @param {number} [odds=0.5] Likelihood of returning 1 + * @return {number} 1 or 0 + * @example + * Nexus.coin(0.1) // returns 1 (10% of the time) or 0 (90% of the time) + */ + exports.coin = function () { + var odds = arguments[0] === undefined ? 0.5 : arguments[0]; + + if (exports.rf(0, 1) < odds) { + return 1; + } else { + return 0; + } + }; + +/***/ }), +/* 6 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + + var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var svg = __webpack_require__(4); + var dom = __webpack_require__(7); + var util = __webpack_require__(8); + var touch = __webpack_require__(9); + var EventEmitter = __webpack_require__(10); + + var colors = __webpack_require__(1).colors; + + /** + Interface + */ + + var Interface = (function (_EventEmitter) { + function Interface(args, options, defaults) { + _classCallCheck(this, Interface); + + _get(Object.getPrototypeOf(Interface.prototype), "constructor", this).call(this); + this.type = this.constructor.name; + this.settings = this.parseSettings(args, options, defaults); + this.mouse = {}; + this.wait = false; + this.colors = {}; + var defaultColors = colors(); // jshint ignore:line + this.colors.accent = defaultColors.accent; + this.colors.fill = defaultColors.fill; + this.colors.light = defaultColors.light; + this.colors.dark = defaultColors.dark; + this.colors.mediumLight = defaultColors.mediumLight; + this.colors.mediumDark = defaultColors.mediumDark; + } + + _inherits(Interface, _EventEmitter); + + _createClass(Interface, { + parseSettings: { + value: function parseSettings(args, options, defaults) { + + options.unshift("target"); + defaults.defaultSize = defaults.size.splice(0, 2); + defaults.size = false; + + var settings = { + target: document.body, + colors: {}, // should inherit from a colors module, + snapWithParent: true, + event: function event() {}, + component: false + }; + + for (var key in defaults) { + settings[key] = defaults[key]; + } + + for (var i = 0; i < args.length; i++) { + // grabs the next argument + var setting = args[i]; + // if it's an object, it must be the settings object + if (util.isObject(setting)) { + for (var key in setting) { + settings[key] = setting[key]; + } + // if it's a function, it must be the event setting + } else if (typeof setting === "function") { + settings.event = setting; + // otherwise, consider it one of the widget's custom options + } else if (options.length >= 1) { + // grab the first option -- i.e. 'target' + var key = options.splice(0, 1)[0]; + settings[key] = setting; + } + } + + /* handle common settings */ + + // target + this.parent = dom.parseElement(settings.target); + + // nexus-ui attribute + if (this.parent && this.parent instanceof HTMLElement && !settings.component) { + if (!this.parent.hasAttribute("nexus-ui")) { + this.parent.setAttribute("nexus-ui", ""); + } + } + + // size + + if (settings.size && Array.isArray(settings.size) && settings.snapWithParent) { + this.width = settings.size[0]; + this.height = settings.size[1]; + this.parent.style.width = this.width + "px"; + this.parent.style.height = this.height + "px"; + } else if (settings.snapWithParent && !settings.component) { + + this.width = parseFloat(window.getComputedStyle(this.parent, null).getPropertyValue("width").replace("px", "")); + this.height = parseFloat(window.getComputedStyle(this.parent, null).getPropertyValue("height").replace("px", "")); + + if (this.width == 5000) { + this.width = settings.defaultSize[0]; + this.parent.style.width = this.parent.width = this.width + "px"; + } + if (this.height == 5000) { + this.height = settings.defaultSize[1]; + this.parent.style.height = this.parent.height = this.height + "px"; + } + } else { + settings.size = settings.defaultSize; + this.width = settings.size[0]; + this.height = settings.size[1]; + } + + // event + if (settings.event) { + this.event = this.on("change", settings.event); + } else { + this.event = false; + } + + return settings; + } + }, + init: { + value: function init() { + this.buildFrame(); + this.buildInterface(); + this.sizeInterface(); + this.attachListeners(); + this.colorInterface(); + this.finalTouches(); + } + }, + buildFrame: { + value: function buildFrame() { + this.element = svg.create("svg"); + this.element.setAttribute("width", this.width); + this.element.setAttribute("height", this.height); + this.parent.appendChild(this.element); + } + }, + buildInterface: { + value: function buildInterface() {} + }, + sizeInterface: { + value: function sizeInterface() {} + }, + colorInterface: { + value: function colorInterface() {} + }, + attachListeners: { + value: function attachListeners() { + var _this = this; + + this.interactionTarget = this.interactionTarget || this.element; + + // Setup interaction + if (touch.exists) { + this.interactionTarget.addEventListener("touchstart", function (evt) { + return _this.preTouch(evt); + }); + this.interactionTarget.addEventListener("touchmove", function (evt) { + return _this.preTouchMove(evt); + }); + this.interactionTarget.addEventListener("touchend", function (evt) { + return _this.preTouchRelease(evt); + }); + } + this.boundPreMove = function (evt) { + return _this.preMove(evt); + }; + this.boundPreRelease = function (evt) { + return _this.preRelease(evt); + }; + this.interactionTarget.addEventListener("mousedown", function (evt) { + return _this.preClick(evt); + }); + } + }, + finalTouches: { + value: function finalTouches() { + this.element.style.cursor = "pointer"; + } + }, + preClick: { + value: function preClick(e) { + // 10000 getComputedStyle calls takes 100 ms. + // .:. one takes about .01ms + if (this.element instanceof HTMLElement) { + this.width = window.getComputedStyle(this.element, null).getPropertyValue("width").replace("px", ""); + } + // 10000 getComputedStyle calls takes 40 ms. + // .:. one takes about .004ms + this.offset = dom.findPosition(this.element); + this.mouse = dom.locateMouse(e, this.offset); + this.clicked = true; + this.click(); + this.moveEvent = document.addEventListener("mousemove", this.boundPreMove); + this.releaseEvent = document.addEventListener("mouseup", this.boundPreRelease); + this.emit("click"); + e.preventDefault(); + e.stopPropagation(); + } + }, + preMove: { + value: function preMove(e) { + var _this = this; + + if (!this.wait) { + this.mouse = dom.locateMouse(e, this.offset); + this.move(); + this.wait = true; + setTimeout(function () { + _this.wait = false; + }, 25); + } + e.preventDefault(); + e.stopPropagation(); + } + }, + preRelease: { + value: function preRelease(e) { + this.mouse = dom.locateMouse(e, this.offset); + this.clicked = false; + this.release(); + this.emit("release"); + document.removeEventListener("mousemove", this.boundPreMove); + document.removeEventListener("mouseup", this.boundPreRelease); + e.preventDefault(); + e.stopPropagation(); + } + }, + click: { + value: function click() {} + }, + move: { + value: function move() {} + }, + release: { + value: function release() {} + }, + preTouch: { + + /* touch */ + + value: function preTouch(e) { + if (this.element instanceof HTMLElement) { + this.width = window.getComputedStyle(this.element, null).getPropertyValue("width").replace("px", ""); + } + this.offset = dom.findPosition(this.element); + this.mouse = dom.locateTouch(e, this.offset); + this.clicked = true; + this.touch(e); + this.emit("click"); + e.preventDefault(); + e.stopPropagation(); + } + }, + preTouchMove: { + value: function preTouchMove(e) { + if (this.clicked) { + this.mouse = dom.locateTouch(e, this.offset); + this.touchMove(); + e.preventDefault(); + e.stopPropagation(); + } + } + }, + preTouchRelease: { + value: function preTouchRelease(e) { + this.mouse = dom.locateTouch(e, this.offset); + this.clicked = false; + this.touchRelease(); + this.emit("release"); + e.preventDefault(); + e.stopPropagation(); + } + }, + touch: { + value: function touch() { + this.click(); + } + }, + touchMove: { + value: function touchMove() { + this.move(); + } + }, + touchRelease: { + value: function touchRelease() { + this.release(); + } + }, + resize: { + + /** + * Resize the interface + * @param width {number} New width in pixels + * @param height {number} New height in pixels + * + * @example + * button.resize(100,100); + */ + + value: function resize(width, height) { + this.width = width; + this.height = height; + this.parent.style.width = this.width + "px"; + this.parent.style.height = this.height + "px"; + this.element.setAttribute("width", this.width); + this.element.setAttribute("height", this.height); + this.sizeInterface(); + } + }, + empty: { + value: function empty() { + while (this.element.lastChild) { + this.element.removeChild(this.element.lastChild); + } + } + }, + destroy: { + + /** + * Remove the interface from the page and cancel its event listener(s). + * + * @example + * button.destroy(); + */ + + value: function destroy() { + this.empty(); + this.parent.removeChild(this.element); + this.removeAllListeners(); + if (this.instrument) { + delete this.instrument[this.id]; + } + this.customDestroy(); + } + }, + customDestroy: { + value: function customDestroy() {} + }, + colorize: { + value: function colorize(type, color) { + this.colors[type] = color; + this.colorInterface(); + } + } + }); + + return Interface; + })(EventEmitter); + + module.exports = Interface; + +/***/ }), +/* 7 */ +/***/ (function(module, exports) { + + "use strict"; + + exports.findPosition = function (el) { + var viewportOffset = el.getBoundingClientRect(); + var top = viewportOffset.top + window.scrollY; + var left = viewportOffset.left + window.scrollX; + return { top: top, left: left }; + }; + + exports.parseElement = function (parent) { + if (typeof parent === "string") { + parent = document.getElementById(parent.replace("#", "")); + } + + if (parent instanceof HTMLElement || parent instanceof SVGElement) { + return parent; + } else { + return "No valid parent argument"; + } + }; + + exports.locateMouse = function (e, offset) { + return { + x: e.pageX - offset.left, + y: e.pageY - offset.top + }; + }; + + exports.locateTouch = function (e, offset) { + return { + x: e.targetTouches.length ? e.targetTouches[0].pageX - offset.left : false, + y: e.targetTouches.length ? e.targetTouches[0].pageY - offset.top : false + }; + }; + + exports.SmartCanvas = function (parent) { + var _this = this; + + this.element = document.createElement("canvas"); + this.context = this.element.getContext("2d"); + parent.appendChild(this.element); + + this.resize = function (w, h) { + _this.element.width = w * 2; + _this.element.height = h * 2; + _this.element.style.width = w + "px"; + _this.element.style.height = h + "px"; + }; + }; + +/***/ }), +/* 8 */ +/***/ (function(module, exports) { + + "use strict"; + + exports.isObject = function (obj) { + if (typeof obj === "object" && !Array.isArray(obj) && obj !== null && obj instanceof SVGElement === false && obj instanceof HTMLElement === false) { + return true; + } else { + return false; + } + }; + + // Restricts input for the given textbox to the given inputFilter function + // cf https://stackoverflow.com/a/469362 + exports.setInputFilter = function (textbox, inputFilter) { + ["input", "keydown", "keyup", "mousedown", "mouseup", "select", "contextmenu", "drop"].forEach(function (event) { + textbox.addEventListener(event, function () { + if (inputFilter(this.value)) { + this.oldValue = this.value; + this.oldSelectionStart = this.selectionStart; + this.oldSelectionEnd = this.selectionEnd; + } else if (this.hasOwnProperty("oldValue")) { + this.value = this.oldValue; + this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd); + } else { + this.value = ""; + } + }); + }); + }; + +/***/ }), +/* 9 */ +/***/ (function(module, exports) { + + "use strict"; + + exports.exists = "ontouchstart" in document.documentElement; + +/***/ }), +/* 10 */ +/***/ (function(module, exports) { + + // Copyright Joyent, Inc. and other Node contributors. + // + // Permission is hereby granted, free of charge, to any person obtaining a + // copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to permit + // persons to whom the Software is furnished to do so, subject to the + // following conditions: + // + // The above copyright notice and this permission notice shall be included + // in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + function EventEmitter() { + this._events = this._events || {}; + this._maxListeners = this._maxListeners || undefined; + } + module.exports = EventEmitter; + + // Backwards-compat with node 0.10.x + EventEmitter.EventEmitter = EventEmitter; + + EventEmitter.prototype._events = undefined; + EventEmitter.prototype._maxListeners = undefined; + + // By default EventEmitters will print a warning if more than 10 listeners are + // added to it. This is a useful default which helps finding memory leaks. + EventEmitter.defaultMaxListeners = 10; + + // Obviously not all Emitters should be limited to 10. This function allows + // that to be increased. Set to zero for unlimited. + EventEmitter.prototype.setMaxListeners = function(n) { + if (!isNumber(n) || n < 0 || isNaN(n)) + throw TypeError('n must be a positive number'); + this._maxListeners = n; + return this; + }; + + EventEmitter.prototype.emit = function(type) { + var er, handler, len, args, i, listeners; + + if (!this._events) + this._events = {}; + + // If there is no 'error' event listener then throw. + if (type === 'error') { + if (!this._events.error || + (isObject(this._events.error) && !this._events.error.length)) { + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } else { + // At least give some kind of context to the user + var err = new Error('Uncaught, unspecified "error" event. (' + er + ')'); + err.context = er; + throw err; + } + } + } + + handler = this._events[type]; + + if (isUndefined(handler)) + return false; + + if (isFunction(handler)) { + switch (arguments.length) { + // fast cases + case 1: + handler.call(this); + break; + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + // slower + default: + args = Array.prototype.slice.call(arguments, 1); + handler.apply(this, args); + } + } else if (isObject(handler)) { + args = Array.prototype.slice.call(arguments, 1); + listeners = handler.slice(); + len = listeners.length; + for (i = 0; i < len; i++) + listeners[i].apply(this, args); + } + + return true; + }; + + EventEmitter.prototype.addListener = function(type, listener) { + var m; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events) + this._events = {}; + + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (this._events.newListener) + this.emit('newListener', type, + isFunction(listener.listener) ? + listener.listener : listener); + + if (!this._events[type]) + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener; + else if (isObject(this._events[type])) + // If we've already got an array, just append. + this._events[type].push(listener); + else + // Adding the second element, need to change to array. + this._events[type] = [this._events[type], listener]; + + // Check for listener leak + if (isObject(this._events[type]) && !this._events[type].warned) { + if (!isUndefined(this._maxListeners)) { + m = this._maxListeners; + } else { + m = EventEmitter.defaultMaxListeners; + } + + if (m && m > 0 && this._events[type].length > m) { + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + if (typeof console.trace === 'function') { + // not supported in IE 10 + console.trace(); + } + } + } + + return this; + }; + + EventEmitter.prototype.on = EventEmitter.prototype.addListener; + + EventEmitter.prototype.once = function(type, listener) { + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + var fired = false; + + function g() { + this.removeListener(type, g); + + if (!fired) { + fired = true; + listener.apply(this, arguments); + } + } + + g.listener = listener; + this.on(type, g); + + return this; + }; + + // emits a 'removeListener' event iff the listener was removed + EventEmitter.prototype.removeListener = function(type, listener) { + var list, position, length, i; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events || !this._events[type]) + return this; + + list = this._events[type]; + length = list.length; + position = -1; + + if (list === listener || + (isFunction(list.listener) && list.listener === listener)) { + delete this._events[type]; + if (this._events.removeListener) + this.emit('removeListener', type, listener); + + } else if (isObject(list)) { + for (i = length; i-- > 0;) { + if (list[i] === listener || + (list[i].listener && list[i].listener === listener)) { + position = i; + break; + } + } + + if (position < 0) + return this; + + if (list.length === 1) { + list.length = 0; + delete this._events[type]; + } else { + list.splice(position, 1); + } + + if (this._events.removeListener) + this.emit('removeListener', type, listener); + } + + return this; + }; + + EventEmitter.prototype.removeAllListeners = function(type) { + var key, listeners; + + if (!this._events) + return this; + + // not listening for removeListener, no need to emit + if (!this._events.removeListener) { + if (arguments.length === 0) + this._events = {}; + else if (this._events[type]) + delete this._events[type]; + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + for (key in this._events) { + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = {}; + return this; + } + + listeners = this._events[type]; + + if (isFunction(listeners)) { + this.removeListener(type, listeners); + } else if (listeners) { + // LIFO order + while (listeners.length) + this.removeListener(type, listeners[listeners.length - 1]); + } + delete this._events[type]; + + return this; + }; + + EventEmitter.prototype.listeners = function(type) { + var ret; + if (!this._events || !this._events[type]) + ret = []; + else if (isFunction(this._events[type])) + ret = [this._events[type]]; + else + ret = this._events[type].slice(); + return ret; + }; + + EventEmitter.prototype.listenerCount = function(type) { + if (this._events) { + var evlistener = this._events[type]; + + if (isFunction(evlistener)) + return 1; + else if (evlistener) + return evlistener.length; + } + return 0; + }; + + EventEmitter.listenerCount = function(emitter, type) { + return emitter.listenerCount(type); + }; + + function isFunction(arg) { + return typeof arg === 'function'; + } + + function isNumber(arg) { + return typeof arg === 'number'; + } + + function isObject(arg) { + return typeof arg === 'object' && arg !== null; + } + + function isUndefined(arg) { + return arg === void 0; + } + + +/***/ }), +/* 11 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var math = __webpack_require__(5); + + /** + Creates a steppable value with minimum, maximum, and step size. This is used in many interfaces to constrict their values to certain ranges. + @param {number} [min=0] minimum + @param {number} [max=1] maximum + @param {number} [step=0] + @param {number} [value=0] initial value + @returns {Object} Step + */ + + var Step = (function () { + function Step() { + var min = arguments[0] === undefined ? 0 : arguments[0]; + var max = arguments[1] === undefined ? 1 : arguments[1]; + var step = arguments[2] === undefined ? 0 : arguments[2]; + var value = arguments[3] === undefined ? 0 : arguments[3]; + + _classCallCheck(this, Step); + + //Object.assign(this,{min,max,step}); + //Cannot use Object.assign because not supported in Safari. + //I would expect for Babel to take care of this but it is not. + this.min = min; + this.max = max; + this.step = step; + this.value = value; + this.changed = false; + this.oldValue = false; + this.update(this.value); + } + + _createClass(Step, { + update: { + + /** + Update with a new value. The value will be auto-adjusted to fit the min/max/step. + @param {number} value + */ + + value: function update(value) { + if (this.step) { + // this.value = math.clip(Math.round(value / (this.step)) * this.step, this.min,this.max); + this.value = math.clip(Math.round((value - this.min) / this.step) * this.step + this.min, this.min, this.max); + } else { + this.value = math.clip(value, this.min, this.max); + } + if (this.oldValue !== this.value) { + this.oldValue = this.value; + this.changed = true; + } else { + this.changed = false; + } + return this.value; + } + }, + updateNormal: { + + /** + Update with a normalized value 0-1. + @param {number} value + */ + + value: function updateNormal(value) { + this.value = math.scale(value, 0, 1, this.min, this.max); + return this.update(this.value); + } + }, + normalized: { + + /** + Get a normalized version of this.value . Not settable. + */ + + get: function () { + return math.normalize(this.value, this.min, this.max); + } + } + }); + + return Step; + })(); + + module.exports = Step; + +/***/ }), +/* 12 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + "use strict"; + + var math = _interopRequire(__webpack_require__(5)); + + var ToggleModel = _interopRequire(__webpack_require__(13)); + + /* + how to use : + + dial.interaction = new Handle('radial','relative',this.width,this.height); + // dial.interaction.mode = 'relative' + // dial.interaction.direction = 'radial' + + on click: + dial.interaction.anchor = this.mouse; + + on move: + dial.interaction.update(this.mouse); + + console.log( dial.interaction.value ); should be a normalized value. + + */ + + /* + absolute/relative are property: mode + radial/vertical/horizontal/2d are property: direction + + plan : + + if relative -- + NO on click, get value offset between current value and click value. + NO on move, use click value - offset + INSTEAD + use delta -- bc vertical motion on dial is impossible otherwise + also allow to set sensitivity + + */ + + var Handle = exports.Handle = (function () { + function Handle() { + var mode = arguments[0] === undefined ? "absolute" : arguments[0]; + var direction = arguments[1] === undefined ? "vertical" : arguments[1]; + var xbound = arguments[2] === undefined ? [0, 100] : arguments[2]; + var ybound = arguments[3] === undefined ? [0, 100] : arguments[3]; + + _classCallCheck(this, Handle); + + this.mode = mode; + this.direction = direction; + this.previous = 0; + this.value = 0; + this.sensitivity = 1; + this.resize(xbound, ybound); + } + + _createClass(Handle, { + resize: { + value: function resize(xbound, ybound) { + this.boundary = { + min: { + x: xbound[0], + y: ybound[0] + }, + max: { + x: xbound[1], + y: ybound[1] + }, + center: { + x: (xbound[1] - xbound[0]) / 2 + xbound[0], + y: (ybound[1] - ybound[0]) / 2 + ybound[0] + } + }; + } + }, + anchor: { + set: function (mouse) { + this._anchor = this.convertPositionToValue(mouse); + }, + get: function () { + return this._anchor; + } + }, + update: { + value: function update(mouse) { + if (this.mode === "relative") { + var increment = this.convertPositionToValue(mouse) - this.anchor; + if (Math.abs(increment) > 0.5) { + increment = 0; + } + this.anchor = mouse; + this.value = this.value + increment * this.sensitivity; + } else { + this.value = this.convertPositionToValue(mouse); + } + this.value = math.clip(this.value, 0, 1); + } + }, + convertPositionToValue: { + value: function convertPositionToValue(current) { + switch (this.direction) { + case "radial": + var position = math.toPolar(current.x - this.boundary.center.x, current.y - this.boundary.center.y); + position = position.angle / (Math.PI * 2); + position = (position - 0.25 + 1) % 1; + return position; + case "vertical": + return math.scale(current.y, this.boundary.min.y, this.boundary.max.y, 0, 1); + case "horizontal": + return math.scale(current.x, this.boundary.min.x, this.boundary.max.x, 0, 1); + } + } + } + }); + + return Handle; + })(); + + var Button = exports.Button = (function () { + function Button() { + var mode = arguments[0] === undefined ? "button" : arguments[0]; + + _classCallCheck(this, Button); + + this.mode = mode; + this.state = new ToggleModel(); + this.paintbrush = false; + } + + _createClass(Button, { + click: { + value: function click() { + switch (this.mode) { + case "impulse": + this.state.on(); + if (this.timeout) { + clearTimeout(this.timeout); + } + this.timeout = setTimeout(this.state.off.bind(this), 30); + this.emit("change", this.state); + break; + case "button": + this.turnOn(); + this.emit("change", this.state); + break; + case "aftertouch": + this.position = { + x: math.clip(this.mouse.x / this.width, 0, 1), + y: math.clip(1 - this.mouse.y / this.height, 0, 1) + }; + this.turnOn(); + this.emit("change", { + state: this.state, + x: this.position.x, + y: this.position.y }); + break; + case "toggle": + this.flip(); + this.emit("change", this.state); + break; + } + } + }, + move: { + value: function move() { + if (this.mode === "aftertouch") { + this.position = { + x: math.clip(this.mouse.x / this.width, 0, 1), + y: math.clip(1 - this.mouse.y / this.height, 0, 1) + }; + this.emit("change", { + state: this.state, + x: this.position.x, + y: this.position.y }); + this.render(); + } + } + }, + release: { + value: function release() { + switch (this.mode) { + case "button": + this.turnOff(); + this.emit("change", this.state); + break; + case "aftertouch": + this.turnOff(); + this.position = { + x: this.mouse.x / this.width, + y: 1 - this.mouse.y / this.height + }; + this.emit("change", { + state: this.state, + x: this.position.x, + y: this.position.y }); + break; + } + } + } + }); + + return Button; + })(); + +/***/ }), +/* 13 */ +/***/ (function(module, exports) { + + "use strict"; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var Toggle = (function () { + function Toggle(state) { + _classCallCheck(this, Toggle); + + this.state = state || false; + } + + _createClass(Toggle, { + flip: { + value: function flip(state) { + if (state || state === false) { + this.state = state; + } else { + this.state = !this.state; + } + } + }, + on: { + value: function on() { + this.state = true; + } + }, + off: { + value: function off() { + this.state = false; + } + } + }); + + return Toggle; + })(); + + module.exports = Toggle; + +/***/ }), +/* 14 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { "default": obj }; }; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + + var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var svg = __webpack_require__(4); + var Interface = __webpack_require__(6); + var Step = __webpack_require__(11); + + var Interaction = _interopRequireWildcard(__webpack_require__(12)); + + /** + * Slider + * + * @description Horizontal or vertical slider with settable interaction modes. + * + * @demo + * + * @example + * var slider = new Nexus.Slider('#target') + * + * @example + * var slider = new Nexus.Slider('#target',{ + * 'size': [120,20], + * 'mode': 'relative', // 'relative' or 'absolute' + * 'min': 0, + * 'max': 1, + * 'step': 0, + * 'value': 0 + * }) + * + * @output + * change + * Fires when the interface's value changes.
+ * Event data: number The number value of the interface. + * + * @outputexample + * slider.on('change',function(v) { + * console.log(v); + * }) + * + * + */ + + var Slider = (function (_Interface) { + function Slider() { + _classCallCheck(this, Slider); + + var options = ["min", "max", "value"]; + + var defaults = { + size: [120, 20], + mode: "relative", // 'relative' or 'absolute' + min: 0, + max: 1, + step: 0, + value: 0 + }; + + _get(Object.getPrototypeOf(Slider.prototype), "constructor", this).call(this, arguments, options, defaults); + + this.orientation = "vertical"; // This will change automatically to 'horizontal'if the interface is wider than it is tall. + + this._value = new Step(this.settings.min, this.settings.max, this.settings.step, this.settings.value); + + this.position = new Interaction.Handle(this.settings.mode, this.orientation, [0, this.width], [this.height, 0]); + this.position.value = this._value.normalized; + + this.init(); + + this.position.direction = this.orientation; + + this.emit("change", this.value); + } + + _inherits(Slider, _Interface); + + _createClass(Slider, { + buildInterface: { + value: function buildInterface() { + + this.bar = svg.create("rect"); + this.fillbar = svg.create("rect"); + this.knob = svg.create("circle"); + + this.element.appendChild(this.bar); + this.element.appendChild(this.fillbar); + this.element.appendChild(this.knob); + } + }, + sizeInterface: { + value: function sizeInterface() { + + if (this.width < this.height) { + this.orientation = "vertical"; + this.position.direction = "vertical"; + } else { + this.orientation = "horizontal"; + this.position.direction = "horizontal"; + } + + if (this.position) { + this.position.resize([0, this.width], [this.height, 0]); + } + + var x = undefined, + y = undefined, + w = undefined, + h = undefined, + barOffset = undefined, + cornerRadius = undefined; + this.knobData = { + level: 0, + r: 0 + }; + + if (this.orientation === "vertical") { + this.thickness = this.width / 2; + x = this.width / 2; + y = 0; + w = this.thickness; + h = this.height; + this.knobData.r = this.thickness * 0.8; + this.knobData.level = h - this.knobData.r - this.normalized * (h - this.knobData.r * 2); + barOffset = "translate(" + this.thickness * -1 / 2 + ",0)"; + cornerRadius = w / 2; + } else { + this.thickness = this.height / 2; + x = 0; + y = this.height / 2; + w = this.width; + h = this.thickness; + this.knobData.r = this.thickness * 0.8; + this.knobData.level = this.normalized * (w - this.knobData.r * 2) + this.knobData.r; + barOffset = "translate(0," + this.thickness * -1 / 2 + ")"; + cornerRadius = h / 2; + } + + this.bar.setAttribute("x", x); + this.bar.setAttribute("y", y); + this.bar.setAttribute("transform", barOffset); + this.bar.setAttribute("rx", cornerRadius); // corner radius + this.bar.setAttribute("ry", cornerRadius); + this.bar.setAttribute("width", w); + this.bar.setAttribute("height", h); + + if (this.orientation === "vertical") { + this.fillbar.setAttribute("x", x); + this.fillbar.setAttribute("y", this.knobData.level); + this.fillbar.setAttribute("width", w); + this.fillbar.setAttribute("height", h - this.knobData.level); + } else { + this.fillbar.setAttribute("x", 0); + this.fillbar.setAttribute("y", y); + this.fillbar.setAttribute("width", this.knobData.level); + this.fillbar.setAttribute("height", h); + } + this.fillbar.setAttribute("transform", barOffset); + this.fillbar.setAttribute("rx", cornerRadius); + this.fillbar.setAttribute("ry", cornerRadius); + + if (this.orientation === "vertical") { + this.knob.setAttribute("cx", x); + this.knob.setAttribute("cy", this.knobData.level); + } else { + this.knob.setAttribute("cx", this.knobData.level); + this.knob.setAttribute("cy", y); + } + this.knob.setAttribute("r", this.knobData.r); + } + }, + colorInterface: { + value: function colorInterface() { + this.bar.setAttribute("fill", this.colors.fill); + this.fillbar.setAttribute("fill", this.colors.accent); + this.knob.setAttribute("fill", this.colors.accent); + } + }, + render: { + value: function render() { + if (!this.clicked) { + this.knobData.r = this.thickness * 0.75; + } + this.knob.setAttribute("r", this.knobData.r); + + if (this.orientation === "vertical") { + this.knobData.level = this.knobData.r + this._value.normalized * (this.height - this.knobData.r * 2); + this.knob.setAttribute("cy", this.height - this.knobData.level); + this.fillbar.setAttribute("y", this.height - this.knobData.level); + this.fillbar.setAttribute("height", this.knobData.level); + } else { + this.knobData.level = this._value.normalized * (this.width - this.knobData.r * 2) + this.knobData.r; + this.knob.setAttribute("cx", this.knobData.level); + this.fillbar.setAttribute("x", 0); + this.fillbar.setAttribute("width", this.knobData.level); + } + } + }, + click: { + value: function click() { + this.knobData.r = this.thickness * 0.9; + this.position.anchor = this.mouse; + this.move(); + } + }, + move: { + value: function move() { + if (this.clicked) { + this.position.update(this.mouse); + this._value.updateNormal(this.position.value); + this.emit("change", this._value.value); + this.render(); + } + } + }, + release: { + value: function release() { + this.render(); + } + }, + normalized: { + get: function () { + return this._value.normalized; + } + }, + value: { + + /** + The slider's current value. If set manually, will update the interface and trigger the output event. + @type {number} + @example slider.value = 10; + */ + + get: function () { + return this._value.value; + }, + set: function (v) { + this._value.update(v); + this.position.value = this._value.normalized; + this.emit("change", this._value.value); + this.render(); + } + }, + min: { + + /** + Lower limit of the sliders's output range + @type {number} + @example slider.min = 1000; + */ + + get: function () { + return this._value.min; + }, + set: function (v) { + this._value.min = v; + } + }, + max: { + + /** + Upper limit of the slider's output range + @type {number} + @example slider.max = 1000; + */ + + get: function () { + return this._value.max; + }, + set: function (v) { + this._value.max = v; + } + }, + step: { + + /** + The increment that the slider's value changes by. + @type {number} + @example slider.step = 5; + */ + + get: function () { + return this._value.step; + }, + set: function (v) { + this._value.step = v; + } + }, + mode: { + + /** + Absolute mode (slider's value jumps to mouse click position) or relative mode (mouse drag changes value relative to its current position). Default: "relative". + @type {string} + @example slider.mode = "relative"; + */ + + get: function () { + return this.position.mode; + }, + set: function (v) { + this.position.mode = v; + } + } + }); + + return Slider; + })(Interface); + + module.exports = Slider; + +/***/ }), +/* 15 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + + var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var svg = __webpack_require__(4); + var ToggleModel = __webpack_require__(13); + var Interface = __webpack_require__(6); + + /** + * Toggle + * + * @description Binary switch + * + * @demo + * + * @example + * var toggle = new Nexus.Toggle('#target') + * + * @example + * var toggle = new Nexus.Toggle('#target',{ + * 'size': [40,20], + * 'state': false + * }) + * + * @output + * change + * Fires any time the interface's value changes.
+ * Parameter: The boolean state of the interface. + * + * @outputexample + * toggle.on('change',function(v) { + * console.log(v); + * }) + * + * + */ + + var Toggle = (function (_Interface) { + function Toggle() { + _classCallCheck(this, Toggle); + + var options = ["value"]; + + var defaults = { + size: [40, 20], + target: false, + state: false + }; + + _get(Object.getPrototypeOf(Toggle.prototype), "constructor", this).call(this, arguments, options, defaults); + + this._state = new ToggleModel(this.settings.state); + + this.init(); + } + + _inherits(Toggle, _Interface); + + _createClass(Toggle, { + buildInterface: { + value: function buildInterface() { + + this.bar = svg.create("rect"); + this.knob = svg.create("circle"); + this.element.appendChild(this.bar); + this.element.appendChild(this.knob); + } + }, + sizeInterface: { + value: function sizeInterface() { + + if (this.height < this.width / 2) { + this.knobSize = this.height / 2; + } else { + this.knobSize = this.width / 4; + } + + this.bar.setAttribute("x", this.width / 2 - this.knobSize * 1.5); + this.bar.setAttribute("y", this.height / 2 - this.knobSize / 2); + this.bar.setAttribute("rx", this.knobSize / 2); + this.bar.setAttribute("ry", this.knobSize / 2); + this.bar.setAttribute("width", this.knobSize * 3); + this.bar.setAttribute("height", this.knobSize); + + this.knob.setAttribute("cx", this.width / 2 - this.knobSize); + this.knob.setAttribute("cy", this.height / 2); + this.knob.setAttribute("r", this.knobSize); + } + }, + colorInterface: { + value: function colorInterface() { + this.knob.setAttribute("fill", this.colors.accent); + this.render(); + } + }, + render: { + value: function render() { + if (!this.state) { + this.knob.setAttribute("cx", this.width / 2 - this.knobSize); + this.bar.setAttribute("fill", this.colors.fill); + } else { + this.knob.setAttribute("cx", this.width / 2 + this.knobSize); + this.bar.setAttribute("fill", this.colors.accent); + } + } + }, + click: { + value: function click() { + this.flip(); + this.render(); + this.emit("change", this.state); + } + }, + state: { + + /** + Whether the toggle is currently on or off. Setting this property will update the toggle interface and trigger the output event. + @type {boolean} + @example toggle.state = false; + */ + + get: function () { + return this._state.state; + }, + set: function (value) { + this._state.flip(value); + this.emit("change", this.state); + this.render(); + } + }, + flip: { + + /** + * Switch the toggle state to its opposite state + * @example + * toggle.flip(); + */ + + value: function flip() { + this._state.flip(); + this.render(); + } + } + }); + + return Toggle; + })(Interface); + + module.exports = Toggle; + +/***/ }), +/* 16 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + + var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var svg = __webpack_require__(4); + var ButtonTemplate = __webpack_require__(17); + + /** + * Button + * + * @description Circular button with optional aftertouch. + * + * @demo + * + * @example + * var button = new Nexus.Button('#target') + * + * @example + * var button = new Nexus.Button('#target',{ + * 'size': [80,80], + * 'mode': 'aftertouch', + * 'state': false + * }) + * + * @output + * change + * Fires any time the interface's value changes.
+ * In button mode, toggle mode, and impulse mode, the output data is a boolean describing the state of the button.
+ * In aftertouch mode, the output data is an object containing x (0-1) and y (0-1) positions of aftertouch. + * + * @outputexample + * button.on('change',function(v) { + * // v is the value of the button + * console.log(v); + * }) + * + */ + + var Button = (function (_ButtonTemplate) { + function Button() { + _classCallCheck(this, Button); + + var options = ["mode"]; + + var defaults = { + size: [80, 80], + mode: "aftertouch", // button, aftertouch, impulse, toggle + state: false + }; + + _get(Object.getPrototypeOf(Button.prototype), "constructor", this).call(this, arguments, options, defaults); + + /** + * Interaction mode: supports "button", "aftertouch", "impulse", or "toggle" + * @type {string} + * @example button.mode = 'toggle'; + */ + this.mode = this.settings.mode; + + this.init(); + this.render(); + } + + _inherits(Button, _ButtonTemplate); + + _createClass(Button, { + buildInterface: { + value: function buildInterface() { + this.pad = svg.create("circle"); + this.element.appendChild(this.pad); + + this.interactionTarget = this.pad; + + // only used if in 'aftertouch' mode + this.defs = svg.create("defs"); + this.element.appendChild(this.defs); + + this.gradient = svg.radialGradient(this.defs, 2); + + this.gradient.stops[0].setAttribute("offset", "30%"); + + this.gradient.stops[1].setAttribute("offset", "100%"); + } + }, + sizeInterface: { + value: function sizeInterface() { + + this.pad.setAttribute("cx", this.width / 2); + this.pad.setAttribute("cy", this.height / 2); + this.pad.setAttribute("r", Math.min(this.width, this.height) / 2 - this.width / 40); + this.pad.setAttribute("stroke-width", this.width / 20); + } + }, + colorInterface: { + value: function colorInterface() { + + this.gradient.stops[0].setAttribute("stop-color", this.colors.accent); + this.gradient.stops[1].setAttribute("stop-color", this.colors.fill); + this.render(); + } + }, + render: { + + /* + * Update the visual interface using its current state + * + * @example + * button.render(); + */ + + value: function render() { + if (!this.state) { + this.pad.setAttribute("fill", this.colors.fill); + this.pad.setAttribute("stroke", this.colors.mediumLight); + } else { + if (this.mode === "aftertouch") { + this.pad.setAttribute("stroke", "url(#" + this.gradient.id + ")"); + this.gradient.element.setAttribute("cx", this.position.x * 100 + "%"); + this.gradient.element.setAttribute("cy", (1 - this.position.y) * 100 + "%"); + } else { + this.pad.setAttribute("stroke", this.colors.accent); + } + this.pad.setAttribute("fill", this.colors.accent); + } + } + } + }); + + return Button; + })(ButtonTemplate); + + module.exports = Button; + +/***/ }), +/* 17 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + + var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var svg = __webpack_require__(4); + var math = __webpack_require__(5); + var ToggleModel = __webpack_require__(13); + var Interface = __webpack_require__(6); + + /** + Button Template + */ + + var ButtonTemplate = (function (_Interface) { + function ButtonTemplate(args, options, defaults) { + _classCallCheck(this, ButtonTemplate); + + _get(Object.getPrototypeOf(ButtonTemplate.prototype), "constructor", this).call(this, args, options, defaults); + + this.mode = this.settings.mode || "button"; + + this.position = { + x: 0, + y: 0 + }; + + this._state = new ToggleModel(this.settings.state); + } + + _inherits(ButtonTemplate, _Interface); + + _createClass(ButtonTemplate, { + buildInterface: { + value: function buildInterface() { + this.pad = svg.create("circle"); + this.pad.setAttribute("fill", "#d18"); + this.pad.setAttribute("stroke", "#d18"); + this.pad.setAttribute("stroke-width", 4); + + this.element.appendChild(this.pad); + + this.interactionTarget = this.pad; + + this.sizeInterface(); + } + }, + sizeInterface: { + value: function sizeInterface() { + this.pad.setAttribute("cx", this.width / 2); + this.pad.setAttribute("cy", this.height / 2); + this.pad.setAttribute("r", Math.min(this.width, this.height) / 2 - 2); + } + }, + render: { + value: function render() { + if (!this.state) { + this.pad.setAttribute("fill", this.colors.fill); + this.pad.setAttribute("stroke", this.colors.mediumLight); + } else { + this.pad.setAttribute("fill", this.colors.accent); + this.pad.setAttribute("stroke", this.colors.accent); + } + } + }, + down: { + value: function down(paintbrush) { + switch (this.mode) { + case "impulse": + this.turnOn(); + if (this.timeout) { + clearTimeout(this.timeout); + } + this.timeout = setTimeout(this.turnOff.bind(this), 30); + // this.emit('change',this.state); + break; + case "button": + this.turnOn(); + // this.emit('change',this.state); + break; + case "aftertouch": + this.position = { + x: math.clip(this.mouse.x / this.width, 0, 1), + y: math.clip(1 - this.mouse.y / this.height, 0, 1) + }; + this.turnOn(); + // this.emit('change',{ + // state: this.state, + // x: this.position.x, + // y: this.position.y, + // }); + break; + case "toggle": + this.flip(paintbrush); + // this.emit('change',this.state); + break; + } + } + }, + bend: { + value: function bend(mouse) { + if (this.mode === "aftertouch") { + this.mouse = mouse || this.mouse; + this.position = { + x: math.clip(this.mouse.x / this.width, 0, 1), + y: math.clip(1 - this.mouse.y / this.height, 0, 1) + }; + this.emit("change", { + state: this.state, + x: this.position.x, + y: this.position.y }); + this.render(); + } + } + }, + up: { + value: function up() { + switch (this.mode) { + case "button": + this.turnOff(); + // this.emit('change',this.state); + break; + case "aftertouch": + this.turnOff(); + this.position = { + x: math.clip(this.mouse.x / this.width, 0, 1), + y: math.clip(1 - this.mouse.y / this.height, 0, 1) + }; + // this.emit('change',{ + // state: this.state, + // x: this.position.x, + // y: this.position.y, + // }); + break; + } + } + }, + click: { + + /* overwritable interaction handlers */ + + value: function click() { + this.down(); + } + }, + move: { + value: function move() { + this.bend(); + } + }, + release: { + value: function release() { + this.up(); + } + }, + state: { + + /** + Whether the button is on (pressed) or off (not pressed) + @type {boolean} + @example button.state = true; + */ + + get: function () { + return this._state.state; + }, + set: function (value) { + this._state.flip(value); + if (this.mode === "aftertouch") { + this.emit("change", { + state: this.state, + x: this.position.x, + y: this.position.y }); + } else { + this.emit("change", this.state); + } + this.render(); + } + }, + flip: { + + /** + Change the button to its alternate state (off=>on, on=>off), or flip it to a specified state. + @param value {boolean} (Optional) State to flip to. + @example button.flip(); + */ + + value: function flip(value) { + this._state.flip(value); + if (this.mode === "aftertouch") { + this.emit("change", { + state: this.state, + x: this.position.x, + y: this.position.y }); + } else { + this.emit("change", this.state); + } + this.render(); + } + }, + turnOn: { + + /** + Turn the button's state to true. + @example button.turnOn(); + */ + + value: function turnOn(emitting) { + this._state.on(); + if (emitting !== false) { + if (this.mode === "aftertouch") { + this.emit("change", { + state: this.state, + x: this.position.x, + y: this.position.y }); + } else { + this.emit("change", this.state); + } + } + this.render(); + } + }, + turnOff: { + + /** + Turn the button's state to false. + @example button.turnOff(); + */ + + value: function turnOff(emitting) { + this._state.off(); + if (emitting !== false) { + if (this.mode === "aftertouch") { + this.emit("change", { + state: this.state, + x: this.position.x, + y: this.position.y }); + } else { + this.emit("change", this.state); + } + } + this.render(); + } + } + }); + + return ButtonTemplate; + })(Interface); + + module.exports = ButtonTemplate; + +/***/ }), +/* 18 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + + var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var ButtonTemplate = __webpack_require__(17); + + /** + * TextButton + * + * @description Text button + * + * @demo + * + * @example + * var textbutton = new Nexus.TextButton('#target') + * + * @example + * var textbutton = new Nexus.TextButton('#target',{ + * 'size': [150,50], + * 'state': false, + * 'text': 'Play', + * 'alternateText': 'Stop' + * }) + * + * @output + * change + * Fires any time the interface's value changes.
+ * The event data is a string of the text on the button at the moment it was clicked. + * + * @outputexample + * textbutton.on('change',function(v) { + * console.log(v); + * }) + * + */ + + var TextButton = (function (_ButtonTemplate) { + function TextButton() { + _classCallCheck(this, TextButton); + + var options = ["value"]; + + var defaults = { + size: [150, 50], + state: false, + text: "Play" + }; + + _get(Object.getPrototypeOf(TextButton.prototype), "constructor", this).call(this, arguments, options, defaults); + + this._text = this.settings.text; + + if (this.settings.alternate) { + //TODO: Remove this conditional in a breaking-changes release + this.settings.alternateText = this.settings.alternate; + console.warn("'alternate' initiator is deprecated. Use 'alternateText' instead."); + } + this._alternateText = this.settings.alternateText; + this.mode = this.settings.alternateText ? "toggle" : "button"; + this.init(); + this.render(); + + this.state = this.settings.state; + } + + _inherits(TextButton, _ButtonTemplate); + + _createClass(TextButton, { + buildFrame: { + value: function buildFrame() { + + this.element = document.createElement("div"); + this.parent.appendChild(this.element); + + this.textElement = document.createElement("div"); + this.textElement.innerHTML = this._text; + this.element.appendChild(this.textElement); + } + }, + buildInterface: { + value: function buildInterface() {} + }, + colorInterface: { + value: function colorInterface() { + this.element.style.color = this.colors.dark; + this.render(); + } + }, + sizeInterface: { + value: function sizeInterface() { + var textsize = this.height / 3; + var textsize2 = this.width / (this._text.length + 2); + textsize = Math.min(textsize, textsize2); + if (this.alternateText) { + var textsize3 = this.width / (this.alternateText.length + 2); + textsize = Math.min(textsize, textsize3); + } + var styles = "width: " + this.width + "px;"; + styles += "height: " + this.height + "px;"; + styles += "padding: " + (this.height - textsize) / 2 + "px 0px;"; + styles += "box-sizing: border-box;"; + styles += "text-align: center;"; + styles += "font-family: inherit;"; + styles += "font-weight: 700;"; + styles += "opacity: 1;"; + styles += "font-size:" + textsize + "px;"; + this.textElement.style.cssText = styles; + this.render(); + } + }, + render: { + value: function render() { + if (!this.state) { + this.element.style.backgroundColor = this.colors.fill; + this.textElement.style.color = this.colors.dark; + this.textElement.innerHTML = this._text; + } else { + this.element.style.backgroundColor = this.colors.accent; + this.textElement.style.color = this.colors.fill; + if (this.alternateText) { + this.textElement.innerHTML = this._alternateText; + } else { + this.textElement.innerHTML = this._text; + } + } + } + }, + alternateText: { + + /** + The text to display when the button is in its "on" state. If set, this puts the button in "toggle" mode. + @type {String} + */ + + get: function () { + return this._alternateText; + }, + set: function (text) { + if (text) { + this.mode = "toggle"; + } else { + this.mode = "button"; + } + this._alternateText = text; + this.render(); + } + }, + text: { + + /** + The text to display. (If .alternateText exists, then this .text will only be displayed when the button is in its "off" state.) + @type {String} + */ + + get: function () { + return this._text; + }, + set: function (text) { + this._text = text; + this.sizeInterface(); + this.render(); + } + } + }); + + return TextButton; + })(ButtonTemplate); + + module.exports = TextButton; + +/***/ }), +/* 19 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + + var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + //let svg = require('../util/svg'); + var Interface = __webpack_require__(6); + var Button = __webpack_require__(16); + + /** + * RadioButton + * + * @description An array of buttons. By default, selecting one button will deselect all other buttons, but this can be customized using the API below. + * + * @demo
+ * + * @example + * var radiobutton = new Nexus.RadioButton('#target') + * + * @example + * var radiobutton = new Nexus.RadioButton('#target',{ + * 'size': [120,25], + * 'numberOfButtons': 4, + * 'active': -1 + * }) + * + * @output + * change + * Fires any time the interface's value changes.
+ * The event data an integer, the index of the button that is currently on. If no button is selected, the value will be -1. + * + * @outputexample + * radiobutton.on('change',function(v) { + * console.log(v); + * }) + * + */ + + var RadioButton = (function (_Interface) { + function RadioButton() { + _classCallCheck(this, RadioButton); + + var options = ["value"]; + + var defaults = { + size: [120, 25], + numberOfButtons: 4, + active: -1 + }; + + _get(Object.getPrototypeOf(RadioButton.prototype), "constructor", this).call(this, arguments, options, defaults); + + this.buttons = []; + this._numberOfButtons = this.settings.numberOfButtons; + this.active = this.settings.active; + + this.init(); + this.render(); + } + + _inherits(RadioButton, _Interface); + + _createClass(RadioButton, { + buildFrame: { + value: function buildFrame() { + this.element = document.createElement("div"); + this.parent.appendChild(this.element); + } + }, + buildInterface: { + value: function buildInterface() { + + for (var i = 0; i < this._numberOfButtons; i++) { + var container = document.createElement("span"); + + var button = new Button(container, { + mode: "toggle", + component: true }, this.update.bind(this, i)); + + this.buttons.push(button); + this.element.appendChild(container); + } + } + }, + sizeInterface: { + value: function sizeInterface() { + + var buttonWidth = this.width / this._numberOfButtons; + var buttonHeight = this.height; + + for (var i = 0; i < this._numberOfButtons; i++) { + this.buttons[i].resize(buttonWidth, buttonHeight); + } + } + }, + colorInterface: { + value: function colorInterface() { + for (var i = 0; i < this._numberOfButtons; i++) { + this.buttons[i].colors = this.colors; + this.buttons[i].render(); + } + } + }, + update: { + value: function update(index) { + if (this.buttons[index].state) { + this.select(index); + } else { + this.deselect(); + } + // this.render(); + } + }, + render: { + value: function render() { + for (var i = 0; i < this.buttons.length; i++) { + if (i === this.active) { + this.buttons[i].turnOn(false); + } else { + this.buttons[i].turnOff(false); + } + } + } + }, + select: { + + /** + Select one button and deselect all other buttons. + @param index {number} The index of the button to select + */ + + value: function select(index) { + if (index >= 0 && index < this.buttons.length) { + this.active = index; + this.emit("change", this.active); + this.render(); + } + } + }, + deselect: { + + /** + Deselect all buttons. + */ + + value: function deselect() { + this.active = -1; + this.emit("change", this.active); + this.render(); + } + }, + numberOfButtons: { + get: function () { + return this._numberOfButtons; + }, + + /** + * Update how many buttons are in the interface + * @param {number} buttons How many buttons are in the interface + */ + set: function (buttons) { + this._numberOfButtons = buttons; + for (var i = 0; i < this.buttons.length; i++) { + this.buttons[i].destroy(); + } + this.buttons = []; + // for (let i=0;i + * + * @example + * var number = new Nexus.Number('#target') + * + * @example + * var number = new Nexus.Number('#target',{ + * 'size': [60,30], + * 'value': 0, + * 'min': 0, + * 'max': 20000, + * 'step': 1 + * }) + * + * @output + * change + * Fires any time the interface's value changes.
+ * The event data is the number value of the interface. + * + * @outputexample + * number.on('change',function(v) { + * console.log(v); + * }) + * + * + */ + + var Number = (function (_Interface) { + function Number() { + _classCallCheck(this, Number); + + var options = ["value"]; + + var defaults = { + size: [60, 30], + value: 0, + min: 0, + max: 20000, + step: 1 + }; + + _get(Object.getPrototypeOf(Number.prototype), "constructor", this).call(this, arguments, options, defaults); + + this._value = new Step(this.settings.min, this.settings.max, this.settings.step, this.settings.value); + + /* + Default: 2. How many decimal places to clip the number's visual rendering to. This does not affect number's actual value output -- for that, set the step property to .01, .1, or 1. + @type {number} + @example number.decimalPlaces = 2; + */ + this.decimalPlaces = 2; + this.actual = 0; + + this.max = this._value.max; + + this.min = this._value.min; + + this.step = this._value.step; + + this.init(); + this.render(); + } + + _inherits(Number, _Interface); + + _createClass(Number, { + buildFrame: { + value: function buildFrame() { + this.element = document.createElement("input"); + this.element.type = "text"; + + this.element.addEventListener("blur", (function () { + this.element.style.backgroundColor = this.colors.fill; + this.element.style.color = this.colors.dark; + if (this.element.value !== this.value) { + this.value = parseFloat(this.element.value); + this.render(); + } + }).bind(this)); + + util.setInputFilter(this.element, function (value) { + return /^\d*\.?\d*$/.test(value); + }); + + this.element.addEventListener("keydown", (function (e) { + if (e.which === 13) { + this.element.blur(); + this.value = this.element.value; + this.emit("change", this.value); + this.render(); + } + }).bind(this), true); + + this.parent.appendChild(this.element); + } + }, + sizeInterface: { + value: function sizeInterface() { + + this._minDimension = Math.min(this.width, this.height); + + var styles = "width: " + this.width + "px;"; + styles += "height: " + this.height + "px;"; + styles += "background-color: #e7e7e7;"; + styles += "color: #333;"; + styles += "font-family: arial;"; + styles += "font-weight: 500;"; + styles += "font-size:" + this._minDimension / 2 + "px;"; + // styles += 'highlight: #d18;'; + styles += "border: none;"; + styles += "outline: none;"; + styles += "padding: " + this._minDimension / 4 + "px " + this._minDimension / 4 + "px;"; + styles += "box-sizing: border-box;"; + styles += "userSelect: text;"; + styles += "mozUserSelect: text;"; + styles += "webkitUserSelect: text;"; + this.element.style.cssText += styles; + + // to add eventually + // var css = '#'+this.elementID+'::selection{ background-color: transparent }'; + + this.element.value = this.value; + } + }, + colorInterface: { + value: function colorInterface() { + this.element.style.backgroundColor = this.colors.fill; + this.element.style.color = this.colors.dark; + } + }, + render: { + value: function render() { + + this.element.value = math.prune(this.value, this.decimalPlaces); + } + }, + click: { + value: function click() { + this.hasMoved = false; + this.element.readOnly = true; + this.actual = this.value; + this.initial = { y: this.mouse.y }; + this.changeFactor = math.invert(this.mouse.x / this.width); + } + }, + move: { + value: function move() { + this.hasMoved = true; + if (this.clicked) { + + var newvalue = this.actual - (this.mouse.y - this.initial.y) * (math.clip(this.max - this.min, 0, 1000) / 200) * Math.pow(this.changeFactor, 2); + this.value = newvalue; + + this.render(); + if (this._value.changed) { + this.emit("change", this.value); + } + } + } + }, + release: { + value: function release() { + if (!this.hasMoved) { + this.element.readOnly = false; + this.element.focus(); + this.element.setSelectionRange(0, this.element.value.length); + this.element.style.backgroundColor = this.colors.accent; + this.element.style.color = this.colors.light; + } else { + document.body.focus(); + } + } + }, + link: { + + /** + Connect this number interface to a dial or slider + @param {Interface} element Element to connect to. + @example number.link(slider) + */ + + value: function link(destination) { + var _this = this; + + this.min = destination.min; + this.max = destination.max; + this.step = destination.step; + destination.on("change", function (v) { + _this.passiveUpdate(v); + }); + this.on("change", function (v) { + destination.value = v; + }); + this.value = destination.value; + /* return { + listener1: listener1, + listener2: listener2, + destroy: () => { + listener1.remove() (or similar) + listener2.remove() (or similar) + } + } */ + } + }, + passiveUpdate: { + value: function passiveUpdate(v) { + this._value.update(v); + this.render(); + } + }, + value: { + + /** + The interface's current value. If set manually, will update the interface and trigger the output event. + @type {number} + @example number.value = 10; + */ + + get: function () { + return this._value.value; + }, + set: function (v) { + this._value.update(v); + this.emit("change", this.value); + this.render(); + } + }, + min: { + + /** + Lower limit of the number's output range + @type {number} + @example number.min = 1000; + */ + + get: function () { + return this._value.min; + }, + set: function (v) { + this._value.min = v; + } + }, + max: { + + /** + Upper limit of the number's output range + @type {number} + @example number.max = 1000; + */ + + get: function () { + return this._value.max; + }, + set: function (v) { + this._value.max = v; + } + }, + step: { + + /** + The increment that the number's value changes by. + @type {number} + @example number.step = 5; + */ + + get: function () { + return this._value.step; + }, + set: function (v) { + this._value.step = v; + } + } + }); + + return Number; + })(Interface); + + module.exports = Number; + +/***/ }), +/* 21 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + + var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var Interface = __webpack_require__(6); + + /** + * Select + * + * @description Dropdown menu + * + * @demo + * + * @example + * var select = new Nexus.Select('#target') + * + * @example + * var select = new Nexus.Select('#target',{ + * 'size': [100,30], + * 'options': ['default','options'] + * }) + * + * @output + * change + * Fires any time the interface's value changes.
+ * The event data is an object containing the text value of the selected option, as well as the numeric index of the selection. + * + * @outputexample + * select.on('change',function(v) { + * console.log(v); + * }) + * + * + */ + + var Select = (function (_Interface) { + function Select() { + _classCallCheck(this, Select); + + var options = ["value"]; + + var defaults = { + size: [100, 30], + options: ["default", "options"] + }; + + _get(Object.getPrototypeOf(Select.prototype), "constructor", this).call(this, arguments, options, defaults); + + this._selectedIndex = -1; + this._value = false; + + this._options = this.settings.options; + + this.init(); + this.render(); + } + + _inherits(Select, _Interface); + + _createClass(Select, { + buildFrame: { + value: function buildFrame() { + this.element = document.createElement("select"); + this.element.style.fontSize = this.height / 2 + "px"; + this.element.style.outline = "none"; + this.element.style.highlight = "none"; + this.element.style.width = this.width + "px"; + this.element.style.height = this.height + "px"; + + this.boundRender = this.render.bind(this); + + this.element.addEventListener("change", this.boundRender); + + this.parent.appendChild(this.element); + } + }, + attachListeners: { + value: function attachListeners() {} + }, + buildInterface: { + value: function buildInterface() { + + this.defineOptions(); + } + }, + colorInterface: { + value: function colorInterface() { + this.element.style.backgroundColor = this.colors.fill; + this.element.style.color = this.colors.dark; + this.element.style.border = "solid 0px " + this.colors.mediumLight; + } + }, + render: { + value: function render() { + + this._value = this.element.options[this.element.selectedIndex].text; + this._selectedIndex = this.element.selectedIndex; + this.emit("change", { + value: this._value, + index: this._selectedIndex + }); + } + }, + click: { + value: function click() {} + }, + move: { + value: function move() {} + }, + release: { + value: function release() {} + }, + defineOptions: { + + /** + * Update the list of options. This removes all existing options and creates a new list of options. + * @param {array} options New array of options + */ + + value: function defineOptions(options) { + + /* function removeOptions(selectbox) + { + var i; + for(i = selectbox.options.length - 1 ; i >= 0 ; i--) + { + selectbox.remove(i); + } + } + //using the function: + removeOptions(document.getElementById("mySelectObject")); */ + + if (options) { + this._options = options; + } + + for (var i = this.element.options.length - 1; i >= 0; i--) { + this.element.remove(i); + } + + for (var i = 0; i < this._options.length; i++) { + this.element.options.add(new Option(this._options[i], i)); + } + } + }, + value: { + + /** + The text of the option that is currently selected. If set, will update the interface and trigger the output event. + @type {String} + @example select.value = "sawtooth"; + */ + + get: function () { + return this._value; + }, + set: function (v) { + this._value = v; + for (var i = 0; i < this.element.options.length; i++) { + if (v === this.element.options[i].text) { + this.selectedIndex = i; + break; + } + } + } + }, + selectedIndex: { + + /** + The numeric index of the option that is currently selected. If set, will update the interface and trigger the output event. + @type {number} + @example select.selectedIndex = 2; + */ + + get: function () { + return this._selectedIndex; + }, + set: function (v) { + this._selectedIndex = v; + this.element.selectedIndex = v; + this.render(); + } + }, + customDestroy: { + value: function customDestroy() { + this.element.removeEventListener("change", this.boundRender); + } + } + }); + + return Select; + })(Interface); + + module.exports = Select; + +/***/ }), +/* 22 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { "default": obj }; }; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + + var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var svg = __webpack_require__(4); + var math = __webpack_require__(5); + var Interface = __webpack_require__(6); + var Step = __webpack_require__(11); + + var Interaction = _interopRequireWildcard(__webpack_require__(12)); + + /** + * Dial + * + * + * @description Dial with radial or linear interaction. + * + * @demo + * + * @example + * var dial = new Nexus.Dial('#target') + * + * @example + * var dial = new Nexus.Dial('#target',{ + * 'size': [75,75], + * 'interaction': 'radial', // "radial", "vertical", or "horizontal" + * 'mode': 'relative', // "absolute" or "relative" + * 'min': 0, + * 'max': 1, + * 'step': 0, + * 'value': 0 + * }) + * + * @output + * change + * Fires any time the interface's value changes.
+ * The event data is the number value of the interface. + * + * @outputexample + * dial.on('change',function(v) { + * console.log(v); + * }) + * + * @tutorial + * Dial + * ygGMxq + * + */ + + var Dial = (function (_Interface) { + function Dial() { + _classCallCheck(this, Dial); + + var options = ["min", "max", "value"]; + + var defaults = { + size: [75, 75], + interaction: "radial", // radial, vertical, horizontal + mode: "relative", // absolute, relative + min: 0, + max: 1, + step: 0, + value: 0 + }; + + _get(Object.getPrototypeOf(Dial.prototype), "constructor", this).call(this, arguments, options, defaults); + + this.interaction = this.settings.interaction; + + this._value = new Step(this.settings.min, this.settings.max, this.settings.step, this.settings.value); + + this.position = new Interaction.Handle(this.settings.mode, this.interaction, [0, this.width], [this.height, 0]); + + this.init(); + + this.value = this._value.value; + + this.position.value = this._value.normalized; + + this.previousAngle = false; + + this.emit("change", this.value); + } + + _inherits(Dial, _Interface); + + _createClass(Dial, { + buildInterface: { + value: function buildInterface() { + + this.background = svg.create("circle"); + this.screw = svg.create("circle"); + this.handle = svg.create("path"); + this.handle2 = svg.create("path"); + this.handleFill = svg.create("path"); + this.handle2Fill = svg.create("path"); + this.handleLine = svg.create("path"); + + this.element.appendChild(this.background); + this.element.appendChild(this.handle); + this.element.appendChild(this.handle2); + this.element.appendChild(this.handleFill); + this.element.appendChild(this.handle2Fill); + this.element.appendChild(this.handleLine); + this.element.appendChild(this.screw); + } + }, + sizeInterface: { + value: function sizeInterface() { + + this.position.resize([0, this.width], [this.height, 0]); + + var center = { + x: this.width / 2, + y: this.height / 2 + }; + + var diameter = Math.min(this.width, this.height); + + this.background.setAttribute("cx", center.x); + this.background.setAttribute("cy", center.y); + this.background.setAttribute("r", diameter / 2 - diameter / 40); + + this.screw.setAttribute("cx", center.x); + this.screw.setAttribute("cy", center.y); + this.screw.setAttribute("r", diameter / 12); + + var value = this.value; + + var handlePoints = { + start: Math.PI * 1.5, + end: math.clip(math.scale(value, 0, 0.5, Math.PI * 1.5, Math.PI * 0.5), Math.PI * 0.5, Math.PI * 1.5) + }; + var handle2Points = { + start: Math.PI * 2.5, + end: math.clip(math.scale(value, 0.5, 1, Math.PI * 2.5, Math.PI * 1.5), Math.PI * 1.5, Math.PI * 2.5) + }; + + var handlePath = svg.arc(center.x, center.y, diameter / 2 - diameter / 40, handlePoints.start, handlePoints.end); + var handle2Path = svg.arc(center.x, center.y, diameter / 2 - diameter / 40, handle2Points.start, handle2Points.end); + + this.handle.setAttribute("d", handlePath); + this.handle.setAttribute("stroke-width", diameter / 20); + this.handle.setAttribute("fill", "none"); + + this.handle2.setAttribute("d", handle2Path); + this.handle2.setAttribute("stroke-width", diameter / 20); + this.handle2.setAttribute("fill", "none"); + + handlePath += " L " + center.x + " " + center.y; + + this.handleFill.setAttribute("d", handlePath); + this.handleFill.setAttribute("fill-opacity", "0.3"); + + handle2Path += " L " + center.x + " " + center.y; + + this.handle2Fill.setAttribute("d", handle2Path); + this.handle2Fill.setAttribute("fill-opacity", "0.3"); + + var arcEndingA = undefined; + if (value < 0.5) { + arcEndingA = handlePoints.end; + } else { + arcEndingA = handle2Points.end; + } + + var arcEndingX = center.x + Math.cos(arcEndingA) * (diameter / 2); + var arcEndingY = center.y + Math.sin(arcEndingA) * (diameter / 2) * -1; + + this.handleLine.setAttribute("d", "M " + center.x + " " + center.y + " L " + arcEndingX + " " + arcEndingY); + this.handleLine.setAttribute("stroke-width", diameter / 20); + } + }, + colorInterface: { + value: function colorInterface() { + this.background.setAttribute("fill", this.colors.fill); + this.screw.setAttribute("fill", this.colors.accent); + this.handle.setAttribute("stroke", this.colors.accent); + this.handle2.setAttribute("stroke", this.colors.accent); + this.handleFill.setAttribute("fill", this.colors.accent); + this.handle2Fill.setAttribute("fill", this.colors.accent); + this.handleLine.setAttribute("stroke", this.colors.accent); + } + }, + render: { + value: function render() { + var value = this._value.normalized; + + var center = { + x: this.width / 2, + y: this.height / 2 + }; + + var diameter = Math.min(this.width, this.height); + + var handlePoints = { + start: Math.PI * 1.5, + end: math.clip(math.scale(value, 0, 0.5, Math.PI * 1.5, Math.PI * 0.5), Math.PI * 0.5, Math.PI * 1.5) + }; + var handle2Points = { + start: Math.PI * 2.5, + end: math.clip(math.scale(value, 0.5, 1, Math.PI * 2.5, Math.PI * 1.5), Math.PI * 1.5, Math.PI * 2.5) + }; + + var handlePath = svg.arc(center.x, center.y, diameter / 2 - diameter / 40, handlePoints.start, handlePoints.end); + var handle2Path = svg.arc(center.x, center.y, diameter / 2 - diameter / 40, handle2Points.start, handle2Points.end); + + this.handle.setAttribute("d", handlePath); + this.handle2.setAttribute("d", handle2Path); + + handlePath += " L " + center.x + " " + center.y; + + this.handleFill.setAttribute("d", handlePath); + + handle2Path += " L " + center.x + " " + center.y; + + this.handle2Fill.setAttribute("d", handle2Path); + + var arcEndingA = undefined; + if (value <= 0.5) { + arcEndingA = handlePoints.end; + } else { + arcEndingA = handle2Points.end; + } + + var arcEndingX = center.x + Math.cos(arcEndingA) * (diameter / 2); + var arcEndingY = center.y + Math.sin(arcEndingA) * (diameter / 2) * -1; + + this.handleLine.setAttribute("d", "M " + center.x + " " + center.y + " L " + arcEndingX + " " + arcEndingY); + } + }, + click: { + value: function click() { + if (this.mode === "relative") { + this.previousAngle = false; + } + this.position.anchor = this.mouse; + this.position.value = this._value.normalized; + this.move(); + } + }, + move: { + value: function move() { + if (this.clicked) { + + this.position.update(this.mouse); + + var angle = this.position.value * Math.PI * 2; + + if (angle < 0) { + angle += Math.PI * 2; + } + + if (this.mode === "relative") { + if (this.previousAngle !== false && Math.abs(this.previousAngle - angle) > 2) { + if (this.previousAngle > 3) { + angle = Math.PI * 2; + } else { + angle = 0; + } + } + } /* else { + if (this.previousAngle !== false && Math.abs(this.previousAngle - angle) > 2) { + if (this.previousAngle > 3) { + angle = Math.PI*2; + } else { + angle = 0; + } + } + } */ + this.previousAngle = angle; + + var realValue = angle / (Math.PI * 2); + + this.value = this._value.updateNormal(realValue); + + if (this.mode === "relative") { + this.position.value = realValue; + } + + this.emit("change", this._value.value); + + this.render(); + } + } + }, + release: { + value: function release() {} + }, + value: { + + /* + Dial's value. When set, it will automatically be adjust to fit min/max/step settings of the interface. + @type {number} + @example dial.value = 10; + get value() { + return this._value.value; + } + set value(value) { + this._value.update(value); + this.emit('change',this.value); + this.render(); + } + */ + + /** + Dial's value. When set, it will automatically be adjust to fit min/max/step settings of the interface. + @type {number} + @example dial.value = 10; + */ + + get: function () { + return this._value.value; + }, + set: function (v) { + this._value.update(v); + this.position.value = this._value.normalized; + this.emit("change", this._value.value); + this.render(); + } + }, + min: { + + /** + Lower limit of the dial's output range + @type {number} + @example dial.min = 1000; + */ + + get: function () { + return this._value.min; + }, + set: function (v) { + this._value.min = v; + } + }, + max: { + + /** + Upper limit of the dial's output range + @type {number} + @example dial.max = 1000; + */ + + get: function () { + return this._value.max; + }, + set: function (v) { + this._value.max = v; + } + }, + step: { + + /** + The increment that the dial's value changes by. + @type {number} + @example dial.step = 5; + */ + + get: function () { + return this._value.step; + }, + set: function (v) { + this._value.step = v; + } + }, + mode: { + + /** + Absolute mode (dial's value jumps to mouse click position) or relative mode (mouse drag changes value relative to its current position). Default: "relative". + @type {string} + @example dial.mode = "relative"; + */ + + get: function () { + return this.position.mode; + }, + set: function (v) { + this.position.mode = v; + } + }, + normalized: { + + /** + Normalized value of the dial. + @type {number} + @example dial.normalized = 0.5; + */ + + get: function () { + return this._value.normalized; + }, + set: function (v) { + this._value.updateNormal(v); + this.emit("change", this.value); + } + } + }); + + return Dial; + })(Interface); + + module.exports = Dial; + +/***/ }), +/* 23 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + + var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var svg = __webpack_require__(4); + var Interface = __webpack_require__(6); + var ButtonTemplate = __webpack_require__(17); + var touch = __webpack_require__(9); + + var PianoKey = (function (_ButtonTemplate) { + function PianoKey() { + _classCallCheck(this, PianoKey); + + var options = ["value", "note", "color"]; + + var defaults = { + size: [80, 80], + target: false, + mode: "button", + value: 0 + }; + + _get(Object.getPrototypeOf(PianoKey.prototype), "constructor", this).call(this, arguments, options, defaults); + + this.note = this.settings.note; + this.color = this.settings.color; + + this.colors = { + w: "#fff", + b: "#666" }; + + this.init(); + this.render(); + } + + _inherits(PianoKey, _ButtonTemplate); + + _createClass(PianoKey, { + buildFrame: { + value: function buildFrame() { + this.element = svg.create("svg"); + this.element.setAttribute("width", this.width); + this.element.setAttribute("height", this.height); + this.parent.appendChild(this.element); + } + }, + buildInterface: { + value: function buildInterface() { + var _this = this; + + this.pad = svg.create("rect"); + + this.element.appendChild(this.pad); + + this.interactionTarget = this.pad; + + /* events */ + + if (!touch.exists) { + + this.click = function () { + // console.log('click'); + _this.piano.interacting = true; + _this.piano.paintbrush = !_this.state; + _this.down(_this.piano.paintbrush); + }; + + this.pad.addEventListener("mouseover", function () { + if (_this.piano.interacting) { + // console.log('mouseover'); + _this.down(_this.piano.paintbrush); + } + }); + + this.move = function () { + if (_this.piano.interacting) { + // console.log('move'); + _this.bend(); + } + }; + + this.release = function () { + _this.piano.interacting = false; + // console.log('release'); + // this.up(); + }; + this.pad.addEventListener("mouseup", function () { + if (_this.piano.interacting) { + // console.log('mouseup'); + _this.up(); + } + }); + this.pad.addEventListener("mouseout", function () { + if (_this.piano.interacting) { + // console.log('mouseout'); + _this.up(); + } + }); + } + } + }, + sizeInterface: { + value: function sizeInterface() { + + //let radius = Math.min(this.width,this.height) / 5; + var radius = 0; + + this.pad.setAttribute("x", 0.5); + this.pad.setAttribute("y", 0.5); + if (this.width > 2) { + this.pad.setAttribute("width", this.width - 1); + } else { + this.pad.setAttribute("width", this.width); + } + if (this.height > 2) { + this.pad.setAttribute("height", this.height); + } else { + this.pad.setAttribute("height", this.height); + } + this.pad.setAttribute("rx", radius); + this.pad.setAttribute("ry", radius); + } + }, + render: { + value: function render() { + if (!this.state) { + this.pad.setAttribute("fill", this.colors[this.color]); + } else { + this.pad.setAttribute("fill", this.colors.accent); + } + } + } + }); + + return PianoKey; + })(ButtonTemplate); + + /** + * Piano + * + * @description Piano keyboard interface + * + * @demo
+ * + * @example + * var piano = new Nexus.Piano('#target') + * + * @example + * var piano = new Nexus.Piano('#target',{ + * 'size': [500,125], + * 'mode': 'button', // 'button', 'toggle', or 'impulse' + * 'lowNote': 24, + * 'highNote': 60 + * }) + * + * @output + * change + * Fires any time a new key is pressed or released
+ * The event data is an object containing note and state properties. + * + * @outputexample + * piano.on('change',function(v) { + * console.log(v); + * }) + * + */ + + var Piano = (function (_Interface) { + function Piano() { + _classCallCheck(this, Piano); + + var options = ["value"]; + + var defaults = { + size: [500, 125], + lowNote: 24, + highNote: 60, + mode: "button" + }; + + _get(Object.getPrototypeOf(Piano.prototype), "constructor", this).call(this, arguments, options, defaults); + + this.keyPattern = ["w", "b", "w", "b", "w", "w", "b", "w", "b", "w", "b", "w"]; + + this.paintbrush = false; + + this.mode = this.settings.mode; + + this.range = { + low: this.settings.lowNote, + high: this.settings.highNote + }; + + this.range.size = this.range.high - this.range.low + 1; + + this.keys = []; + + this.toggleTo = false; + + this.init(); + this.render(); + } + + _inherits(Piano, _Interface); + + _createClass(Piano, { + buildFrame: { + value: function buildFrame() { + this.element = document.createElement("div"); + this.element.style.position = "relative"; + this.element.style.borderRadius = "0px"; + this.element.style.display = "block"; + this.element.style.width = "100%"; + this.element.style.height = "100%"; + this.parent.appendChild(this.element); + } + }, + buildInterface: { + value: function buildInterface() { + + this.keys = []; + + for (var i = 0; i < this.range.size; i++) { + + var container = document.createElement("span"); + var scaleIndex = (i + this.range.low) % this.keyPattern.length; + + var key = new PianoKey(container, { + component: true, + note: i + this.range.low, + color: this.keyPattern[scaleIndex], + mode: this.mode + }, this.keyChange.bind(this, i + this.range.low)); + + key.piano = this; + + if (touch.exists) { + key.pad.index = i; + key.preClick = key.preMove = key.preRelease = function () {}; + key.click = key.move = key.release = function () {}; + key.preTouch = key.preTouchMove = key.preTouchRelease = function () {}; + key.touch = key.touchMove = key.touchRelease = function () {}; + } + + this.keys.push(key); + this.element.appendChild(container); + } + if (touch.exists) { + this.addTouchListeners(); + } + } + }, + sizeInterface: { + value: function sizeInterface() { + + var keyX = 0; + + var keyPositions = []; + + for (var i = 0; i < this.range.size; i++) { + + keyPositions.push(keyX); + + var scaleIndex = (i + this.range.low) % this.keyPattern.length; + var nextScaleIndex = (i + 1 + this.range.low) % this.keyPattern.length; + if (i + 1 + this.range.low >= this.range.high) { + keyX += 1; + } else if (this.keyPattern[scaleIndex] === "w" && this.keyPattern[nextScaleIndex] === "w") { + keyX += 1; + } else { + keyX += 0.5; + } + } + var keysWide = keyX; + + // let padding = this.width / 120; + var padding = 1; + var buttonWidth = (this.width - padding * 2) / keysWide; + var buttonHeight = (this.height - padding * 2) / 2; + + for (var i = 0; i < this.keys.length; i++) { + + var container = this.keys[i].parent; + container.style.position = "absolute"; + container.style.left = keyPositions[i] * buttonWidth + padding + "px"; + if (this.keys[i].color === "w") { + container.style.top = padding + "px"; + this.keys[i].resize(buttonWidth, buttonHeight * 2); + } else { + container.style.zIndex = 1; + container.style.top = padding + "px"; + this.keys[i].resize(buttonWidth, buttonHeight * 1.1); + } + } + } + }, + colorInterface: { + value: function colorInterface() { + + // Piano keys don't actually have a stroke border + // They have space between them, which shows the Piano bg color + this.element.style.backgroundColor = this.colors.mediumLight; + + for (var i = 0; i < this.keys.length; i++) { + this.keys[i].colors = { + w: this.colors.light, + b: this.colors.dark, + accent: this.colors.accent, + border: this.colors.mediumLight + }; + this.keys[i].colorInterface(); + this.keys[i].render(); + } + } + }, + keyChange: { + value: function keyChange(note, on) { + // emit data for any key turning on/off + // "note" is the note value + // "on" is a boolean whether it is on or off + // in aftertouch mode, "on: is an object with state/x/y properties + var data = { + note: note + }; + if (typeof on === "object") { + data.state = on.state; + // data.x = on.x + // data.y = on.y + } else { + data.state = on; + } + this.emit("change", data); + } + }, + render: { + + /* drag(note,on) { + this.emit('change',{ + note: note, + state: on + }); + } */ + + value: function render() {} + }, + addTouchListeners: { + value: function addTouchListeners() { + var _this = this; + + this.preClick = this.preMove = this.preRelease = function () {}; + this.click = this.move = this.release = function () {}; + this.preTouch = this.preTouchMove = this.preTouchRelease = function () {}; + this.touch = this.touchMove = this.touchRelease = function () {}; + + this.currentElement = false; + + this.element.addEventListener("touchstart", function (e) { + console.log("touchstart"); + var element = document.elementFromPoint(e.targetTouches[0].clientX, e.targetTouches[0].clientY); + var key = _this.keys[element.index]; + _this.paintbrush = !key.state; + key.down(_this.paintbrush); + _this.currentElement = element.index; + e.preventDefault(); + e.stopPropagation(); + }); + + this.element.addEventListener("touchmove", function (e) { + var element = document.elementFromPoint(e.targetTouches[0].clientX, e.targetTouches[0].clientY); + var key = _this.keys[element.index]; + if (element.index !== _this.currentElement) { + if (_this.currentElement) { + var pastKey = _this.keys[_this.currentElement]; + pastKey.up(); + } + key.down(_this.paintbrush); + } else { + key.bend(); + } + _this.currentElement = element.index; + e.preventDefault(); + e.stopPropagation(); + }); + + this.element.addEventListener("touchend", function (e) { + // no touches to calculate because none remaining + var key = _this.keys[_this.currentElement]; + key.up(); + _this.interacting = false; + _this.currentElement = false; + e.preventDefault(); + e.stopPropagation(); + }); + } + }, + setRange: { + + /** + Define the pitch range (lowest and highest note) of the piano keyboard. + @param low {number} MIDI note value of the lowest note on the keyboard + @param high {number} MIDI note value of the highest note on the keyboard + */ + + value: function setRange(low, high) { + this.range.low = low; + this.range.high = high; + this.empty(); + this.buildInterface(); + } + }, + toggleKey: { + + /** + Turn a key on or off using its MIDI note value; + @param note {number} MIDI note value of the key to change + @param on {boolean} Whether the note should turn on or off + */ + + value: function toggleKey(note, on) { + this.keys[note - this.range.low].flip(on); + } + }, + toggleIndex: { + + /** + Turn a key on or off using its key index on the piano interface. + @param index {number} Index of the key to change + @param on {boolean} Whether the note should turn on or off + */ + + value: function toggleIndex(index, on) { + this.keys[index].flip(on); + } + } + }); + + return Piano; + })(Interface); + + module.exports = Piano; + + // loop through and render the keys? + +/***/ }), +/* 24 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + + var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var svg = __webpack_require__(4); + var dom = __webpack_require__(7); + var Interface = __webpack_require__(6); + var ButtonTemplate = __webpack_require__(17); + var MatrixModel = __webpack_require__(25); + var CounterModel = __webpack_require__(28); + var Interval = __webpack_require__(29); + var touch = __webpack_require__(9); + + var MatrixCell = (function (_ButtonTemplate) { + function MatrixCell() { + _classCallCheck(this, MatrixCell); + + var options = ["value"]; + + var defaults = { + size: [80, 80], + target: false, + mode: "toggle", + value: 0 + }; + + _get(Object.getPrototypeOf(MatrixCell.prototype), "constructor", this).call(this, arguments, options, defaults); + + this.index = this.settings.index; + this.row = this.settings.row; + this.column = this.settings.column; + + this.matrix = this.settings.matrix; + + this.interacting = false; + this.paintbrush = false; + + this.init(); + this.render(); + } + + _inherits(MatrixCell, _ButtonTemplate); + + _createClass(MatrixCell, { + buildFrame: { + value: function buildFrame() { + this.element = svg.create("svg"); + this.element.setAttribute("width", this.width); + this.element.setAttribute("height", this.height); + this.element.style.top = "0px"; + this.element.style.left = "0px"; + this.element.style.position = "absolute"; + this.parent.appendChild(this.element); + } + }, + buildInterface: { + value: function buildInterface() { + var _this = this; + + this.pad = svg.create("rect"); + this.element.appendChild(this.pad); + + this.interactionTarget = this.pad; + + /* events */ + + if (!touch.exists) { + + this.click = function () { + _this.matrix.interacting = true; + _this.matrix.paintbrush = !_this.state; + _this.down(_this.matrix.paintbrush); + }; + this.pad.addEventListener("mouseover", function () { + if (_this.matrix.interacting) { + _this.down(_this.matrix.paintbrush); + } + }); + + this.move = function () {}; + this.pad.addEventListener("mousemove", function (e) { + if (_this.matrix.interacting) { + if (!_this.offset) { + _this.offset = dom.findPosition(_this.element); + } + _this.mouse = dom.locateMouse(e, _this.offset); + _this.bend(); + } + }); + + this.release = function () { + _this.matrix.interacting = false; + }; + this.pad.addEventListener("mouseup", function () { + if (_this.matrix.interacting) { + _this.up(); + } + }); + this.pad.addEventListener("mouseout", function () { + if (_this.matrix.interacting) { + _this.up(); + } + }); + } + } + }, + sizeInterface: { + value: function sizeInterface() { + + this.pad.setAttribute("x", 1); + this.pad.setAttribute("y", 1); + if (this.width > 2) { + this.pad.setAttribute("width", this.width - 2); + } else { + this.pad.setAttribute("width", this.width); + } + if (this.height > 2) { + this.pad.setAttribute("height", this.height - 2); + } else { + this.pad.setAttribute("height", this.height); + } + //this.pad.setAttribute('height', this.height - 2); + this.pad.setAttribute("fill", this.matrix.colors.fill); + } + }, + render: { + value: function render() { + if (!this.state) { + this.pad.setAttribute("fill", this.matrix.colors.fill); + } else { + this.pad.setAttribute("fill", this.matrix.colors.accent); + } + } + } + }); + + return MatrixCell; + })(ButtonTemplate); + + /** + * Sequencer + * + * @description Grid of buttons with built-in step sequencer. + * + * @demo
+ * + * @example + * var sequencer = new Nexus.Sequencer('#target') + * + * @example + * var sequencer = new Nexus.Sequencer('#target',{ + * 'size': [400,200], + * 'mode': 'toggle', + * 'rows': 5, + * 'columns': 10 + *}) + * + * @output + * change + * Fires any time the interface's matrix changes.
+ * The event data is an object containing row (number), column (number), and state (boolean) properties. + * + * @outputexample + * sequencer.on('change',function(v) { + * console.log(v); + * }) + * + * @output + * step + * Fires any time the sequencer steps to the next column, in sequece mode.
+ * The event data is an array containing all values in the column, bottom row first. + * + * @outputexample + * sequencer.on('step',function(v) { + * console.log(v); + * }) + */ + + var Sequencer = (function (_Interface) { + function Sequencer() { + _classCallCheck(this, Sequencer); + + var options = ["value"]; + + var defaults = { + size: [400, 200], + mode: "toggle", + rows: 5, + columns: 10 + }; + + _get(Object.getPrototypeOf(Sequencer.prototype), "constructor", this).call(this, arguments, options, defaults); + + this.active = -1; + + /** + * Button interaction mode: see Button + * @type {string} + * @example button.mode = 'toggle'; + */ + this.mode = this.settings.mode; + + /** + * The interval object which controls timing and sequence scheduling. + * @type {interval} + */ + this.interval = new Interval(200, function () {}, false); // jshint ignore:line + + /** + * A Matrix model containing methods for manipulating the sequencer's array of values. To learn how to manipulate the matrix, read about the matrix model. + * @type {matrix} + */ + this.matrix = new MatrixModel(this.settings.rows, this.settings.columns); + this.matrix.ui = this; + + /** + * A Counter model which the sequencer steps through. For example, you could use this model to step through the sequencer in reverse, randomly, or in a drunk walk. + * @type {counter} + */ + this.stepper = new CounterModel(0, this.columns); + + this.init(); + } + + _inherits(Sequencer, _Interface); + + _createClass(Sequencer, { + buildFrame: { + value: function buildFrame() { + this.element = document.createElement("div"); + this.element.style.position = "relative"; + this.element.style.display = "block"; + this.element.style.width = "100%"; + this.element.style.height = "100%"; + this.parent.appendChild(this.element); + if (touch.exists) { + this.addTouchListeners(); + } + } + }, + buildInterface: { + value: function buildInterface() { + + this.cells = []; + for (var i = 0; i < this.matrix.length; i++) { + + var _location = this.matrix.locate(i); + // returns {row,col} + + var container = document.createElement("span"); + container.style.position = "absolute"; + + var cell = new MatrixCell(container, { + component: true, + index: i, + row: _location.row, + column: _location.column, + mode: this.mode, + matrix: this + }, this.keyChange.bind(this, i)); + + // cell.matrix = this; + if (touch.exists) { + cell.pad.index = i; + cell.preClick = cell.preMove = cell.preRelease = function () {}; + cell.click = cell.move = cell.release = function () {}; + cell.preTouch = cell.preTouchMove = cell.preTouchRelease = function () {}; + cell.touch = cell.touchMove = cell.touchRelease = function () {}; + } + + this.cells.push(cell); + this.element.appendChild(container); + } + this.sizeInterface(); + } + }, + sizeInterface: { + value: function sizeInterface() { + + var cellWidth = this.width / this.columns; + var cellHeight = this.height / this.rows; + + for (var i = 0; i < this.cells.length; i++) { + var container = this.cells[i].parent; + container.style.left = this.cells[i].column * cellWidth + "px"; + container.style.top = this.cells[i].row * cellHeight + "px"; + this.cells[i].resize(cellWidth, cellHeight); + } + } + }, + colorInterface: { + value: function colorInterface() { + for (var i = 0; i < this.cells.length; i++) { + this.cells[i].render(); + } + } + }, + update: { + value: function update() { + var _this = this; + + // console.log("updating...") + //on = on || false; + this.matrix.iterate(function (r, c, i) { + // console.log(this.matrix.pattern[r][c], this.cells[i].state); + if (_this.matrix.pattern[r][c] !== _this.cells[i].state) { + if (_this.matrix.pattern[r][c] > 0) { + _this.cells[i].turnOn(); + } else { + _this.cells[i].turnOff(); + } + } + }); + } + }, + keyChange: { + + // update => cell.turnOn => cell.emit => keyChange (seq.emit) => matrix.set.cell => update + // + // interaction => keyChange => matrix.set.cell => update => cell.turnOn + // => emit + // + // set.cell => update => needs to emit. + + value: function keyChange(note, on) { + // emit data for any key turning on/off + // i is the note index + // v is whether it is on or off + var cell = this.matrix.locate(note); + // this.matrix.set.cell(cell.column,cell.row,on); + this.matrix.pattern[cell.row][cell.column] = on; + var data = { + row: cell.row, + column: cell.column, + state: on + }; + this.emit("change", data); + } + }, + render: { + value: function render() { + var _this = this; + + if (this.stepper.value >= 0) { + this.matrix.iterate(function (r, c, i) { + if (c === _this.stepper.value) { + _this.cells[i].pad.setAttribute("stroke", _this.colors.mediumLight); + _this.cells[i].pad.setAttribute("stroke-width", "1"); + _this.cells[i].pad.setAttribute("stroke-opacity", "1"); + } else { + _this.cells[i].pad.setAttribute("stroke", "none"); + } + }); + } + } + }, + start: { + + /** + * Start sequencing + * @param {number} ms Beat tempo in milliseconds + */ + + value: function start(ms) { + this.interval.event = this.next.bind(this); + if (ms) { + this.interval.ms(ms); + } + this.interval.start(); + } + }, + stop: { + + /** + Stop sequencing + */ + + value: function stop() { + this.interval.stop(); + } + }, + next: { + + /** + Manually jump to the next column and trigger the 'change' event. The "next" column is determined by your mode of sequencing. + */ + + value: function next() { + this.stepper.next(); + this.emit("step", this.matrix.column(this.stepper.value).reverse()); + this.render(); + } + }, + addTouchListeners: { + value: function addTouchListeners() { + var _this = this; + + this.preClick = this.preMove = this.preRelease = function () {}; + this.click = this.move = this.release = function () {}; + this.preTouch = this.preTouchMove = this.preTouchRelease = function () {}; + this.touch = this.touchMove = this.touchRelease = function () {}; + + this.currentElement = false; + + this.element.addEventListener("touchstart", function (e) { + var element = document.elementFromPoint(e.targetTouches[0].clientX, e.targetTouches[0].clientY); + var cell = _this.cells[element.index]; + _this.paintbrush = !cell.state; + cell.down(_this.paintbrush); + _this.currentElement = element.index; + e.preventDefault(); + e.stopPropagation(); + }); + + this.element.addEventListener("touchmove", function (e) { + var element = document.elementFromPoint(e.targetTouches[0].clientX, e.targetTouches[0].clientY); + var cell = _this.cells[element.index]; + if (element.index !== _this.currentElement) { + if (_this.currentElement >= 0) { + var pastCell = _this.cells[_this.currentElement]; + pastCell.up(); + } + cell.down(_this.paintbrush); + } else { + cell.bend(); + } + _this.currentElement = element.index; + e.preventDefault(); + e.stopPropagation(); + }); + + this.element.addEventListener("touchend", function (e) { + // no touches to calculate because none remaining + var cell = _this.cells[_this.currentElement]; + cell.up(); + _this.interacting = false; + _this.currentElement = false; + e.preventDefault(); + e.stopPropagation(); + }); + } + }, + rows: { + + /** + Number of rows in the sequencer + @type {number} + */ + + get: function () { + return this.matrix.rows; + }, + set: function (v) { + this.matrix.rows = v; + this.empty(); + this.buildInterface(); + this.update(); + } + }, + columns: { + + /** + Number of columns in the sequencer + @type {number} + */ + + get: function () { + return this.matrix.columns; + }, + set: function (v) { + this.matrix.columns = v; + this.stepper.max = v; + this.empty(); + this.buildInterface(); + this.update(); + } + } + }); + + return Sequencer; + })(Interface); + + module.exports = Sequencer; + +/***/ }), +/* 25 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var math = _interopRequire(__webpack_require__(5)); + + var Sequence = _interopRequire(__webpack_require__(26)); + + // For the tutorial, looking at + + //Pattern section: + // .create(), .rows, .columns, + // .pattern, .length, .formatAsText(), .log(), + // .locate(i), .indexOf(c,r) + // row(), column() (returns contents of row or colum) + + //Control section: + // toggle x3 + // set x4 + // rotate x3 + // populate x3 + // erase x3 + + // should some version of this have a float value for each cell? + // could be like a mirror .pattern that has values. by default, everything is 1, but could be set... + // not a good way to do that on interface, but as a model it would be nice... + // for .formatAsText(), could multiply by 100 and floor, so each cell is an int from 0 to 9 + + var Matrix = (function () { + function Matrix(rows, columns) { + var _this = this; + + _classCallCheck(this, Matrix); + + // should also have ability to create using an existing matrix (2d array) + this.pattern = []; + this.create(rows, columns); + + this.toggle = { + cell: function (column, row) { + _this.pattern[row][column] = !_this.pattern[row][column]; // math.invert(this.pattern[row][column]); + if (_this.ui) { + _this.ui.update(); + } + return _this.pattern[row][column]; + }, + all: function () { + _this.iterate(function (r, c) { + _this.toggle.cell(c, r); + }); + if (_this.ui) { + _this.ui.update(); + } + }, + row: function (row) { + for (var i = 0; i < _this.columns; i++) { + _this.toggle.cell(i, row); + } + if (_this.ui) { + _this.ui.update(); + } + }, + column: function (column) { + for (var i = 0; i < _this.rows; i++) { + _this.toggle.cell(column, i); + } + if (_this.ui) { + _this.ui.update(); + } + } + }; + + this.set = { + cell: function (column, row, value) { + _this.pattern[row][column] = value; + if (_this.ui) { + _this.ui.update(); + } + }, + all: function (values) { + // set the whole matrix using a 2d array as input + // this should also resize the array? + _this.pattern = values; + if (_this.ui) { + _this.ui.update(); + } + }, + row: function (row, values) { + // set a row using an array as input + _this.pattern[row] = values; + if (_this.ui) { + _this.ui.update(); + } + }, + column: function (column, values) { + // set a column using an array as input + _this.pattern.forEach(function (row, i) { + _this.pattern[i][column] = values[i]; + }); + if (_this.ui) { + _this.ui.update(); + } + } + }; + + this.rotate = { + //should eventually do (amountX, amountY) here + // could just use a loop and this.rotate.row(i,amountX); + all: function (amount) { + if (!amount && amount !== 0) { + amount = 1; + } + amount %= _this.pattern[0].length; + if (amount < 0) { + amount = _this.pattern[0].length + amount; + } + for (var i = 0; i < _this.rows; i++) { + var cut = _this.pattern[i].splice(_this.pattern[i].length - amount, amount); + _this.pattern[i] = cut.concat(_this.pattern[i]); + } + if (_this.ui) { + _this.ui.update(); + } + }, + row: function (row, amount) { + if (!amount && amount !== 0) { + amount = 1; + } + amount %= _this.pattern[0].length; + if (amount < 0) { + amount = _this.pattern[0].length + amount; + } + var cut = _this.pattern[row].splice(_this.pattern[row].length - amount, amount); + _this.pattern[row] = cut.concat(_this.pattern[row]); + if (_this.ui) { + _this.ui.update(); + } + }, + column: function (column, amount) { + if (!amount && amount !== 0) { + amount = 1; + } + amount %= _this.pattern.length; + if (amount < 0) { + amount = _this.pattern.length + amount; + } + var proxy = []; + _this.pattern.forEach(function (row) { + proxy.push(row[column]); + }); + var cut = proxy.splice(proxy.length - amount, amount); + proxy = cut.concat(proxy); + _this.pattern.forEach(function (row, i) { + row[column] = proxy[i]; + }); + if (_this.ui) { + _this.ui.update(); + } + } + }; + + // the idea behind populate is to be able to set a whole row or column to 0 or 1 + // IF the value is a float, such as 0.7, then it would become a probability + // so populate(0.7) would give each cell a 70% chance of being 1 + this.populate = { + all: function (odds) { + var oddsSequence = new Sequence(odds); + _this.iterate(function (r, c) { + _this.pattern[r][c] = math.coin(oddsSequence.next()); + }); + // This could be used so that each row has same odds pattern, even if row length is not divisibly by sequence length. + //,() => { + // odds.pos = -1; + // } + if (_this.ui) { + _this.ui.update(); + } + }, + row: function () { + var row = arguments[0] === undefined ? 0 : arguments[0]; + var odds = arguments[1] === undefined ? 1 : arguments[1]; + + var oddsSequence = new Sequence(odds); + _this.pattern[row].forEach(function (cell, i) { + _this.pattern[row][i] = math.coin(oddsSequence.next()); + }); + if (_this.ui) { + _this.ui.update(); + } + }, + column: function () { + var column = arguments[0] === undefined ? 0 : arguments[0]; + var odds = arguments[1] === undefined ? 1 : arguments[1]; + + var oddsSequence = new Sequence(odds); + _this.pattern.forEach(function (row, i) { + _this.pattern[i][column] = math.coin(oddsSequence.next()); + }); + if (_this.ui) { + _this.ui.update(); + } + } + }; + + // essentiall populate(0) so i'm not sure if this is necessary but is nice + this.erase = { + all: function () { + _this.set.all(0); + }, + row: function (row) { + _this.set.row(row, 0); + }, + column: function (column) { + _this.set.column(column, 0); + } + }; + + // end constructor + } + + _createClass(Matrix, { + create: { + value: function create(rows, columns) { + var _this = this; + + this.pattern = []; + for (var row = 0; row < rows; row++) { + var arr = new Array(columns); + this.pattern.push(arr); + } + this.iterate(function (r, c) { + _this.pattern[r][c] = false; + }); + } + }, + iterate: { + value: function iterate(f, f2) { + var i = 0; + for (var row = 0; row < this.rows; row++) { + if (f2) { + f2(row); + } + for (var column = 0; column < this.columns; column++) { + f(row, column, i); + i++; + } + } + } + }, + formatAsText: { + value: function formatAsText() { + var _this = this; + + var patternString = ""; + this.iterate(function (r, c) { + patternString += (_this.pattern[r][c] ? 1 : 0) + " "; + }, function () { + patternString += "\n"; + }); + return patternString; + } + }, + log: { + value: function log() { + console.log(this.formatAsText()); + } + }, + update: { + value: function update(pattern) { + this.pattern = pattern || this.pattern; + } + }, + length: { + get: function () { + return this.rows * this.columns; + } + }, + locate: { + value: function locate(index) { + // returns row and column of cell by index + return { + row: ~ ~(index / this.columns), + column: index % this.columns + }; + } + }, + indexOf: { + value: function indexOf(row, column) { + return column + row * this.columns; + // returns index of cell by row and column + } + }, + row: { + value: (function (_row) { + var _rowWrapper = function row(_x) { + return _row.apply(this, arguments); + }; + + _rowWrapper.toString = function () { + return _row.toString(); + }; + + return _rowWrapper; + })(function (row) { + var data = []; + for (var i = 0; i < this.columns; i++) { + data.push(this.pattern[row] ? 1 : 0); + } + return data; + }) + }, + column: { + value: (function (_column) { + var _columnWrapper = function column(_x2) { + return _column.apply(this, arguments); + }; + + _columnWrapper.toString = function () { + return _column.toString(); + }; + + return _columnWrapper; + })(function (column) { + var data = []; + for (var i = 0; i < this.rows; i++) { + data.push(this.pattern[i][column] ? 1 : 0); + } + return data; + }) + }, + rows: { + get: function () { + return this.pattern.length; + }, + set: function (v) { + var _this = this; + + var previous = this.pattern.slice(0); + this.create(v, this.columns); + this.iterate(function (r, c) { + if (previous[r] && previous[r][c]) { + _this.pattern[r][c] = previous[r][c]; + } + }); + } + }, + columns: { + get: function () { + return this.pattern[0].length; + }, + set: function (v) { + var _this = this; + + var previous = this.pattern.slice(0); + this.create(this.rows, v); + this.iterate(function (r, c) { + if (previous[r] && previous[r][c]) { + _this.pattern[r][c] = previous[r][c]; + } + }); + } + } + }); + + return Matrix; + })(); + + module.exports = Matrix; + +/***/ }), +/* 26 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var math = _interopRequire(__webpack_require__(5)); + + var Drunk = _interopRequire(__webpack_require__(27)); + + var Sequence = (function () { + function Sequence() { + var sequence = arguments[0] === undefined ? [0, 10, 20, 30] : arguments[0]; + var mode = arguments[1] === undefined ? "up" : arguments[1]; + var position = arguments[2] === undefined ? false : arguments[2]; + + _classCallCheck(this, Sequence); + + this.values = sequence; + if (!Array.isArray(this.values)) { + this.values = [this.values]; + } + this._mode = mode; + this.position = position; + + this.drunkWalk = new Drunk(0, this.values.length - 1); + + this.startValues = { + up: 0, + down: this.values.length - 1, + drunk: ~ ~(this.values.length / 2), + random: math.ri(this.values.length) + }; + + if (this.position !== false) { + this.next = this[this._mode]; + } else { + this.next = this.first; + } + } + + _createClass(Sequence, { + mode: { + get: function () { + return this._mode; + }, + set: function (mode) { + if (!(mode === "up" || mode === "down" || mode === "random" || mode === "drunk")) { + console.error("The only modes currently allowed are: up, down, random, drunk"); + return; + } + this._mode = mode; + if (this.position) { + this.next = this[this._mode]; + } + } + }, + value: { + get: function () { + return this.values[this.position]; + }, + set: function (v) { + this.position = this.values.indexOf(v); + } + }, + first: { + value: function first() { + if (this.position !== false) { + this.next = this[this._mode]; + return this.next(); + } + this.position = this.startValues[this._mode]; + this.next = this[this._mode]; + return this.value; + } + }, + up: { + value: function up() { + this.position++; + this.position %= this.values.length; + return this.value; + } + }, + down: { + value: function down() { + this.position--; + if (this.position < 0) { + this.position = (this.position + this.values.length) % this.values.length; + } + return this.value; + } + }, + random: { + value: function random() { + this.position = math.ri(0, this.values.length); + return this.value; + } + }, + drunk: { + value: function drunk() { + this.drunkWalk.max = this.values.length; + this.drunkWalk.value = this.position; + this.position = this.drunkWalk.next(); + return this.value; + } + + /* future methods + .group(start,stop) -- outputs a group of n items from the list, with wrapping + .loop(start,stop) -- confines sequencing to a subset of the values + (could even have a distinction between .originalValues and the array of values being used) + */ + + } + }); + + return Sequence; + })(); + + module.exports = Sequence; + +/***/ }), +/* 27 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var math = _interopRequire(__webpack_require__(5)); + + var Drunk = (function () { + function Drunk() { + var min = arguments[0] === undefined ? 0 : arguments[0]; + var max = arguments[1] === undefined ? 9 : arguments[1]; + var value = arguments[2] === undefined ? 0 : arguments[2]; + var increment = arguments[3] === undefined ? 1 : arguments[3]; + var loop = arguments[4] === undefined ? false : arguments[4]; + + _classCallCheck(this, Drunk); + + this.min = min; + this.max = max; + this.value = value; + this.increment = increment; + this.loop = loop; + } + + _createClass(Drunk, { + next: { + value: function next() { + this.value += math.pick(-1 * this.increment, this.increment); + if (this.value > this.max) { + if (this.loop) { + this.value = this.min; + } else { + this.value = this.max - this.increment; + } + } + + if (this.value < this.min) { + if (this.loop) { + this.value = this.max; + } else { + this.value = this.min + this.increment; + } + } + return this.value; + } + } + }); + + return Drunk; + })(); + + module.exports = Drunk; + +/***/ }), +/* 28 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var math = _interopRequire(__webpack_require__(5)); + + var Drunk = _interopRequire(__webpack_require__(27)); + + var Counter = (function () { + function Counter() { + var min = arguments[0] === undefined ? 0 : arguments[0]; + var max = arguments[1] === undefined ? 10 : arguments[1]; + var mode = arguments[2] === undefined ? "up" : arguments[2]; + var value = arguments[3] === undefined ? false : arguments[3]; + + _classCallCheck(this, Counter); + + this.min = min; + this.max = max; + this.value = value; + this.mode = mode; + this.drunkWalk = new Drunk(this.min, this.max); + if (this.value !== false) { + this.next = this[this._mode]; + } else { + this.next = this.first; + } + } + + _createClass(Counter, { + mode: { + set: function (mode) { + if (!(mode === "up" || mode === "down" || mode === "random" || mode === "drunk")) { + console.error("The only modes currently allowed are: up, down, random, drunk"); + return; + } + this._mode = mode; + if (this.value) { + this.next = this[this._mode]; + } + }, + get: function () { + return this._mode; + } + }, + first: { + value: function first() { + if (this.value !== false) { + this.next = this[this._mode]; + return this.next(); + } + this.startValues = { + up: this.min, + down: this.max, + drunk: ~ ~math.average(this.min, this.max), + random: math.ri(this.min, this.max) + }; + this.value = this.startValues[this._mode]; + this.next = this[this._mode]; + return this.value; + } + }, + up: { + value: function up() { + this.value++; + if (this.value >= this.max) { + this.value = this.min; + } + return this.value; + } + }, + down: { + value: function down() { + this.value--; + if (this.value < this.min) { + this.value = this.max; + } + return this.value; + } + }, + random: { + value: function random() { + this.value = math.ri(this.min, this.max); + return this.value; + } + }, + drunk: { + value: function drunk() { + this.drunkWalk.min = this.min; + this.drunkWalk.max = this.max; + this.drunkWalk.value = this.value; + this.value = this.drunkWalk.next(); + return this.value; + } + } + }); + + return Counter; + })(); + + module.exports = Counter; + +/***/ }), +/* 29 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var clock = __webpack_require__(1).clock; + + var Interval = (function () { + function Interval(rate, func, on) { + _classCallCheck(this, Interval); + + this.rate = rate; + this.on = on; + this.clock = clock(); // jshint ignore:line + + this.pattern = [1]; + this.index = 0; + + this.event = func ? func : function () {}; + + if (this.on) { + this.start(); + } + } + + _createClass(Interval, { + _event: { + value: function _event(e) { + // if (this.pattern[this.index%this.pattern.length]) { + this.event(e); + // } + this.index++; + } + }, + stop: { + value: function stop() { + this.on = false; + this.interval.clear(); + } + }, + start: { + value: function start() { + this.on = true; + this.interval = this.clock.callbackAtTime(this._event.bind(this), this.clock.context.currentTime).repeat(this.rate / 1000).tolerance({ early: 0.1, late: 1 }); + } + }, + ms: { + value: function ms(newrate) { + if (this.on) { + var ratio = newrate / this.rate; + this.rate = newrate; + this.clock.timeStretch(this.clock.context.currentTime, [this.interval], ratio); + } else { + this.rate = newrate; + } + } + } + }); + + return Interval; + })(); + + module.exports = Interval; + +/***/ }), +/* 30 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { "default": obj }; }; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + + var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var svg = __webpack_require__(4); + var math = __webpack_require__(5); + var Interface = __webpack_require__(6); + var Step = __webpack_require__(11); + + var Interaction = _interopRequireWildcard(__webpack_require__(12)); + + /** + * Pan2D + * + * @description Interface for moving a sound around an array of speakers. Speaker locations can be customized. The interface calculates the closeness of the sound source to each speaker and returns that distance as a numeric value. + * + * @demo + * + * @example + * var pan2d = new Nexus.Pan2d('#target') + * + * @example + * var pan2d = new Nexus.Pan2D('#target',{ + * 'size': [200,200], + * 'range': 0.5, // detection radius of each speaker + * 'mode': 'absolute', // 'absolute' or 'relative' sound movement + * 'speakers': [ // the speaker [x,y] positions + * [0.5,0.2], + * [0.75,0.25], + * [0.8,0.5], + * [0.75,0.75], + * [0.5,0.8], + * [0.25,0.75] + * [0.2,0.5], + * [0.25,0.25] + * ] + * }) + * + * @output + * change + * Fires any time the "source" node's position changes.
+ * The event data is an array of the amplitudes (0-1), representing the level of each speaker (as calculated by its distance to the audio source). + * + * @outputexample + * pan2d.on('change',function(v) { + * console.log(v); + * }) + * + */ + + var Pan2D = (function (_Interface) { + function Pan2D() { + _classCallCheck(this, Pan2D); + + var options = ["range"]; + + var defaults = { + size: [200, 200], + range: 0.5, + mode: "absolute", + speakers: [[0.5, 0.2], [0.75, 0.25], [0.8, 0.5], [0.75, 0.75], [0.5, 0.8], [0.25, 0.75], [0.2, 0.5], [0.25, 0.25]] + }; + + _get(Object.getPrototypeOf(Pan2D.prototype), "constructor", this).call(this, arguments, options, defaults); + + this.value = { + x: new Step(0, 1, 0, 0.5), + y: new Step(0, 1, 0, 0.5) + }; + + /** + Absolute or relative mouse interaction. In "absolute" mode, the source node will jump to your mouse position on mouse click. In "relative" mode, it does not. + */ + this.mode = this.settings.mode; + + this.position = { + x: new Interaction.Handle(this.mode, "horizontal", [0, this.width], [this.height, 0]), + y: new Interaction.Handle(this.mode, "vertical", [0, this.width], [this.height, 0]) + }; + this.position.x.value = this.value.x.normalized; + this.position.y.value = this.value.y.normalized; + + /** + An array of speaker locations. Update this with .moveSpeaker() or .moveAllSpeakers() + */ + this.speakers = this.settings.speakers; + + /** + Rewrite: The maximum distance from a speaker that the source node can be for it to be heard from that speaker. A low range (0.1) will result in speakers only playing when the sound is very close it. Default is 0.5 (half of the interface). + */ + this.range = this.settings.range; + + /** + The current levels for each speaker. This is calculated when a source node or speaker node is moved through interaction or programatically. + */ + this.levels = []; + + this.init(); + + this.calculateLevels(); + this.render(); + } + + _inherits(Pan2D, _Interface); + + _createClass(Pan2D, { + buildInterface: { + value: function buildInterface() { + + this.knob = svg.create("circle"); + + this.element.appendChild(this.knob); + + // add speakers + this.speakerElements = []; + + for (var i = 0; i < this.speakers.length; i++) { + var speakerElement = svg.create("circle"); + + this.element.appendChild(speakerElement); + + this.speakerElements.push(speakerElement); + } + } + }, + sizeInterface: { + value: function sizeInterface() { + + this._minDimension = Math.min(this.width, this.height); + + this.knobRadius = { + off: ~ ~(this._minDimension / 100) * 3 + 5 }; + this.knobRadius.on = this.knobRadius.off * 2; + + this.knob.setAttribute("cx", this.width / 2); + this.knob.setAttribute("cy", this.height / 2); + this.knob.setAttribute("r", this.knobRadius.off); + + for (var i = 0; i < this.speakers.length; i++) { + var speakerElement = this.speakerElements[i]; + var speaker = this.speakers[i]; + speakerElement.setAttribute("cx", speaker[0] * this.width); + speakerElement.setAttribute("cy", speaker[1] * this.height); + speakerElement.setAttribute("r", this._minDimension / 20 + 5); + speakerElement.setAttribute("fill-opacity", "0"); + } + + this.position.x.resize([0, this.width], [this.height, 0]); + this.position.y.resize([0, this.width], [this.height, 0]); + + // next, need to + // resize positions + // calculate speaker distances + this.calculateLevels(); + this.render(); + } + }, + colorInterface: { + value: function colorInterface() { + + this.element.style.backgroundColor = this.colors.fill; + this.knob.setAttribute("fill", this.colors.mediumLight); + + for (var i = 0; i < this.speakers.length; i++) { + var speakerElement = this.speakerElements[i]; + speakerElement.setAttribute("fill", this.colors.accent); + speakerElement.setAttribute("stroke", this.colors.accent); + } + } + }, + render: { + value: function render() { + this.knobCoordinates = { + x: this.value.x.normalized * this.width, + y: this.height - this.value.y.normalized * this.height + }; + + this.knob.setAttribute("cx", this.knobCoordinates.x); + this.knob.setAttribute("cy", this.knobCoordinates.y); + } + }, + click: { + value: function click() { + this.position.x.anchor = this.mouse; + this.position.y.anchor = this.mouse; + this.move(); + } + }, + move: { + value: function move() { + if (this.clicked) { + this.position.x.update(this.mouse); + this.position.y.update(this.mouse); + // position.x and position.y are normalized + // so are the levels + // likely don't need this.value at all -- only used for drawing + // not going to be a 'step' or 'min' and 'max' in this one. + this.calculateLevels(); + this.emit("change", this.levels); + this.render(); + } + } + }, + release: { + value: function release() { + this.render(); + } + }, + normalized: { + get: function () { + return { + x: this.value.x.normalized, + y: this.value.y.normalized + }; + } + }, + calculateLevels: { + value: function calculateLevels() { + var _this = this; + + this.value.x.updateNormal(this.position.x.value); + this.value.y.updateNormal(this.position.y.value); + this.levels = []; + this.speakers.forEach(function (s, i) { + var distance = math.distance(s[0] * _this.width, s[1] * _this.height, _this.position.x.value * _this.width, (1 - _this.position.y.value) * _this.height); + var level = math.clip(1 - distance / (_this.range * _this.width), 0, 1); + _this.levels.push(level); + _this.speakerElements[i].setAttribute("fill-opacity", level); + }); + } + }, + moveSource: { + + /** + Move the audio source node and trigger the output event. + @param x {number} New x location, normalized 0-1 + @param y {number} New y location, normalized 0-1 + */ + + value: function moveSource(x, y) { + var location = { + x: x * this.width, + y: y * this.height + }; + this.position.x.update(location); + this.position.y.update(location); + this.calculateLevels(); + this.emit("change", this.levels); + this.render(); + } + }, + moveSpeaker: { + + /** + Move a speaker node and trigger the output event. + @param index {number} Index of the speaker to move + @param x {number} New x location, normalized 0-1 + @param y {number} New y location, normalized 0-1 + */ + + value: function moveSpeaker(index, x, y) { + + this.speakers[index] = [x, y]; + this.speakerElements[index].setAttribute("cx", x * this.width); + this.speakerElements[index].setAttribute("cy", y * this.height); + this.calculateLevels(); + this.emit("change", this.levels); + this.render(); + } + + /** + Set all speaker locations + @param locations {Array} Array of speaker locations. Each item in the array should be an array of normalized x and y coordinates. + setSpeakers(locations) { + } + */ + + } + }); + + return Pan2D; + })(Interface); + + module.exports = Pan2D; + +/***/ }), +/* 31 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + + var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var math = __webpack_require__(5); + var svg = __webpack_require__(4); + var Interface = __webpack_require__(6); + + /** + * Tilt + * + * @description Device tilt sensor with 2 or 3 axes (depending on your device and browser). + * + * @demo + * + * @example + * var tilt = new Nexus.Tilt('#target') + * + * @output + * change + * Fires at a regular interval, as long as this interface is active (see the interface's .active property)
+ * The event data is an object containing x (number) and y (number) properties which represent the current tilt state of the device. + * + * @outputexample + * tilt.on('change',function(v) { + * console.log(v); + * }) + * + * + */ + + var Tilt = (function (_Interface) { + function Tilt() { + _classCallCheck(this, Tilt); + + var options = ["value"]; + + var defaults = { + size: [80, 80] + }; + + _get(Object.getPrototypeOf(Tilt.prototype), "constructor", this).call(this, arguments, options, defaults); + + this._active = true; + + this.init(); + + // add event listener for device orientation + + this.boundUpdate = this.update.bind(this); + // this.boundMozTilt = this.mozTilt.bind(this) + + if (window.DeviceOrientationEvent) { + this.orientationListener = window.addEventListener("deviceorientation", this.boundUpdate, false); + } else { + this._active = false; + this.colorInterface(); + } + + /*else if (window.OrientationEvent) { + // window.addEventListener('MozOrientation', this.boundMozTilt, false); + } else { + console.log('Not supported on your device or browser.'); + } */ + } + + _inherits(Tilt, _Interface); + + _createClass(Tilt, { + buildInterface: { + value: function buildInterface() { + + this.title = svg.create("text"); + this.circleX = svg.create("circle"); + this.circleY = svg.create("circle"); + this.circleZ = svg.create("circle"); + + this.barX = svg.create("path"); + this.barY = svg.create("path"); + this.barZ = svg.create("path"); + + this.barX2 = svg.create("path"); + this.barY2 = svg.create("path"); + this.barZ2 = svg.create("path"); + + this.barX.setAttribute("opacity", "0.8"); + this.barY.setAttribute("opacity", "0.8"); + this.barZ.setAttribute("opacity", "0.8"); + this.barX2.setAttribute("opacity", "0.8"); + this.barY2.setAttribute("opacity", "0.8"); + this.barZ2.setAttribute("opacity", "0.8"); + + this.circleX.setAttribute("cx", this.width * 3 / 12); + this.circleX.setAttribute("cy", this.height * 3 / 4); + this.circleX.setAttribute("r", this.height / 10); + this.circleX.setAttribute("opacity", "0.4"); + + this.circleY.setAttribute("cx", this.width * 6 / 12); + this.circleY.setAttribute("cy", this.height * 3 / 4); + this.circleY.setAttribute("r", this.height / 10); + this.circleY.setAttribute("opacity", "0.4"); + + this.circleZ.setAttribute("cx", this.width * 9 / 12); + this.circleZ.setAttribute("cy", this.height * 3 / 4); + this.circleZ.setAttribute("r", this.height / 10); + this.circleZ.setAttribute("opacity", "0.4"); + + this.barX.setAttribute("stroke-width", Math.round(this.height / 30)); + this.barY.setAttribute("stroke-width", Math.round(this.height / 30)); + this.barZ.setAttribute("stroke-width", Math.round(this.height / 30)); + + this.barX.setAttribute("fill", "none"); + this.barY.setAttribute("fill", "none"); + this.barZ.setAttribute("fill", "none"); + + this.barX2.setAttribute("stroke-width", Math.round(this.height / 30)); + this.barY2.setAttribute("stroke-width", Math.round(this.height / 30)); + this.barZ2.setAttribute("stroke-width", Math.round(this.height / 30)); + + this.barX2.setAttribute("fill", "none"); + this.barY2.setAttribute("fill", "none"); + this.barZ2.setAttribute("fill", "none"); + + this.title.setAttribute("x", this.width / 2); + this.title.setAttribute("y", this.height / 3 + 7); + this.title.setAttribute("font-size", "15px"); + this.title.setAttribute("font-weight", "bold"); + this.title.setAttribute("letter-spacing", "2px"); + this.title.setAttribute("opacity", "0.7"); + this.title.setAttribute("text-anchor", "middle"); + this.title.textContent = "TILT"; + + this.element.appendChild(this.circleX); + this.element.appendChild(this.circleY); + this.element.appendChild(this.circleZ); + + this.element.appendChild(this.barX); + this.element.appendChild(this.barY); + this.element.appendChild(this.barZ); + + this.element.appendChild(this.barX2); + this.element.appendChild(this.barY2); + this.element.appendChild(this.barZ2); + + this.element.appendChild(this.title); + } + }, + colorInterface: { + value: function colorInterface() { + + if (this._active) { + this.element.style.backgroundColor = this.colors.accent; + this.circleX.setAttribute("fill", this.colors.light); + this.circleY.setAttribute("fill", this.colors.light); + this.circleZ.setAttribute("fill", this.colors.light); + this.circleX.setAttribute("stroke", this.colors.light); + this.circleY.setAttribute("stroke", this.colors.light); + this.circleZ.setAttribute("stroke", this.colors.light); + this.barX.setAttribute("stroke", this.colors.light); + this.barY.setAttribute("stroke", this.colors.light); + this.barZ.setAttribute("stroke", this.colors.light); + this.barX2.setAttribute("stroke", this.colors.light); + this.barY2.setAttribute("stroke", this.colors.light); + this.barZ2.setAttribute("stroke", this.colors.light); + this.title.setAttribute("fill", this.colors.light); + } else { + this.element.style.backgroundColor = this.colors.fill; + this.circleX.setAttribute("fill", this.colors.mediumLight); + this.circleY.setAttribute("fill", this.colors.mediumLight); + this.circleZ.setAttribute("fill", this.colors.mediumLight); + this.circleX.setAttribute("stroke", this.colors.mediumLight); + this.circleY.setAttribute("stroke", this.colors.mediumLight); + this.circleZ.setAttribute("stroke", this.colors.mediumLight); + this.barX.setAttribute("stroke", this.colors.mediumLight); + this.barY.setAttribute("stroke", this.colors.mediumLight); + this.barZ.setAttribute("stroke", this.colors.mediumLight); + this.barX2.setAttribute("stroke", this.colors.mediumLight); + this.barY2.setAttribute("stroke", this.colors.mediumLight); + this.barZ2.setAttribute("stroke", this.colors.mediumLight); + this.title.setAttribute("fill", this.colors.mediumLight); + } + } + }, + update: { + value: function update(v) { + if (this._active) { + + var y = v.beta; + var x = v.gamma; + var z = v.alpha; + + // take the original -90 to 90 scale and normalize it 0-1 + x = math.scale(x, -90, 90, 0, 1); + y = math.scale(y, -90, 90, 0, 1); + z = math.scale(z, 0, 360, 0, 1); + + var handlePoints = { + start: Math.PI * 1.5, + end: math.clip(math.scale(x, 0, 0.5, Math.PI * 1.5, Math.PI * 0.5), Math.PI * 0.5, Math.PI * 1.5) + }; + var handle2Points = { + start: Math.PI * 2.5, + end: math.clip(math.scale(x, 0.5, 1, Math.PI * 2.5, Math.PI * 1.5), Math.PI * 1.5, Math.PI * 2.5) + }; + + var handlePath = svg.arc(this.circleX.cx.baseVal.value, this.circleX.cy.baseVal.value, this.circleX.r.baseVal.value, handlePoints.start, handlePoints.end); + var handle2Path = svg.arc(this.circleX.cx.baseVal.value, this.circleX.cy.baseVal.value, this.circleX.r.baseVal.value, handle2Points.start, handle2Points.end); + + this.barX.setAttribute("d", handlePath); + this.barX2.setAttribute("d", handle2Path); + + handlePoints = { + start: Math.PI * 1.5, + end: math.clip(math.scale(y, 0, 0.5, Math.PI * 1.5, Math.PI * 0.5), Math.PI * 0.5, Math.PI * 1.5) + }; + handle2Points = { + start: Math.PI * 2.5, + end: math.clip(math.scale(y, 0.5, 1, Math.PI * 2.5, Math.PI * 1.5), Math.PI * 1.5, Math.PI * 2.5) + }; + + handlePath = svg.arc(this.circleY.cx.baseVal.value, this.circleY.cy.baseVal.value, this.circleY.r.baseVal.value, handlePoints.start, handlePoints.end); + handle2Path = svg.arc(this.circleY.cx.baseVal.value, this.circleY.cy.baseVal.value, this.circleY.r.baseVal.value, handle2Points.start, handle2Points.end); + + this.barY.setAttribute("d", handlePath); + this.barY2.setAttribute("d", handle2Path); + + handlePoints = { + start: Math.PI * 1.5, + end: math.clip(math.scale(z, 0, 0.5, Math.PI * 1.5, Math.PI * 0.5), Math.PI * 0.5, Math.PI * 1.5) + }; + handle2Points = { + start: Math.PI * 2.5, + end: math.clip(math.scale(z, 0.5, 1, Math.PI * 2.5, Math.PI * 1.5), Math.PI * 1.5, Math.PI * 2.5) + }; + + handlePath = svg.arc(this.circleZ.cx.baseVal.value, this.circleZ.cy.baseVal.value, this.circleZ.r.baseVal.value, handlePoints.start, handlePoints.end); + handle2Path = svg.arc(this.circleZ.cx.baseVal.value, this.circleZ.cy.baseVal.value, this.circleZ.r.baseVal.value, handle2Points.start, handle2Points.end); + + this.barZ.setAttribute("d", handlePath); + this.barZ2.setAttribute("d", handle2Path); + + /* + let pointsX = { + start: 0, + end: math.scale( x, 0, 1, 0, Math.PI*2 ) + }; + // console.log(this.circleX.cx.baseVal.value); + let pathX = svg.arc(this.circleX.cx.baseVal.value, this.circleX.cy.baseVal.value, this.circleX.r.baseVal.value*2, pointsX.start, pointsX.end); + this.barX.setAttribute('d',pathX); */ + + //this.textH.textContent = math.prune(x,2); + //this.textV.textContent = math.prune(y,2); + // + // this.circleX.setAttribute('opacity',x); + // this.circleY.setAttribute('opacity',y); + // this.circleZ.setAttribute('opacity',z); + + this.emit("change", { + x: x, + y: y, + z: z + }); + } + } + }, + click: { + value: function click() { + if (window.DeviceOrientationEvent) { + this.active = !this.active; + } + } + }, + active: { + + /** + Whether the interface is on (emitting values) or off (paused & not emitting values). Setting this property will update it. + @type {boolean} + */ + + get: function () { + return this._active; + }, + set: function (on) { + this._active = on; + this.colorInterface(); + } + }, + customDestroy: { + value: function customDestroy() { + window.removeEventListener("deviceorientation", this.boundUpdate, false); + } + } + }); + + return Tilt; + })(Interface); + + module.exports = Tilt; + +/***/ }), +/* 32 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + + var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var math = __webpack_require__(5); + var svg = __webpack_require__(4); + var Interface = __webpack_require__(6); + + /** + * Multislider + * + * @description Multislider + * + * @demo + * + * @example + * var multislider = new Nexus.Multislider('#target') + * + * @example + * var multislider = new Nexus.Multislider('#target',{ + * 'size': [200,100], + * 'numberOfSliders': 5, + * 'min': 0, + * 'max': 1, + * 'step': 0, + * 'candycane': 3, + * 'values': [0.9,0.8,0.7,0.6,0.5,0.4,0.3,0.2,0.1], + * 'smoothing': 0, + * 'mode': 'bar' // 'bar' or 'line' + *}) + * + * @output + * change + * Fires any time the interface's value changes.
+ * The event data is an object containing index and value properties + * + * @outputexample + * multislider.on('change',function(v) { + * console.log(v); + * }) + * + */ + + var Multislider = (function (_Interface) { + function Multislider() { + _classCallCheck(this, Multislider); + + var options = ["value"]; + + var defaults = { + size: [200, 100], + numberOfSliders: 5, + min: 0, + max: 1, + step: 0, + candycane: 3, + values: [0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1], + smoothing: 0, + mode: "bar" // 'bar', 'line' + }; + + _get(Object.getPrototypeOf(Multislider.prototype), "constructor", this).call(this, arguments, options, defaults); + + this._numberOfSliders = this.settings.numberOfSliders; + this._min = this.settings.min; + this._max = this.settings.max; + this._step = this.settings.step; + + this._mode = this.settings.mode; + + /** + The current values of the slider. NOTE: Use this only to get the current values. Setting this array will not update the multislider. To set the multislider's values, use setSlider() or setAllSliders() + @type {Array} + */ + this.values = this.settings.values; + + this.candycane = this.settings.candycane; + + this.sliderWidth = this.width / this.values.length; + + /** + Applies a simple low-pass filter to the multislider as it is interacted with. A smoothing of 0 will be no smoothing. A smoothing of 1 will smooth 1 slider on each side of the interaction. A smoothing of 2 will smooth 2 sliders on each side, and so on. + @type {Number} + */ + this.smoothing = this.settings.smoothing; + + this.init(); + this.render(); + } + + _inherits(Multislider, _Interface); + + _createClass(Multislider, { + buildInterface: { + value: function buildInterface() { + + if (this._mode == "line") { + + this.line = svg.create("polyline"); + this.line.setAttribute("stroke-width", 2); + this.line.setAttribute("fill", "none"); + + this.element.appendChild(this.line); + + this.fill = svg.create("polyline"); + this.fill.setAttribute("fill-opacity", "0.2"); + + this.element.appendChild(this.fill); + + this.nodes = []; + + this.values.forEach((function (value, index) { + + var node = svg.create("circle"); + + node.setAttribute("cx", this.getX(index)); + node.setAttribute("cy", this.getY(value)); + + this.element.appendChild(node); + this.nodes.push(node); + }).bind(this)); + } else { + + this.bars = []; + this.caps = []; + + this.values.forEach((function (value, index) { + + var bar = svg.create("rect"); + + var x = this.getBarX(index); + var y = this.getY(value); + + bar.setAttribute("x", x - 0.1); + bar.setAttribute("y", y); + bar.setAttribute("width", this.sliderWidth + 0.2); + bar.setAttribute("height", this.height); + bar.setAttribute("opacity", 1 - (index % this.candycane + 1) / (this.candycane + 1)); + + this.element.appendChild(bar); + this.bars.push(bar); + + var cap = svg.create("rect"); + + cap.setAttribute("x", x - 0.1); + cap.setAttribute("y", y); + cap.setAttribute("width", this.sliderWidth + 0.2); + cap.setAttribute("height", 5); + + this.element.appendChild(cap); + this.caps.push(cap); + }).bind(this)); + } + } + }, + getBarX: { + value: function getBarX(index) { + return this.getX(index) - this.sliderWidth / 2; + } + }, + getX: { + value: function getX(index) { + //return Math.floor( index * this.sliderWidth + this.sliderWidth/2 ); + return index * this.sliderWidth + this.sliderWidth / 2; + } + }, + getY: { + value: function getY(value) { + return math.scale(value, this._min, this._max, this.height, 0); //(1 - value) * this.height; + } + }, + getValueFromY: { + value: function getValueFromY(y) { + var scaleAdjusted = math.scale(y, this.height, 0, this._min, this._max); + return this.adjustValueToStep(scaleAdjusted); + } + }, + getIndexFromX: { + value: function getIndexFromX(x) { + return math.clip(Math.floor(x / this.width * this.values.length), 0, this.values.length - 1); + } + }, + adjustValueToStep: { + value: function adjustValueToStep(value) { + if (!this._step) { + return value; + } + var offset = value % this._step; + value = value - value % this._step; + if (offset > this._step / 2) { + value += this._step; + } + return value; + } + }, + adjustAllValues: { + value: function adjustAllValues() { + this.values.forEach((function (value, index) { + value = this.adjustValueToStep(value); + this.values[index] = math.clip(value, this._min, this._max); + }).bind(this)); + } + }, + getNormalizedValues: { + value: function getNormalizedValues() { + this.normalizedValues = []; + this.values.forEach((function (value) { + this.normalizedValues.push(math.scale(value, this._min, this._max, 0, 1)); + }).bind(this)); + } + }, + colorInterface: { + value: function colorInterface() { + var _this = this; + + this.element.style.backgroundColor = this.colors.fill; + + if (this._mode == "line") { + this.line.setAttribute("stroke", this.colors.accent); + this.fill.setAttribute("fill", this.colors.accent); + this.nodes.forEach(function (node) { + node.setAttribute("fill", _this.colors.accent); + }); + } else { + this.bars.forEach(function (bar) { + bar.setAttribute("fill", _this.colors.accent); + }); + this.caps.forEach(function (cap) { + cap.setAttribute("fill", _this.colors.accent); + }); + } + } + }, + sizeInterface: { + value: function sizeInterface() { + + this.sliderWidth = this.width / this.values.length; + + if (this._mode == "line") { + this.nodes.forEach((function (node) { + var r = ~ ~(Math.min(this.width, this.height) / 50) + 2; + r = Math.min(this.sliderWidth, r); + node.setAttribute("r", r); + }).bind(this)); + } + + this.render(); + } + }, + render: { + value: function render() { + var _this = this; + + if (this._mode == "line") { + (function () { + + var data = "0 " + _this.getY(_this.values[0]) + ", "; + + _this.values.forEach(function (value, index) { + var x = _this.getX(index); + var y = _this.getY(value); + data += x + " " + y + ", "; + _this.nodes[index].setAttribute("cx", _this.getX(index)); + _this.nodes[index].setAttribute("cy", _this.getY(value)); + }); + + data += _this.width + " " + _this.getY(_this.values[_this.values.length - 1]); + + _this.line.setAttribute("points", data); + + // fill data + // add bottom corners + + data += ", " + _this.width + " " + _this.height + ", "; + data += "0 " + _this.height; + + _this.fill.setAttribute("points", data); + })(); + } else { + + this.values.forEach(function (value, index) { + _this.bars[index].setAttribute("y", _this.getY(value)); + _this.caps[index].setAttribute("y", _this.getY(value)); + }); + } + } + }, + click: { + value: function click() { + this.hasMoved = false; + this.previousSlider = false; + this.move(); + } + }, + move: { + value: function move() { + if (this.clicked) { + this.mouse.x = math.clip(this.mouse.x, 0, this.width); + this.mouse.y = math.clip(this.mouse.y, 0, this.height); + this.hasMoved = true; + + this.selectedSlider = this.getIndexFromX(this.mouse.x); + + this.values[this.selectedSlider] = this.getValueFromY(this.mouse.y); + + /* handle interpolation for in-between sliders */ + + if (this.previousSlider !== false) { + var distance = Math.abs(this.previousSlider - this.selectedSlider); + if (distance > 1) { + var low = Math.min(this.previousSlider, this.selectedSlider); + var high = Math.max(this.previousSlider, this.selectedSlider); + var lowValue = this.values[low]; + var highValue = this.values[high]; + for (var _i = low; _i < high; _i++) { + this.values[_i] = math.interp((_i - low) / distance, lowValue, highValue); + this.values[_i] = this.adjustValueToStep(this.values[_i]); + } + } + } + + if (this.smoothing > 0) { + + for (var i = 1; i <= this.smoothing; i++) { + var downCenter = this.selectedSlider - i; + var upCenter = this.selectedSlider + i; + + if (downCenter >= 1) { + var downLowerNeighbor = downCenter - 1 >= 0 ? downCenter - 1 : 0; + var downUpperNeighbor = downCenter + 1; + this.values[downCenter] = (this.values[downLowerNeighbor] + this.values[downUpperNeighbor]) / 2; + this.values[downCenter] = this.adjustValueToStep(this.values[downCenter]); + } + + if (upCenter < this.values.length - 1) { + var upLowerNeighbor = upCenter - 1; + var upUpperNeighbor = upCenter + 1 < this.values.length ? upCenter + 1 : this.values.length - 1; + this.values[upCenter] = (this.values[upLowerNeighbor] + this.values[upUpperNeighbor]) / 2; + this.values[upCenter] = this.adjustValueToStep(this.values[upCenter]); + } + } + } + + this.previousSlider = this.selectedSlider; + + this.emit("change", this.values); + this.render(); + } + } + }, + scan: { + + // would be a cool API call to have for later... + + value: function scan() {} + }, + update: { + value: function update(index, value) { + this.values[index] = this.adjustValueToStep(value); + this.emit("change", { + index: index, + value: value + }); + } + }, + numberOfSliders: { + + /** + Get the number of sliders + @type {Number} + */ + + get: function () { + return this.values.length; + } + }, + min: { + + /** + Lower limit of the multislider's output range + @type {number} + @example multislider.min = 1000; + */ + + get: function () { + return this._min; + }, + set: function (v) { + this._min = v; + this.adjustAllValues(); + this.render(); + } + }, + max: { + + /** + Upper limit of the multislider's output range + @type {number} + @example multislider.max = 1000; + */ + + get: function () { + return this._max; + }, + set: function (v) { + this._max = v; + this.adjustAllValues(); + this.render(); + } + }, + step: { + + /** + The increment that the multislider's value changes by. + @type {number} + @example multislider.step = 5; + */ + + get: function () { + return this._step; + }, + set: function (v) { + this._step = v; + this.adjustAllValues(); + this.render(); + } + }, + setSlider: { + + /** + Set the value of an individual slider + @param index {number} Slider index + @param value {number} New slider value + @example + // Set the first slider to value 0.5 + multislider.setSlider(0,0.5) + */ + + value: function setSlider(index, value) { + this.values[index] = this.adjustValueToStep(value); + this.values[index] = math.clip(this.values[index], this._min, this._max); + this.emit("change", { + index: index, + value: value + }); + } + }, + setAllSliders: { + + /** + Set the value of all sliders at once. If the size of the input array does not match the current number of sliders, the value array will repeat until all sliders have been set. I.e. an input array of length 1 will set all sliders to that value. + @param values {Array} All slider values + @example + multislider.setAllSliders([0.2,0.3,0.4,0.5,0.6]) + */ + + value: function setAllSliders(values) { + var previousLength = this.values.length; + var newLength = values.length; + this.values = values; + this.adjustAllValues(); + if (previousLength != newLength) { + this.empty(); + this.buildInterface(); + this.colorInterface(); + } + this.sizeInterface(); + } + } + }); + + return Multislider; + })(Interface); + + module.exports = Multislider; + +/***/ }), +/* 33 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { "default": obj }; }; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + + var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var svg = __webpack_require__(4); + var math = __webpack_require__(5); + var Interface = __webpack_require__(6); + var Step = __webpack_require__(11); + + var Interaction = _interopRequireWildcard(__webpack_require__(12)); + + /** + * Pan + * + * @description Stereo crossfader. + * + * @demo + * + * @example + * var pan = new Nexus.Pan('#target') + * + * @output + * change + * Fires any time the interface's value changes.
+ * The event data is an object containing the interface's value (-1 to 1), as well as L and R amplitude values (0-1) for left and right speakers, calculated by a square-root crossfade algorithm. + * + * @outputexample + * pan.on('change',function(v) { + * console.log(v); + * }) + * + * + */ + + var Pan = (function (_Interface) { + function Pan() { + _classCallCheck(this, Pan); + + var options = ["scale", "value"]; + + var defaults = { + size: [120, 20], + orientation: "horizontal", + mode: "relative", + scale: [-1, 1], + step: 0, + value: 0, + hasKnob: true + }; + + _get(Object.getPrototypeOf(Pan.prototype), "constructor", this).call(this, arguments, options, defaults); + + this.orientation = this.settings.orientation; + + this.mode = this.settings.mode; + + this.hasKnob = this.settings.hasKnob; + + // this.step should eventually be get/set + // updating it will update the _value step model + this.step = this.settings.step; // float + + this._value = new Step(this.settings.scale[0], this.settings.scale[1], this.settings.step, this.settings.value); + + this.init(); + + this.position = new Interaction.Handle(this.mode, this.orientation, [0, this.width], [this.height, 0]); + this.position.value = this._value.normalized; + + this.value = this._value.value; + + this.emit("change", this.value); + } + + _inherits(Pan, _Interface); + + _createClass(Pan, { + buildInterface: { + value: function buildInterface() { + + this.bar = svg.create("rect"); + this.knob = svg.create("circle"); + + this.element.appendChild(this.bar); + this.element.appendChild(this.knob); + } + }, + sizeInterface: { + value: function sizeInterface() { + + if (this.position) { + this.position.resize([0, this.width], [this.height, 0]); + } + + if (this.width < this.height) { + this.orientation = "vertical"; + } else { + this.orientation = "horizontal"; + } + + var x = undefined, + y = undefined, + w = undefined, + h = undefined, + barOffset = undefined, + cornerRadius = undefined; + this.knobData = { + level: 0, + r: 0 + }; + + if (this.orientation === "vertical") { + this.thickness = this.width / 2; + x = this.width / 2; + y = 0; + w = this.thickness; + h = this.height; + this.knobData.r = this.thickness * 0.8; + this.knobData.level = h - this.knobData.r - this.normalized * (h - this.knobData.r * 2); + barOffset = "translate(" + this.thickness * -1 / 2 + ",0)"; + cornerRadius = w / 2; + } else { + this.thickness = this.height / 2; + x = 0; + y = this.height / 2; + w = this.width; + h = this.thickness; + this.knobData.r = this.thickness * 0.8; + this.knobData.level = this.normalized * (w - this.knobData.r * 2) + this.knobData.r; + barOffset = "translate(0," + this.thickness * -1 / 2 + ")"; + cornerRadius = h / 2; + } + + this.bar.setAttribute("x", x); + this.bar.setAttribute("y", y); + this.bar.setAttribute("transform", barOffset); + this.bar.setAttribute("rx", cornerRadius); // corner radius + this.bar.setAttribute("ry", cornerRadius); + this.bar.setAttribute("width", w); + this.bar.setAttribute("height", h); + + if (this.orientation === "vertical") { + this.knob.setAttribute("cx", x); + this.knob.setAttribute("cy", this.knobData.level); + } else { + this.knob.setAttribute("cx", this.knobData.level); + this.knob.setAttribute("cy", y); + } + this.knob.setAttribute("r", this.knobData.r); + } + }, + colorInterface: { + value: function colorInterface() { + + this.bar.setAttribute("fill", this.colors.fill); + this.knob.setAttribute("fill", this.colors.accent); + + if (!this.hasKnob) { + this.knob.setAttribute("fill", "transparent"); + } + } + }, + render: { + value: function render() { + if (!this.clicked) { + this.knobData.r = this.thickness * 0.75; + } + this.knob.setAttribute("r", this.knobData.r); + + if (this.orientation === "vertical") { + this.knobData.level = this.knobData.r + this._value.normalized * (this.height - this.knobData.r * 2); + this.knob.setAttribute("cy", this.height - this.knobData.level); + } else { + this.knobData.level = this._value.normalized * (this.width - this.knobData.r * 2) + this.knobData.r; + this.knob.setAttribute("cx", this.knobData.level); + } + } + }, + click: { + value: function click() { + this.knobData.r = this.thickness * 0.9; + this.position.anchor = this.mouse; + this.move(); + } + }, + move: { + value: function move() { + if (this.clicked) { + this.position.update(this.mouse); + + this.value = this._value.updateNormal(this.position.value); + + this.emit("change", { + value: this.value, + L: Math.pow(math.scale(this.value, -1, 1, 1, 0), 2), + R: Math.pow(math.scale(this.value, -1, 1, 0, 1), 2) + }); + } + } + }, + release: { + value: function release() { + this.render(); + } + }, + value: { + + /** + The position of crossfader, from -1 (left) to 1 (right). Setting this value updates the interface and triggers the output event. + @type {number} + */ + + get: function () { + return this._value.value; + }, + set: function (value) { + this._value.update(value); + this.position.value = this._value.normalized; + this.emit("change", { + value: this.value, + L: Math.pow(math.scale(this.value, -1, 1, 1, 0), 2), + R: Math.pow(math.scale(this.value, -1, 1, 0, 1), 2) + }); + this.render(); + } + }, + normalized: { + get: function () { + return this._value.normalized; + } + } + }); + + return Pan; + })(Interface); + + module.exports = Pan; + +/***/ }), +/* 34 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + + var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var math = __webpack_require__(5); + var svg = __webpack_require__(4); + var Interface = __webpack_require__(6); + + var Point = function Point(point, envelope) { + + this.x = point.x; + this.y = point.y; + + this.xMin = point.xMin || 0; + this.xMax = point.xMax || 1; + this.yMin = point.yMin || 0; + this.yMax = point.yMax || 1; + + this.envelope = envelope; + + this.element = svg.create("circle"); + this.element.setAttribute("fill", this.envelope.colors.accent); + + this.envelope.element.appendChild(this.element); + + this.resize = function () { + var r = ~ ~(Math.min(this.envelope.width, this.envelope.height) / 50) + 2; + this.element.setAttribute("r", r); + }; + + this.move = function (x, y) { + + this.x = x || x === 0 ? x : this.x; + this.y = y || y === 0 ? y : this.y; + + if (this.envelope.nodes.indexOf(this) >= 0) { + + var prevIndex = this.envelope.nodes.indexOf(this) - 1; + var nextIndex = this.envelope.nodes.indexOf(this) + 1; + + var prevNode = this.envelope.nodes[prevIndex]; + var nextNode = this.envelope.nodes[nextIndex]; + + var lowX = prevIndex >= 0 ? prevNode.x : 0; + lowX = lowX < this.xMin ? this.xMin : lowX; + + var highX = nextIndex < this.envelope.nodes.length ? nextNode.x : 1; + highX = highX > this.xMax ? this.xMax : highX; + + if (this.x < lowX) { + this.x = lowX; + } + if (this.x > highX) { + this.x = highX; + } + + if (this.y < this.yMin) { + this.y = this.yMin; + } + if (this.y > this.yMax) { + this.y = this.yMax; + } + } + + this.location = this.getCoordinates(); + this.element.setAttribute("cx", this.location.x); + this.element.setAttribute("cy", this.location.y); + }; + + this.getCoordinates = function () { + return { + x: this.x * this.envelope.width, + y: (1 - this.y) * this.envelope.height + }; + }; + + this.move(this.x, this.y, true); + this.resize(); + + this.destroy = function () { + this.envelope.element.removeChild(this.element); + this.envelope.nodes.splice(this.envelope.nodes.indexOf(this), 1); + }; + }; + + /** + * Envelope + * + * @description Interactive linear ramp visualization. + * + * @demo + * + * @example + * var envelope = new Nexus.Envelope('#target') + * + * @example + * var envelope = new Nexus.Envelope('#target',{ + * 'size': [300,150], + * 'noNewPoints': false, + * 'points': [ + * { + * x: 0.1, + * y: 0.4 + * }, + * { + * x: 0.35, + * y: 0.6 + * }, + * { + * x: 0.65, + * y: 0.2 + * }, + * { + * x: 0.9, + * y: 0.4 + * }, + * ] + * }) + * + * @output + * change + * Fires any time a node is moved.
+ * The event data is an array of point locations. Each item in the array is an object containing x and y properties describing the location of a point on the envelope. + * + * @outputexample + * envelope.on('change',function(v) { + * console.log(v); + * }) + * + */ + + var Envelope = (function (_Interface) { + function Envelope() { + _classCallCheck(this, Envelope); + + var options = ["value"]; + + var defaults = { + size: [300, 150], + noNewPoints: false, + points: [{ + x: 0.1, + y: 0.4 + }, { + x: 0.35, + y: 0.6 + }, { + x: 0.65, + y: 0.2 + }, { + x: 0.9, + y: 0.4 + }] + }; + + _get(Object.getPrototypeOf(Envelope.prototype), "constructor", this).call(this, arguments, options, defaults); + + this.points = this.settings.points; + + this.nodes = []; + + this.selected = false; + + this.init(); + } + + _inherits(Envelope, _Interface); + + _createClass(Envelope, { + buildInterface: { + value: function buildInterface() { + var _this = this; + + this.points.forEach(function (point) { + var node = new Point(point, _this); + _this.nodes.push(node); + }); + + this.sortPoints(); + + this.line = svg.create("polyline"); + this.line.setAttribute("stroke-width", 2); + this.line.setAttribute("fill", "none"); + + this.element.appendChild(this.line); + + this.fill = svg.create("polyline"); + this.fill.setAttribute("fill-opacity", "0.2"); + + this.element.appendChild(this.fill); + } + }, + sizeInterface: { + value: function sizeInterface() { + + for (var i = 0; i < this.nodes.length; i++) { + this.nodes[i].resize(); + this.nodes[i].move(); + } + + this.render(); + } + }, + colorInterface: { + value: function colorInterface() { + var _this = this; + + this.element.style.backgroundColor = this.colors.fill; + this.line.setAttribute("stroke", this.colors.accent); + this.fill.setAttribute("fill", this.colors.accent); + this.nodes.forEach(function (node) { + node.element.setAttribute("fill", _this.colors.accent); + }); + } + }, + render: { + value: function render() { + // this.nodes[this.selected].move( this.points ) + this.calculatePath(); + } + }, + calculatePoints: { + value: function calculatePoints() { + var _this = this; + + this.points = []; + this.nodes.forEach(function (node) { + _this.points.push({ x: node.x, y: node.y }); + }); + } + }, + calculatePath: { + value: function calculatePath() { + + //stroke data + var data = "0 " + this.nodes[0].location.y + ", "; + + // data should be re-ordered based on x location. + // whatever function adds a node should add it at the right index + + this.nodes.forEach(function (node) { + // let location = node.getCoordinates(); + data += node.location.x + " " + node.location.y + ", "; + }); + + // data += point.x*this.width+' '+ point.y*this.height+', '; + data += this.width + " " + this.nodes[this.nodes.length - 1].location.y; + + this.line.setAttribute("points", data); + + // fill data + // add bottom corners + + data += ", " + this.width + " " + this.height + ", "; + data += "0 " + this.height; + + this.fill.setAttribute("points", data); + } + }, + click: { + value: function click() { + // find nearest node and set this.selected (index) + this.hasMoved = false; + this.selected = this.findNearestNode(); + + this.nodes[this.selected].move(this.mouse.x / this.width, 1 - this.mouse.y / this.height); + this.scaleNode(this.selected); + + // must do this b/c new node may have been created + this.calculatePoints(); + this.emit("change", this.points); + this.render(); + } + }, + move: { + value: function move() { + if (this.clicked) { + this.mouse.x = math.clip(this.mouse.x, 0, this.width); + this.hasMoved = true; + + this.nodes[this.selected].move(this.mouse.x / this.width, 1 - this.mouse.y / this.height); + this.scaleNode(this.selected); + + this.calculatePoints(); + this.emit("change", this.points); + this.render(); + } + } + }, + release: { + value: function release() { + + if (!this.hasMoved) { + this.nodes[this.selected].destroy(); + } + + this.calculatePoints(); + this.emit("change", this.points); + this.render(); + + // reset this.selected + this.selected = null; + } + }, + findNearestNode: { + value: function findNearestNode() { + var nearestIndex = null; + // set this unreasonably high so that every distance will be lower than it. + var nearestDist = 10000; + var before = false; + var x = this.mouse.x / this.width; + var y = 1 - this.mouse.y / this.height; + var nodes = this.nodes; + for (var i = 0; i < nodes.length; i++) { + + // calculate the distance from mouse to this node using pythagorean theorem + var distance = Math.sqrt(Math.pow(nodes[i].x - x, 2) + Math.pow(nodes[i].y - y, 2)); + + // if this distance is less than the previous shortest distance, use this index + if (distance < nearestDist) { + nearestDist = distance; + nearestIndex = i; + before = x > nodes[i].x; + } + } + + // if not very close to any node, create a node + if (!this.settings.noNewPoints && nearestDist > 0.07) { + + nearestIndex = this.getIndexFromX(this.mouse.x / this.width); + + this.nodes.splice(nearestIndex, 0, new Point({ + x: this.mouse.x / this.width, + y: 1 - this.mouse.y / this.height + }, this)); + this.hasMoved = true; + } + + return nearestIndex; + } + }, + getIndexFromX: { + value: function getIndexFromX(x) { + var _this = this; + + var index = 0; + this.nodes.forEach(function (node, i) { + if (_this.nodes[i].x <= x) { + index = i + 1; + } + }); + return index; + } + }, + scaleNode: { + value: function scaleNode(i) { + + var clippedX = math.clip(this.nodes[i].x, 0, 1); + var clippedY = math.clip(this.nodes[i].y, 0, 1); + + this.nodes[i].move(clippedX, clippedY); + } + }, + sortPoints: { + + /** + Sort the this.points array from left-most point to right-most point. You should not regularly need to use this, however it may be useful if the points get unordered. + */ + + value: function sortPoints() { + this.nodes.sort(function (a, b) { + return a.x > b.x; + }); + } + }, + addPoint: { + + /** + Add a breakpoint on the envelope. + @param x {number} x location of the point, normalized (0-1) + @param y {number} y location of the point, normalized (0-1) + */ + + value: function addPoint(x, y) { + var index = this.nodes.length; + + this.sortPoints(); + + for (var i = 0; i < this.nodes.length; i++) { + if (x < this.nodes[i].x) { + index = i; + break; + } + } + + this.nodes.splice(index, 0, new Point({ + x: x, + y: y + }, this)); + + this.scaleNode(index); + + this.calculatePoints(); + this.emit("change", this.points); + + this.render(); + } + }, + scan: { + + /** + Find the level at a certain x location on the envelope. + @param x {number} The x location to find the level of, normalized 0-1 + */ + + value: function scan(x) { + // find surrounding points + var nextIndex = this.getIndexFromX(x); + var priorIndex = nextIndex - 1; + if (priorIndex < 0) { + priorIndex = 0; + } + if (nextIndex >= this.nodes.length) { + nextIndex = this.nodes.length - 1; + } + var priorPoint = this.nodes[priorIndex]; + var nextPoint = this.nodes[nextIndex]; + var loc = math.scale(x, priorPoint.x, nextPoint.x, 0, 1); + var value = math.interp(loc, priorPoint.y, nextPoint.y); + this.emit("scan", value); + return value; + } + }, + movePoint: { + + /** + Move a breakpoint on the envelope. + @param index {number} The index of the breakpoint to move + @param x {number} New x location, normalized 0-1 + @param y {number} New y location, normalized 0-1 + */ + + value: function movePoint(index, x, y) { + this.nodes[index].move(x, y); + this.scaleNode(index); + this.calculatePoints(); + this.emit("change", this.points); + this.render(); + } + }, + adjustPoint: { + + /** + Move a breakpoint on the envelope by a certain amount. + @param index {number} The index of the breakpoint to move + @param xOffset {number} X displacement, normalized 0-1 + @param yOffset {number} Y displacement, normalized 0-1 + */ + + value: function adjustPoint(index, xOffset, yOffset) { + this.nodes[index].move(this.nodes[index].x + xOffset, this.nodes[index].y + yOffset); + this.scaleNode(index); + this.calculatePoints(); + this.emit("change", this.points); + this.render(); + } + }, + destroyPoint: { + + /** + Remove a breakpoint from the envelope. + @param index {number} Index of the breakpoint to remove + */ + + value: function destroyPoint(index) { + this.nodes[index].destroy(); + this.calculatePoints(); + this.emit("change", this.points); + this.render(); + } + }, + setPoints: { + + /** + Remove all existing breakpoints and add an entirely new set of breakpoints. + @param allPoints {array} An array of objects with x/y properties (normalized 0-1). Each object in the array specifices the x/y location of a new breakpoint to be added. + */ + + value: function setPoints(allPoints) { + var _this = this; + + while (this.nodes.length) { + this.nodes[0].destroy(); + } + allPoints.forEach(function (point) { + _this.addPoint(point.x, point.y); + }); + this.calculatePoints(); + this.emit("change", this.points); + this.render(); + } + } + }); + + return Envelope; + })(Interface); + + module.exports = Envelope; + +/***/ }), +/* 35 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + + var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var dom = __webpack_require__(7); + //let math = require('../util/math'); + var Interface = __webpack_require__(6); + + var context = __webpack_require__(1).context; + + /** + * Spectrogram + * + * @description Audio spectrum visualization + * + * @demo + * + * @example + * var spectrogram = new Nexus.Spectrogram('#target') + * + * @example + * var spectrogram = new Nexus.Spectrogram('#target',{ + * 'size': [300,150] + * }) + * + * @output + *   + * No events + * + */ + + var Spectrogram = (function (_Interface) { + function Spectrogram() { + _classCallCheck(this, Spectrogram); + + var options = ["scale", "value"]; + + var defaults = { + size: [300, 150] + }; + + _get(Object.getPrototypeOf(Spectrogram.prototype), "constructor", this).call(this, arguments, options, defaults); + + this.context = context(); // jshint ignore:line + + this.analyser = this.context.createAnalyser(); + this.analyser.fftSize = 2048; + this.bufferLength = this.analyser.frequencyBinCount; + this.dataArray = new Uint8Array(this.bufferLength); + + this.active = true; + + this.source = false; + + this.init(); + } + + _inherits(Spectrogram, _Interface); + + _createClass(Spectrogram, { + buildFrame: { + value: function buildFrame() { + this.canvas = new dom.SmartCanvas(this.parent); + this.element = this.canvas.element; + } + }, + sizeInterface: { + value: function sizeInterface() { + this.canvas.resize(this.width, this.height); + } + }, + colorInterface: { + value: function colorInterface() { + this.canvas.element.style.backgroundColor = this.colors.fill; + } + }, + render: { + value: function render() { + if (this.active) { + requestAnimationFrame(this.render.bind(this)); + } + + this.analyser.getByteFrequencyData(this.dataArray); + + this.canvas.context.fillStyle = this.colors.fill; + this.canvas.context.fillRect(0, 0, this.canvas.element.width, this.canvas.element.height); + + if (this.source && this.dataArray) { + //console.log(this.dataArray); + + var barWidth = this.canvas.element.width / this.bufferLength; + var barHeight = undefined; + var x = 0; + + var definition = this.canvas.element.width / 50; + + for (var i = 0; i < this.bufferLength; i = i + definition) { + barHeight = Math.max.apply(null, this.dataArray.subarray(i, i + definition)); + barHeight /= 255; + barHeight *= this.canvas.element.height; + + this.canvas.context.fillStyle = this.colors.accent; + this.canvas.context.fillRect(x, this.canvas.element.height - barHeight, barWidth * definition, barHeight); + + x += barWidth * definition; + } + } + } + }, + connect: { + + /** + Equivalent to "patching in" an audio node to visualize. NOTE: You cannot connect audio nodes across two different audio contexts. NexusUI runs its audio analysis on its own audio context, Nexus.context. If the audio node you are visualizing is created on a different audio context, you will need to tell NexusUI to use that context instead: i.e. Nexus.context = YourAudioContextName. For example, in ToneJS projects, the line would be: Nexus.context = Tone.context . We recommend that you write that line of code only once at the beginning of your project. + @param node {AudioNode} The audio node to visualize + @example Nexus.context = Tone.context // or another audio context you have created + spectrogram.connect( Tone.Master ); + */ + + value: function connect(node) { + if (this.source) { + this.disconnect(); + } + this.source = node; + this.source.connect(this.analyser); + this.render(); + } + }, + disconnect: { + + /** + Stop visualizing the source node and disconnect it. + */ + + value: function disconnect() { + this.source.disconnect(this.analyser); + this.source = null; + } + }, + click: { + value: function click() { + this.active = !this.active; + this.render(); + } + }, + customDestroy: { + value: function customDestroy() { + this.active = false; + } + } + }); + + return Spectrogram; + })(Interface); + + module.exports = Spectrogram; + +/***/ }), +/* 36 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + + var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var dom = __webpack_require__(7); + var math = __webpack_require__(5); + var Interface = __webpack_require__(6); + + var context = __webpack_require__(1).context; + + /** + * Meter + * + * @description Stereo decibel meter + * + * @demo + * + * @example + * var meter = new Nexus.Meter('#target') + * + * @example + * var meter = new Nexus.Meter('#target',{ + * size: [75,75] + * }) + * + * @output + *   + * No events + * + */ + + var Meter = (function (_Interface) { + function Meter() { + _classCallCheck(this, Meter); + + var options = ["scale", "value"]; + + var defaults = { + size: [30, 100] + }; + + _get(Object.getPrototypeOf(Meter.prototype), "constructor", this).call(this, arguments, options, defaults); + + this.context = context(); // jshint ignore:line + + this.channels = 2; + + this.splitter = this.context.createChannelSplitter(this.channels); + + this.analysers = []; + + for (var i = 0; i < this.channels; i++) { + var analyser = this.context.createAnalyser(); + this.splitter.connect(analyser, i); + analyser.fftSize = 1024; + analyser.smoothingTimeConstant = 1; + this.analysers.push(analyser); + } + this.bufferLength = this.analysers[0].frequencyBinCount; + this.dataArray = new Float32Array(this.bufferLength); + + /* + // add linear gradient + var grd = canvasCtx.createLinearGradient(0, 0, 0, canvas.height); + // light blue + grd.addColorStop(0, '#000'); + grd.addColorStop(0.2, '#bbb'); + grd.addColorStop(0.4, '#d18'); + // dark blue + grd.addColorStop(1, '#d18'); + canvasCtx.fillStyle = grd; */ + + this.active = true; + + this.db = -Infinity; + + this.init(); + + this.meterWidth = this.canvas.element.width / this.channels; + + this.render(); + } + + _inherits(Meter, _Interface); + + _createClass(Meter, { + buildFrame: { + value: function buildFrame() { + this.canvas = new dom.SmartCanvas(this.parent); + this.element = this.canvas.element; + } + }, + sizeInterface: { + value: function sizeInterface() { + this.canvas.resize(this.width, this.height); + } + }, + colorInterface: { + value: function colorInterface() { + this.canvas.element.style.backgroundColor = this.colors.fill; + } + }, + render: { + value: function render() { + if (this.active) { + requestAnimationFrame(this.render.bind(this)); + } + + this.canvas.context.fillStyle = this.colors.fill; + this.canvas.context.fillRect(0, 0, this.canvas.element.width, this.canvas.element.height); + + for (var i = 0; i < this.analysers.length; i++) { + if (this.source) { + this.analysers[i].getFloatTimeDomainData(this.dataArray); + + var rms = 0; + + for (var _i = 0; _i < this.dataArray.length; _i++) { + rms += this.dataArray[_i] * this.dataArray[_i]; + } + + rms = Math.sqrt(rms / this.dataArray.length); + + this.db = 20 * Math.log10(rms); + } else if (this.db > -200 && this.db !== -Infinity) { + this.db -= 1; + } else { + this.db = -Infinity; + } + + //console.log(db) + + if (this.db > -70) { + var linear = math.normalize(this.db, -70, 5); + var exp = linear * linear; + var y = math.scale(exp, 0, 1, this.element.height, 0); + + this.canvas.context.fillStyle = this.colors.accent; + this.canvas.context.fillRect(this.meterWidth * i, y, this.meterWidth, this.canvas.element.height - y); + + //console.log("rendering...") + } + } + } + }, + connect: { + + /** + Equivalent to "patching in" an audio node to visualize. NOTE: You cannot connect audio nodes across two different audio contexts. NexusUI runs its audio analysis on its own audio context, Nexus.context. If the audio node you are visualizing is created on a different audio context, you will need to tell NexusUI to use that context instead: i.e. Nexus.context = YourAudioContextName. For example, in ToneJS projects, the line would be: Nexus.context = Tone.context . We recommend that you write that line of code only once at the beginning of your project. + @param node {AudioNode} The audio node to visualize + @param channels {number} (optional) The number of channels in the source node to watch. If not specified, the interface will look for a .channelCount property on the input node. If it does not exist, the interface will default to 1 channel. + @example Nexus.context = Tone.context // or another audio context you have created + meter.connect( Tone.Master, 2 ); + */ + + value: function connect(node, channels) { + if (this.source) { + this.disconnect(); + } + //this.dummy.disconnect(this.splitter); + + if (channels) { + this.channels = channels; + } else if (node.channelCount) { + this.channels = node.channelCount; + } else { + this.channels = 2; + } + this.meterWidth = this.canvas.element.width / this.channels; + + this.source = node; + this.source.connect(this.splitter); + + // this.render(); + } + }, + disconnect: { + + /** + Stop visualizing the source node and disconnect it. + */ + + value: function disconnect() { + this.source.disconnect(this.splitter); + this.source = false; + // this.dummy.connect(this.splitter); + this.meterWidth = this.canvas.element.width / this.channels; + } + }, + click: { + value: function click() { + this.active = !this.active; + this.render(); + } + }, + customDestroy: { + value: function customDestroy() { + this.active = false; + } + } + }); + + return Meter; + })(Interface); + + module.exports = Meter; + +/***/ }), +/* 37 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(object, property, receiver) { var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc && desc.writable) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + + var _inherits = function (subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; }; + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var dom = __webpack_require__(7); + var Interface = __webpack_require__(6); + + var context = __webpack_require__(1).context; + + /** + * Oscilloscope + * + * @description Visualizes a waveform's stream of values. + * + * @demo + * + * @example + * var oscilloscope = new Nexus.Oscilloscope('#target') + * + * @example + * var oscilloscope = new Nexus.Oscilloscope('#target',{ + * 'size': [300,150] + * }) + * + * @output + *   + * No events + * + */ + + var Oscilloscope = (function (_Interface) { + function Oscilloscope() { + _classCallCheck(this, Oscilloscope); + + var options = ["scale", "value"]; + + var defaults = { + size: [300, 150] + }; + + _get(Object.getPrototypeOf(Oscilloscope.prototype), "constructor", this).call(this, arguments, options, defaults); + + this.context = context(); // jshint ignore:line + + this.analyser = this.context.createAnalyser(); + this.analyser.fftSize = 2048; + this.bufferLength = this.analyser.frequencyBinCount; + this.dataArray = new Uint8Array(this.bufferLength); + this.analyser.getByteTimeDomainData(this.dataArray); + + this.active = true; + + this.source = false; + + this.init(); + + this.render(); + } + + _inherits(Oscilloscope, _Interface); + + _createClass(Oscilloscope, { + buildFrame: { + value: function buildFrame() { + this.canvas = new dom.SmartCanvas(this.parent); + this.element = this.canvas.element; + } + }, + sizeInterface: { + value: function sizeInterface() { + this.canvas.resize(this.width, this.height); + } + }, + colorInterface: { + value: function colorInterface() { + this.canvas.element.style.backgroundColor = this.colors.fill; + } + }, + render: { + value: function render() { + if (this.active) { + requestAnimationFrame(this.render.bind(this)); + } + + this.analyser.getByteTimeDomainData(this.dataArray); + + this.canvas.context.fillStyle = this.colors.fill; + this.canvas.context.fillRect(0, 0, this.canvas.element.width, this.canvas.element.height); + + this.canvas.context.lineWidth = ~ ~(this.height / 100 + 2); + this.canvas.context.strokeStyle = this.colors.accent; + + this.canvas.context.beginPath(); + + if (this.source) { + var sliceWidth = this.canvas.element.width * 1 / this.bufferLength; + var x = 0; + + for (var i = 0; i < this.bufferLength; i++) { + var v = this.dataArray[i] / 128; + var y = v * this.canvas.element.height / 2; + + if (i === 0) { + this.canvas.context.moveTo(x, y); + } else { + this.canvas.context.lineTo(x, y); + } + + x += sliceWidth; + } + } else { + this.canvas.context.moveTo(0, this.canvas.element.height / 2); + this.canvas.context.lineTo(this.canvas.element.width, this.canvas.element.height / 2); + } + + this.canvas.context.stroke(); + } + }, + connect: { + + /** + Equivalent to "patching in" an audio node to visualize. NOTE: You cannot connect audio nodes across two different audio contexts. NexusUI runs its audio analysis on its own audio context, Nexus.context. If the audio node you are visualizing is created on a different audio context, you will need to tell NexusUI to use that context instead: i.e. Nexus.context = YourAudioContextName. For example, in ToneJS projects, the line would be: Nexus.context = Tone.context . We recommend that you write that line of code only once at the beginning of your project. + @param node {AudioNode} The audio node to visualize + @example Nexus.context = Tone.context // or another audio context you have created + oscilloscope.connect( Tone.Master ); + */ + + value: function connect(node) { + if (this.source) { + this.disconnect(); + } + + this.source = node; + this.source.connect(this.analyser); + + this.render(); + } + }, + disconnect: { + + /** + Stop visualizing the source node and disconnect it. + */ + + value: function disconnect() { + if (this.source) { + this.source.disconnect(this.analyser); + this.source = null; + } + } + }, + click: { + value: function click() { + this.active = !this.active; + this.render(); + } + }, + customDestroy: { + value: function customDestroy() { + this.active = false; + } + } + }); + + return Oscilloscope; + })(Interface); + + module.exports = Oscilloscope; + +/***/ }), +/* 38 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + + var _interopRequireWildcard = function (obj) { return obj && obj.__esModule ? obj : { "default": obj }; }; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + /* + Main concept: + synth = new Nexus.Rack('elementID'); + + Transform all elements inside the div + synth.elementID will hold the first slider interface + + 2) In future, potentially writing a rack that is re-usable? + Could also take JSON + + new Nexus.Rack('#target',{ + pre: () => { + create some divs here, or some audio code + }, + interface: { + slider1: Nexus.add.slider({ + top:10, + left:10, + width:50, + height:100, + min: 0, + max: 100, + step: 1 + }), + wave1: Nexus.add.waveform({ + file: './path/to/file.mp3', + width:500, + height:100, + mode: 'range' + }) + }, + init: () => { + // some audio init code goes here... + } + }); + + */ + + var transform = _interopRequireWildcard(__webpack_require__(39)); + + var dom = _interopRequire(__webpack_require__(7)); + + var colors = __webpack_require__(1).colors; + + var Rack = (function () { + function Rack(target, settings) { + _classCallCheck(this, Rack); + + this.meta = {}; + this.meta.target = target; + this.meta.parent = dom.parseElement(target); // should be a generic function for parsing a 'target' argument that checks for string/DOM/jQUERY + this.meta.colors = {}; + + if (settings) { + this.meta.attribute = settings.attribute || "nexus-ui"; + this.meta.title = settings.name || false; + this.meta.open = settings.open || false; + } else { + this.meta.attribute = "nexus-ui"; + this.meta.title = false; + this.meta.open = false; + } + + var defaultColors = colors(); // jshint ignore:line + this.meta.colors.accent = defaultColors.accent; + this.meta.colors.fill = defaultColors.fill; + this.meta.colors.light = defaultColors.light; + this.meta.colors.dark = defaultColors.dark; + this.meta.colors.mediumLight = defaultColors.mediumLight; + this.meta.colors.mediumDark = defaultColors.mediumDark; + this.buildInterface(); + this.colorInterface(); + } + + _createClass(Rack, { + buildInterface: { + value: function buildInterface() { + var _this = this; + + this.meta.parent.style.boxSizing = "border-box"; + this.meta.parent.style.userSelect = "none"; + this.meta.parent.style.mozUserSelect = "none"; + this.meta.parent.style.webkitUserSelect = "none"; + + this.meta.contents = document.createElement("div"); + + while (this.meta.parent.childNodes.length > 0) { + this.meta.contents.appendChild(this.meta.parent.childNodes[0]); + } + + this.meta.contents.style.padding = "0px"; + this.meta.contents.style.boxSizing = "border-box"; + + if (this.meta.title) { + this.meta.titleBar = document.createElement("div"); + this.meta.titleBar.innerHTML = this.meta.title; + this.meta.titleBar.style.fontFamily = "arial"; + this.meta.titleBar.style.position = "relative"; + this.meta.titleBar.style.color = "#888"; + this.meta.titleBar.style.padding = "7px"; + this.meta.titleBar.style.fontSize = "12px"; + + this.meta.button = document.createElement("div"); + this.meta.button.style.position = "absolute"; + this.meta.button.style.top = "5px"; + this.meta.button.style.right = "5px"; + this.meta.button.innerHTML = "-"; + this.meta.button.style.padding = "0px 5px 2px"; + this.meta.button.style.lineHeight = "12px"; + this.meta.button.style.fontSize = "15px"; + + this.meta.button.style.cursor = "pointer"; + + this.meta.button.addEventListener("mouseover", function () { + _this.meta.button.style.backgroundColor = _this.meta.colors.mediumDark; + }); + this.meta.button.addEventListener("mouseleave", function () { + _this.meta.button.style.backgroundColor = _this.meta.colors.mediumLight; + }); + this.meta.button.addEventListener("click", function () { + if (_this.meta.open) { + _this.hide(); + } else { + _this.show(); + } + }); + + this.meta.titleBar.appendChild(this.meta.button); + + this.meta.parent.appendChild(this.meta.titleBar); + } + this.meta.parent.appendChild(this.meta.contents); + + // var width = this.meta.parent.style.width = getComputedStyle(this.meta.parent).getPropertyValue('width'); + // this.meta.parent.style.width = width; + + var ui = transform.section(this.meta.target, this.meta.attribute); + for (var key in ui) { + this[key] = ui[key]; + } + } + }, + colorInterface: { + value: function colorInterface() { + if (this.meta.title) { + this.meta.button.style.backgroundColor = this.meta.colors.mediumLight; + this.meta.button.style.border = "solid 0px " + this.meta.colors.fill; + this.meta.parent.style.border = "solid 1px " + this.meta.colors.mediumLight; + this.meta.parent.style.backgroundColor = this.meta.colors.light; + this.meta.titleBar.style.backgroundColor = this.meta.colors.fill; + } + } + }, + show: { + value: function show() { + this.meta.contents.style.display = "block"; + this.meta.open = true; + } + }, + hide: { + value: function hide() { + this.meta.contents.style.display = "none"; + this.meta.open = false; + } + }, + colorize: { + value: function colorize(type, color) { + for (var key in this) { + if (this[key].colorize) { + this[key].colorize(type, color); + } + } + this.meta.colors[type] = color; + this.colorInterface(); + } + }, + empty: { + value: function empty() { + for (var key in this) { + if (this[key].destroy) { + this[key].destroy(); + } + } + } + } + }); + + return Rack; + })(); + + module.exports = Rack; + +/***/ }), +/* 39 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + "use strict"; + + var dom = _interopRequire(__webpack_require__(7)); + + var Interfaces = _interopRequire(__webpack_require__(2)); + + var createInterfaceID = function (widget, interfaceIDs) { + var type = widget.type; + if (interfaceIDs[type]) { + interfaceIDs[type]++; + } else { + interfaceIDs[type] = 1; + } + return type + interfaceIDs[type]; + }; + + var element = function (element, type, options) { + options = options || {}; + for (var i = 0; i < element.attributes.length; i++) { + var att = element.attributes[i]; + // try { + // options[att.nodeName] = eval(att.nodeValue); + // } catch(e) { + options[att.nodeName] = att.nodeValue; + // } + } + type = type[0].toUpperCase() + type.slice(1); + var widget = new Interfaces[type](element, options); + widget.id = element.id; + return widget; + }; + + var section = function (parent, keyword) { + + keyword = keyword || "nexus-ui"; + + var interfaceIDs = {}; + + var container = dom.parseElement(parent); + + var ui = {}; + + var htmlElements = container.getElementsByTagName("*"); + var elements = []; + for (var i = 0; i < htmlElements.length; i++) { + elements.push(htmlElements[i]); + } + for (var i = 0; i < elements.length; i++) { + var type = elements[i].getAttribute(keyword); + if (type) { + var formattedType = false; + for (var key in Interfaces) { + if (type.toLowerCase() === key.toLowerCase()) { + formattedType = key; + } + } + console.log(formattedType); + var widget = element(elements[i], formattedType); + if (widget.id) { + ui[widget.id] = widget; + } else { + var id = createInterfaceID(widget, interfaceIDs); + ui[id] = widget; + } + } + } + + return ui; + }; + + var add = function (type, parent, options) { + var target = document.createElement("div"); + options = options || {}; + if (parent) { + parent = dom.parseElement(parent); + } else { + parent = document.body; + } + parent.appendChild(target); + options.target = target; + if (options.size) { + target.style.width = options.size[0] + "px"; + target.style.height = options.size[1] + "px"; + } + return element(target, type, options); + }; + + exports.element = element; + exports.section = section; + exports.add = add; + +/***/ }), +/* 40 */ +/***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + var _interopRequire = function (obj) { return obj && obj.__esModule ? obj["default"] : obj; }; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + var math = _interopRequire(__webpack_require__(5)); + + var Tune = (function () { + function Tune() { + _classCallCheck(this, Tune); + + // the scale as ratios + this.scale = []; + + // i/o modes + this.mode = { + output: "frequency", + input: "step" + }; + + // ET major + this.etmajor = [261.62558, 293.664764, 329.627563, 349.228241, 391.995422, 440, 493.883301, 523.25116]; + + // Root frequency. + this.root = math.mtof(60); // * Math.pow(2,(60-69)/12); + + // default is a major scale + this.createScale(0, 2, 4, 5, 7, 9, 11); + } + + _createClass(Tune, { + note: { + + /* Return data in the mode you are in (freq, ratio, or midi) */ + + value: function note(input, octave) { + + var newvalue = undefined; + + if (this.mode.output === "frequency") { + newvalue = this.frequency(input, octave); + } else if (this.mode.output === "ratio") { + newvalue = this.ratio(input, octave); + } else if (this.mode.output === "MIDI") { + newvalue = this.MIDI(input, octave); + } else { + newvalue = this.frequency(input, octave); + } + + return newvalue; + } + }, + frequency: { + + /* Return freq data */ + + value: function frequency(stepIn, octaveIn) { + + if (this.mode.input === "midi" || this.mode.input === "MIDI") { + this.stepIn += 60; + } + + // what octave is our input + var octave = Math.floor(stepIn / this.scale.length); + + if (octaveIn) { + octave += octaveIn; + } + + // which scale degree (0 - scale length) is our input + var scaleDegree = stepIn % this.scale.length; + + while (scaleDegree < 0) { + scaleDegree += this.scale.length; + } + + var ratio = this.scale[scaleDegree]; + + var freq = this.root * ratio; + + freq = freq * Math.pow(2, octave); + + // truncate irrational numbers + freq = Math.floor(freq * 100000000000) / 100000000000; + + return freq; + } + }, + ratio: { + + /* Force return ratio data */ + + value: function ratio(stepIn, octaveIn) { + + if (this.mode.input === "midi" || this.mode.input === "MIDI") { + this.stepIn += 60; + } + + // what octave is our input + var octave = Math.floor(stepIn / this.scale.length); + + if (octaveIn) { + octave += octaveIn; + } + + // which scale degree (0 - scale length) is our input + var scaleDegree = stepIn % this.scale.length; + + // what ratio is our input to our key + var ratio = Math.pow(2, octave) * this.scale[scaleDegree]; + + ratio = Math.floor(ratio * 100000000000) / 100000000000; + + return ratio; + } + }, + MIDI: { + + /* Force return adjusted MIDI data */ + + value: function MIDI(stepIn, octaveIn) { + + var newvalue = this.frequency(stepIn, octaveIn); + + var n = 69 + 12 * Math.log(newvalue / 440) / Math.log(2); + + n = Math.floor(n * 1000000000) / 1000000000; + + return n; + } + }, + createScale: { + value: function createScale() { + var newScale = []; + for (var i = 0; i < arguments.length; i++) { + newScale.push(math.mtof(60 + arguments[i])); + } + this.loadScaleFromFrequencies(newScale); + } + }, + createJIScale: { + value: function createJIScale() { + this.scale = []; + for (var i = 0; i < arguments.length; i++) { + this.scale.push(arguments[i]); + } + } + }, + loadScaleFromFrequencies: { + value: function loadScaleFromFrequencies(freqs) { + this.scale = []; + for (var i = 0; i < freqs.length - 1; i++) { + this.scale.push(freqs[i] / freqs[0]); + } + } + }, + loadScale: { + + /* Load a new scale */ + + value: function loadScale(name) { + + /* load the scale */ + var freqs = this.scales[name].frequencies; + this.loadScaleFromFrequencies(freqs); + } + }, + search: { + + /* Search the names of tunings + Returns an array of names of tunings */ + + value: function search(letters) { + var possible = []; + for (var key in this.scales) { + if (key.toLowerCase().indexOf(letters.toLowerCase()) !== -1) { + possible.push(key); + } + } + return possible; + } + }, + chord: { + + /* Return a collection of notes as an array */ + + value: function chord(midis) { + var output = []; + for (var i = 0; i < midis.length; i++) { + output.push(this.note(midis[i])); + } + return output; + } + } + }); + + return Tune; + })(); + + module.exports = Tune; + +/***/ }), +/* 41 */ +/***/ (function(module, exports) { + + "use strict"; + + var _createClass = (function () { function defineProperties(target, props) { for (var key in props) { var prop = props[key]; prop.configurable = true; if (prop.value) prop.writable = true; } Object.defineProperties(target, props); } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; + + //Disable jshint warning concerning trailing regular params + /*jshint -W138 */ + + var Radio = (function () { + //if non-existent buttons are switched, they are ignored + + function Radio() { + for (var _len = arguments.length, onVals = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + onVals[_key - 1] = arguments[_key]; + } + + var length = arguments[0] === undefined ? 3 : arguments[0]; + + _classCallCheck(this, Radio); + + //each optional 'onVals' argument switches on that value in the Radio if it exists + //In the example below, a 3-button radio is created, index 0 is switched on, index 1 is switched on then then attempted again producing an warning, and the final argument produces a warning because the index value does not exist. + //Example: + //` radio = new Radio(3, 0, 1, 1, 3); + //… [1,1,0] + + if (length < 0) { + length = 1; + } + + this.length = length; + this.onVals = onVals; + this.array = new Array(length).fill(0); + + if (onVals.length > 0) { + this.on.apply(this, onVals); + } + } + + _createClass(Radio, { + select: { + value: function select(value) { + this.array.fill(0); + this.array[value] = 1; + return this.array; + } + }, + flip: { + value: function flip() { + for (var _len = arguments.length, values = Array(_len), _key = 0; _key < _len; _key++) { + values[_key] = arguments[_key]; + } + + //flips the specified values. if no value is specified, flips all buttons + var a = this.array; + if (values.length > 0) { + values.forEach(function (v) { + if (v > a.length - 1) { + console.warn("Warning: AnonRadio[" + v + "] does not exist"); + } else { + a[v] = a[v] ? 0 : 1; + } + }); + } else { + a.forEach(function (v, i, arr) { + arr[i] = v ? 0 : 1; + }); + } + return a; + } + }, + on: { + value: function on() { + for (var _len = arguments.length, values = Array(_len), _key = 0; _key < _len; _key++) { + values[_key] = arguments[_key]; + } + + //switch on the specified values. if no value specified, flips on all buttons + var a = this.array; + if (values.length > 0) { + values.forEach(function (v) { + if (v > a.length - 1) { + console.warn("Warning: AnonRadio[" + v + "] exceeds size of object"); + } else { + if (a[v] === 1) { + console.warn("Warning: AnonRadio[" + v + "] was already on."); + } + a[v] = 1; + } + }); + } else { + a.fill(1); + } + return a; + } + }, + off: { + value: function off() { + for (var _len = arguments.length, values = Array(_len), _key = 0; _key < _len; _key++) { + values[_key] = arguments[_key]; + } + + //switch off the specified values. if no value specified, flips off all buttons + var a = this.array; + if (values.length > 0) { + values.forEach(function (v) { + a[v] = 0; + }); + } else { + a.fill(0); + } + return a; + } + } + }); + + return Radio; + })(); + + module.exports = Radio; + +/***/ }), +/* 42 */ +/***/ (function(module, exports, __webpack_require__) { + + var WAAClock = __webpack_require__(43) + + module.exports = WAAClock + if (typeof window !== 'undefined') window.WAAClock = WAAClock + + +/***/ }), +/* 43 */ +/***/ (function(module, exports, __webpack_require__) { + + /* WEBPACK VAR INJECTION */(function(process) {var isBrowser = (typeof window !== 'undefined') + + var CLOCK_DEFAULTS = { + toleranceLate: 0.10, + toleranceEarly: 0.001 + } + + // ==================== Event ==================== // + var Event = function(clock, deadline, func) { + this.clock = clock + this.func = func + this._cleared = false // Flag used to clear an event inside callback + + this.toleranceLate = clock.toleranceLate + this.toleranceEarly = clock.toleranceEarly + this._latestTime = null + this._earliestTime = null + this.deadline = null + this.repeatTime = null + + this.schedule(deadline) + } + + // Unschedules the event + Event.prototype.clear = function() { + this.clock._removeEvent(this) + this._cleared = true + return this + } + + // Sets the event to repeat every `time` seconds. + Event.prototype.repeat = function(time) { + if (time === 0) + throw new Error('delay cannot be 0') + this.repeatTime = time + if (!this.clock._hasEvent(this)) + this.schedule(this.deadline + this.repeatTime) + return this + } + + // Sets the time tolerance of the event. + // The event will be executed in the interval `[deadline - early, deadline + late]` + // If the clock fails to execute the event in time, the event will be dropped. + Event.prototype.tolerance = function(values) { + if (typeof values.late === 'number') + this.toleranceLate = values.late + if (typeof values.early === 'number') + this.toleranceEarly = values.early + this._refreshEarlyLateDates() + if (this.clock._hasEvent(this)) { + this.clock._removeEvent(this) + this.clock._insertEvent(this) + } + return this + } + + // Returns true if the event is repeated, false otherwise + Event.prototype.isRepeated = function() { return this.repeatTime !== null } + + // Schedules the event to be ran before `deadline`. + // If the time is within the event tolerance, we handle the event immediately. + // If the event was already scheduled at a different time, it is rescheduled. + Event.prototype.schedule = function(deadline) { + this._cleared = false + this.deadline = deadline + this._refreshEarlyLateDates() + + if (this.clock.context.currentTime >= this._earliestTime) { + this._execute() + + } else if (this.clock._hasEvent(this)) { + this.clock._removeEvent(this) + this.clock._insertEvent(this) + + } else this.clock._insertEvent(this) + } + + Event.prototype.timeStretch = function(tRef, ratio) { + if (this.isRepeated()) + this.repeatTime = this.repeatTime * ratio + + var deadline = tRef + ratio * (this.deadline - tRef) + // If the deadline is too close or past, and the event has a repeat, + // we calculate the next repeat possible in the stretched space. + if (this.isRepeated()) { + while (this.clock.context.currentTime >= deadline - this.toleranceEarly) + deadline += this.repeatTime + } + this.schedule(deadline) + } + + // Executes the event + Event.prototype._execute = function() { + if (this.clock._started === false) return + this.clock._removeEvent(this) + + if (this.clock.context.currentTime < this._latestTime) + this.func(this) + else { + if (this.onexpired) this.onexpired(this) + console.warn('event expired') + } + // In the case `schedule` is called inside `func`, we need to avoid + // overrwriting with yet another `schedule`. + if (!this.clock._hasEvent(this) && this.isRepeated() && !this._cleared) + this.schedule(this.deadline + this.repeatTime) + } + + // Updates cached times + Event.prototype._refreshEarlyLateDates = function() { + this._latestTime = this.deadline + this.toleranceLate + this._earliestTime = this.deadline - this.toleranceEarly + } + + // ==================== WAAClock ==================== // + var WAAClock = module.exports = function(context, opts) { + var self = this + opts = opts || {} + this.tickMethod = opts.tickMethod || 'ScriptProcessorNode' + this.toleranceEarly = opts.toleranceEarly || CLOCK_DEFAULTS.toleranceEarly + this.toleranceLate = opts.toleranceLate || CLOCK_DEFAULTS.toleranceLate + this.context = context + this._events = [] + this._started = false + } + + // ---------- Public API ---------- // + // Schedules `func` to run after `delay` seconds. + WAAClock.prototype.setTimeout = function(func, delay) { + return this._createEvent(func, this._absTime(delay)) + } + + // Schedules `func` to run before `deadline`. + WAAClock.prototype.callbackAtTime = function(func, deadline) { + return this._createEvent(func, deadline) + } + + // Stretches `deadline` and `repeat` of all scheduled `events` by `ratio`, keeping + // their relative distance to `tRef`. In fact this is equivalent to changing the tempo. + WAAClock.prototype.timeStretch = function(tRef, events, ratio) { + events.forEach(function(event) { event.timeStretch(tRef, ratio) }) + return events + } + + // Removes all scheduled events and starts the clock + WAAClock.prototype.start = function() { + if (this._started === false) { + var self = this + this._started = true + this._events = [] + + if (this.tickMethod === 'ScriptProcessorNode') { + var bufferSize = 256 + // We have to keep a reference to the node to avoid garbage collection + this._clockNode = this.context.createScriptProcessor(bufferSize, 1, 1) + this._clockNode.connect(this.context.destination) + this._clockNode.onaudioprocess = function () { + process.nextTick(function() { self._tick() }) + } + } else if (this.tickMethod === 'manual') null // _tick is called manually + + else throw new Error('invalid tickMethod ' + this.tickMethod) + } + } + + // Stops the clock + WAAClock.prototype.stop = function() { + if (this._started === true) { + this._started = false + this._clockNode.disconnect() + } + } + + // ---------- Private ---------- // + + // This function is ran periodically, and at each tick it executes + // events for which `currentTime` is included in their tolerance interval. + WAAClock.prototype._tick = function() { + var event = this._events.shift() + + while(event && event._earliestTime <= this.context.currentTime) { + event._execute() + event = this._events.shift() + } + + // Put back the last event + if(event) this._events.unshift(event) + } + + // Creates an event and insert it to the list + WAAClock.prototype._createEvent = function(func, deadline) { + return new Event(this, deadline, func) + } + + // Inserts an event to the list + WAAClock.prototype._insertEvent = function(event) { + this._events.splice(this._indexByTime(event._earliestTime), 0, event) + } + + // Removes an event from the list + WAAClock.prototype._removeEvent = function(event) { + var ind = this._events.indexOf(event) + if (ind !== -1) this._events.splice(ind, 1) + } + + // Returns true if `event` is in queue, false otherwise + WAAClock.prototype._hasEvent = function(event) { + return this._events.indexOf(event) !== -1 + } + + // Returns the index of the first event whose deadline is >= to `deadline` + WAAClock.prototype._indexByTime = function(deadline) { + // performs a binary search + var low = 0 + , high = this._events.length + , mid + while (low < high) { + mid = Math.floor((low + high) / 2) + if (this._events[mid]._earliestTime < deadline) + low = mid + 1 + else high = mid + } + return low + } + + // Converts from relative time to absolute time + WAAClock.prototype._absTime = function(relTime) { + return relTime + this.context.currentTime + } + + // Converts from absolute time to relative time + WAAClock.prototype._relTime = function(absTime) { + return absTime - this.context.currentTime + } + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(44))) + +/***/ }), +/* 44 */ +/***/ (function(module, exports) { + + // shim for using process in browser + var process = module.exports = {}; + + // cached from whatever global is present so that test runners that stub it + // don't break things. But we need to wrap it in a try catch in case it is + // wrapped in strict mode code which doesn't define any globals. It's inside a + // function because try/catches deoptimize in certain engines. + + var cachedSetTimeout; + var cachedClearTimeout; + + function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); + } + function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); + } + (function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } + } ()) + function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + + } + function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + + } + var queue = []; + var draining = false; + var currentQueue; + var queueIndex = -1; + + function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } + } + + function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); + } + + process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } + }; + + // v8 likes predictible objects + function Item(fun, array) { + this.fun = fun; + this.array = array; + } + Item.prototype.run = function () { + this.fun.apply(null, this.array); + }; + process.title = 'browser'; + process.browser = true; + process.env = {}; + process.argv = []; + process.version = ''; // empty string to avoid regexp issues + process.versions = {}; + + function noop() {} + + process.on = noop; + process.addListener = noop; + process.once = noop; + process.off = noop; + process.removeListener = noop; + process.removeAllListeners = noop; + process.emit = noop; + process.prependListener = noop; + process.prependOnceListener = noop; + + process.listeners = function (name) { return [] } + + process.binding = function (name) { + throw new Error('process.binding is not supported'); + }; + + process.cwd = function () { return '/' }; + process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); + }; + process.umask = function() { return 0; }; + + +/***/ }) +/******/ ]) +}); +; +//# sourceMappingURL=NexusUI.map \ No newline at end of file diff --git a/receiver/package-lock.json b/receiver/package-lock.json deleted file mode 100644 index f4fa1b6..0000000 --- a/receiver/package-lock.json +++ /dev/null @@ -1,1494 +0,0 @@ -{ - "name": "scroll-link-server", - "version": "1.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@serialport/binding-abstract": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/@serialport/binding-abstract/-/binding-abstract-8.0.6.tgz", - "integrity": "sha512-1swwUVoRyQ9ubxrkJ8JPppykohUpTAP4jkGr36e9NjbVocSPfqeX6tFZFwl/IdUlwJwxGdbKDqq7FvXniCQUMw==", - "optional": true, - "requires": { - "debug": "^4.1.1" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "optional": true - } - } - }, - "@serialport/binding-mock": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-8.0.6.tgz", - "integrity": "sha512-BIbY5/PsDDo0QWDNCCxDgpowAdks+aZR8BOsEtK2GoASTTcJCy1fBwPIfH870o7rnbH901wY3C+yuTfdOvSO9A==", - "optional": true, - "requires": { - "@serialport/binding-abstract": "^8.0.6", - "debug": "^4.1.1" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "optional": true - } - } - }, - "@serialport/bindings": { - "version": "8.0.8", - "resolved": "https://registry.npmjs.org/@serialport/bindings/-/bindings-8.0.8.tgz", - "integrity": "sha512-xMJHr7CyOPq+wwC/S2RNI+tY+WZW4gXY3tE8QUOIRp0K7lSyLYOzKdyGUtk2uI0ohDMV3OcB+TEhhffT2S2DHQ==", - "optional": true, - "requires": { - "@serialport/binding-abstract": "^8.0.6", - "@serialport/parser-readline": "^8.0.6", - "bindings": "^1.5.0", - "debug": "^4.1.1", - "nan": "^2.14.0", - "prebuild-install": "^5.3.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "optional": true - } - } - }, - "@serialport/parser-byte-length": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-8.0.6.tgz", - "integrity": "sha512-92mrFxFEvq3gRvSM7ANK/jfbmHslz91a5oYJy/nbSn4H/MCRXjxR2YOkQgVXuN+zLt+iyDoW3pcOP4Sc1nWdqQ==", - "optional": true - }, - "@serialport/parser-cctalk": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-8.0.6.tgz", - "integrity": "sha512-pqtCYQPgxnxHygiXUPCfgX7sEx+fdR/ObjpscidynEULUq2fFrC5kBkrxRbTfHRtTaU2ii9DyjFq0JVRCbhI0Q==", - "optional": true - }, - "@serialport/parser-delimiter": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-8.0.6.tgz", - "integrity": "sha512-ogKOcPisPMlVtirkuDu3SFTF0+xT0ijxoH7XjpZiYL41EVi367MwuCnEmXG+dEKKnF0j9EPqOyD2LGSJxaFmhQ==", - "optional": true - }, - "@serialport/parser-readline": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-8.0.6.tgz", - "integrity": "sha512-OYBT2mpczh9QUI3MTw8j0A0tIlPVjpVipvuVnjRkYwxrxPeq04RaLFhaDpuRzua5rTKMt89c1y3btYeoDXMjAA==", - "optional": true, - "requires": { - "@serialport/parser-delimiter": "^8.0.6" - } - }, - "@serialport/parser-ready": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-8.0.6.tgz", - "integrity": "sha512-xcEqv4rc119WR5JzAuu8UeJOlAwET2PTdNb6aIrrLlmTxhvuBbuRFcsnF3BpH9jUL30Kh7a6QiNXIwVG+WR/1Q==", - "optional": true - }, - "@serialport/parser-regex": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-8.0.6.tgz", - "integrity": "sha512-J8KY75Azz5ZyExmyM5YfUxbXOWBkZCytKgCCmZ966ttwZS0bUZOuoCaZj2Zp4VILJAiLuxHoqc0foi67Fri5+g==", - "optional": true - }, - "@serialport/stream": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-8.0.6.tgz", - "integrity": "sha512-ym1PwM0rwLrj90vRBB66I1hwMXbuMw9wGTxqns75U3N/tuNFOH85mxXaYVF2TpI66aM849NoI1jMm50fl9equg==", - "optional": true, - "requires": { - "debug": "^4.1.1" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "optional": true - } - } - }, - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "optional": true - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" - }, - "arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" - }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" - }, - "backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" - }, - "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=" - }, - "base64-js": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", - "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", - "optional": true - }, - "base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" - }, - "better-assert": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", - "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "requires": { - "callsite": "1.0.0" - } - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "bl": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.2.tgz", - "integrity": "sha512-j4OH8f6Qg2bGuWfRiltT2HYGx0e1QcBTrK9KAHNMwMZdQnDZFk0ZSYIpADjYCB3U12nicC5tVJwSIhwOWjb4RQ==", - "optional": true, - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "optional": true - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "optional": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "blob": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", - "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" - }, - "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - } - }, - "buffer": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", - "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", - "optional": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" - }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" - }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "optional": true - }, - "component-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" - }, - "component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "optional": true - }, - "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "requires": { - "safe-buffer": "5.1.2" - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" - }, - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "optional": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "decompress-response": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", - "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", - "optional": true, - "requires": { - "mimic-response": "^2.0.0" - } - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "optional": true - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "optional": true - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" - }, - "detect-libc": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", - "optional": true - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "optional": true, - "requires": { - "once": "^1.4.0" - } - }, - "engine.io": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.4.1.tgz", - "integrity": "sha512-8MfIfF1/IIfxuc2gv5K+XlFZczw/BpTvqBdl0E2fBLkYQp4miv4LuDTVtYt4yMyaIFLEr4vtaSgV4mjvll8Crw==", - "requires": { - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "0.3.1", - "debug": "~4.1.0", - "engine.io-parser": "~2.2.0", - "ws": "^7.1.2" - }, - "dependencies": { - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "engine.io-client": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.4.2.tgz", - "integrity": "sha512-AWjc1Xg06a6UPFOBAzJf48W1UR/qKYmv/ubgSCumo9GXgvL/xGIvo05dXoBL+2NTLMipDI7in8xK61C17L25xg==", - "requires": { - "component-emitter": "~1.3.0", - "component-inherit": "0.0.3", - "debug": "~4.1.0", - "engine.io-parser": "~2.2.0", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~6.1.0", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" - }, - "dependencies": { - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "ws": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", - "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", - "requires": { - "async-limiter": "~1.0.0" - } - } - } - }, - "engine.io-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.0.tgz", - "integrity": "sha512-6I3qD9iUxotsC5HEMuuGsKA0cXerGz+4uGcXQEkfBidgKf0amsjrrtwcbwK/nzpZBxclXlV7gGl9dgWvu4LF6w==", - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.5", - "has-binary2": "~1.0.2" - } - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" - }, - "eventemitter3": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz", - "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==" - }, - "expand-template": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", - "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", - "optional": true - }, - "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "requires": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "optional": true - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - } - }, - "follow-redirects": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.11.0.tgz", - "integrity": "sha512-KZm0V+ll8PfBrKwMzdo5D13b1bur9Iq9Zd/RMmAoQQcl2PxxFml8cxXPaaPYVbV0RjNjq1CU7zIzAOqtUPudmA==", - "requires": { - "debug": "^3.0.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" - }, - "fs": { - "version": "0.0.1-security", - "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", - "integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ=" - }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "optional": true - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "github-from-package": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", - "optional": true - }, - "has-binary2": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", - "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", - "requires": { - "isarray": "2.0.1" - }, - "dependencies": { - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" - } - } - }, - "has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "optional": true - }, - "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "http-proxy": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", - "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", - "requires": { - "eventemitter3": "^4.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "https": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https/-/https-1.0.0.tgz", - "integrity": "sha1-PDfHrhqO65ZpBKKtHpdaGUt+06Q=" - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", - "optional": true - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "optional": true - }, - "ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "optional": true - }, - "long": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, - "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" - }, - "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "requires": { - "mime-db": "1.44.0" - } - }, - "mimic-response": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", - "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", - "optional": true - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "optional": true - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "optional": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", - "optional": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "nan": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", - "optional": true - }, - "napi-build-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", - "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", - "optional": true - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" - }, - "node-abi": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.17.0.tgz", - "integrity": "sha512-dFRAA0ACk/aBo0TIXQMEWMLUTyWYYT8OBYIzLmEUrQTElGRjxDCvyBZIsDL0QA7QCaj9PrawhOmTEdsuLY4uOQ==", - "optional": true, - "requires": { - "semver": "^5.4.1" - } - }, - "noop-logger": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", - "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=", - "optional": true - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "optional": true - }, - "object-component": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", - "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=" - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "requires": { - "ee-first": "1.1.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "osc": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/osc/-/osc-2.4.1.tgz", - "integrity": "sha512-3ZJjyqCoHh3J7K5jvXa+RKHHx6qML9hwqWhVk/YON9344QyjpRYdi+ljP8KMsFNTnVfoP82QNIiOkpL9J7mbzA==", - "requires": { - "long": "4.0.0", - "serialport": "8.0.6", - "slip": "1.0.2", - "wolfy87-eventemitter": "5.2.9", - "ws": "7.2.1" - } - }, - "parseqs": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", - "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseuri": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", - "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" - }, - "prebuild-install": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.3.tgz", - "integrity": "sha512-GV+nsUXuPW2p8Zy7SarF/2W/oiK8bFQgJcncoJ0d7kRpekEA0ftChjfEaF9/Y+QJEc/wFR7RAEa8lYByuUIe2g==", - "optional": true, - "requires": { - "detect-libc": "^1.0.3", - "expand-template": "^2.0.3", - "github-from-package": "0.0.0", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "napi-build-utils": "^1.0.1", - "node-abi": "^2.7.0", - "noop-logger": "^0.1.1", - "npmlog": "^4.0.1", - "pump": "^3.0.0", - "rc": "^1.2.7", - "simple-get": "^3.0.3", - "tar-fs": "^2.0.0", - "tunnel-agent": "^0.6.0", - "which-pm-runs": "^1.0.0" - } - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "optional": true - }, - "proxy-addr": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", - "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", - "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.1" - } - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "optional": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" - }, - "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "optional": true - }, - "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" - } - } - }, - "serialport": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/serialport/-/serialport-8.0.6.tgz", - "integrity": "sha512-TDdP374kZ4+iYKqZbx47eSnJEMoQQfZwztAikWFjZORU1HokOSc3KVuyACy1yX2cVK6u+3C7PmBK3N31CLxMWg==", - "optional": true, - "requires": { - "@serialport/binding-mock": "^8.0.6", - "@serialport/bindings": "^8.0.6", - "@serialport/parser-byte-length": "^8.0.6", - "@serialport/parser-cctalk": "^8.0.6", - "@serialport/parser-delimiter": "^8.0.6", - "@serialport/parser-readline": "^8.0.6", - "@serialport/parser-ready": "^8.0.6", - "@serialport/parser-regex": "^8.0.6", - "@serialport/stream": "^8.0.6", - "debug": "^4.1.1" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "optional": true - } - } - }, - "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "optional": true - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" - }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "optional": true - }, - "simple-concat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", - "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=", - "optional": true - }, - "simple-get": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", - "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", - "optional": true, - "requires": { - "decompress-response": "^4.2.0", - "once": "^1.3.1", - "simple-concat": "^1.0.0" - } - }, - "slip": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/slip/-/slip-1.0.2.tgz", - "integrity": "sha1-ukWpIwNNbPQbGieuvnEoKCyNVR8=" - }, - "socket.io": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.3.0.tgz", - "integrity": "sha512-2A892lrj0GcgR/9Qk81EaY2gYhCBxurV0PfmmESO6p27QPrUK1J3zdns+5QPqvUYK2q657nSj0guoIil9+7eFg==", - "requires": { - "debug": "~4.1.0", - "engine.io": "~3.4.0", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.3.0", - "socket.io-parser": "~3.4.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "socket.io-adapter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", - "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==" - }, - "socket.io-client": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.3.0.tgz", - "integrity": "sha512-cEQQf24gET3rfhxZ2jJ5xzAOo/xhZwK+mOqtGRg5IowZsMgwvHwnf/mCRapAAkadhM26y+iydgwsXGObBB5ZdA==", - "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~4.1.0", - "engine.io-client": "~3.4.0", - "has-binary2": "~1.0.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.3.0", - "to-array": "0.1.4" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "socket.io-parser": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", - "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", - "requires": { - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "isarray": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } - } - } - } - }, - "socket.io-parser": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.1.tgz", - "integrity": "sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A==", - "requires": { - "component-emitter": "1.2.1", - "debug": "~4.1.0", - "isarray": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - }, - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "optional": true - }, - "tar-fs": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.0.tgz", - "integrity": "sha512-9uW5iDvrIMCVpvasdFHW0wJPez0K4JnMZtsuIeDI7HyMGJNxmDZDOCQROr7lXyS+iL/QMpj07qcjGYTSdRFXUg==", - "optional": true, - "requires": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.0.0" - } - }, - "tar-stream": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.2.tgz", - "integrity": "sha512-UaF6FoJ32WqALZGOIAApXx+OdxhekNMChu6axLJR85zMMjXKWFGjbIRe+J6P4UnRGg9rAwWvbTT0oI7hD/Un7Q==", - "optional": true, - "requires": { - "bl": "^4.0.1", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "optional": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } - } - }, - "to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "optional": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "optional": true - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "which-pm-runs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", - "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wolfy87-eventemitter": { - "version": "5.2.9", - "resolved": "https://registry.npmjs.org/wolfy87-eventemitter/-/wolfy87-eventemitter-5.2.9.tgz", - "integrity": "sha512-P+6vtWyuDw+MB01X7UeF8TaHBvbCovf4HPEMF/SV7BdDc1SMTiBy13SRD71lQh4ExFTG1d/WNzDGDCyOKSMblw==" - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "optional": true - }, - "ws": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.1.tgz", - "integrity": "sha512-sucePNSafamSKoOqoNfBd8V0StlkzJKL2ZAhGQinCfNQ+oacw+Pk7lcdAElecBF2VkLNZRiIb5Oi1Q5lVUVt2A==" - }, - "xmlhttprequest-ssl": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", - "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=" - }, - "yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" - } - } -} diff --git a/receiver/package.json b/receiver/package.json deleted file mode 100644 index c550f28..0000000 --- a/receiver/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "scroll-link-server", - "version": "1.0.0", - "description": "", - "main": "app.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "", - "license": "ISC", - "dependencies": { - "express": "^4.16.3", - "fs": "0.0.1-security", - "http-proxy": "^1.17.0", - "https": "^1.0.0", - "osc": "^2.2.3", - "socket.io": "^2.1.1", - "socket.io-client": "^2.1.1" - } -} diff --git a/receiver/receiver.js b/receiver/receiver.js deleted file mode 100644 index 24b8f83..0000000 --- a/receiver/receiver.js +++ /dev/null @@ -1,169 +0,0 @@ -//// socket.io client -var socket = require('socket.io-client')('https://choir.run'); -//var socket = require('socket.io-client')('http://192.168.1.105:8080'); - -//// osc.js configuration (UDP) -var osc = require("osc"); - -//// NOTE: apps cannot share port.. (pd & sc) - -// --> for puredata -// tx: 57000 -// rx: 57001 - -var udp_pd = new osc.UDPPort({ - localAddress: '0.0.0.0', - //NOTE: '127.0.0.1' doesn't work!! for comm. between different machines - localPort: 57001, - remoteAddress: '0.0.0.0', - remotePort: 57000, - metadata: true -}); - -// --> for supercollider -// tx: 57120 -// rx: 57121 - -var udp_sc = new osc.UDPPort({ - localAddress: '0.0.0.0', - //NOTE: '127.0.0.1' doesn't work!! for comm. between different machines - localPort: 57121, - remoteAddress: '0.0.0.0', - remotePort: 57120, - metadata: true -}); - -//firstly establish/prepare osc conn. - supercollider & puredata -Promise.all([ - new Promise(function(resolve, reject) { - udp_pd.on("ready", function() { - resolve(0); - console.log('udp_pd ready..'); - }); - }), - new Promise(function(resolve, reject) { - udp_sc.on("ready", function() { - resolve(0); - console.log('udp_sc ready..'); - }); - }), -]).then(function(results) { - - // - socket.on('connect', function() { - console.log("[osc-receiver] i'm connected."); - }); - - // // - // socket.on('sound', function(msg) { - // - // //DEBUG - // //console.log('sound :'); - // console.log(msg); - // - // //// simply relaying messages to apps. - // - // // to puredata - // udp_pd.send({ - // address: "/sound", - // args: [{ - // type: "f", - // value: msg.id - // }, { - // type: "f", - // value: msg.key - // }] - // }); - // - // // to supercollider - // udp_sc.send({ - // address: "/sound", - // args: [{ - // type: "f", - // value: msg.id - // }, { - // type: "f", - // value: msg.key - // }] - // }); - // - // }); - // - // - socket.on('pan', function(msg) { - - //DEBUG - //console.log('pan :'); - console.log(msg); - - //// simply relaying messages to apps. - - // to puredata - udp_pd.send({ - address: "/pan", - args: [{ - type: "f", - value: msg.width - }, { - type: "f", - value: msg.speed - }] - }); - - // // to supercollider - // udp_sc.send({ - // address: "/pan", - // args: [{ - // type: "f", - // value: msg.width - // }, { - // type: "f", - // value: msg.speed - // }] - // }); - - }); - - // - socket.on('disconnect', function() { - console.log("[osc-receiver] i'm disconnected."); - }); - -}); - -// //message handler -// udp_sc.on("message", function(oscmsg, timetag, info) { -// console.log("[udp] got osc message:", oscmsg); -// -// //EX) -// // //method [1] : just relay as a whole -// // io.emit('osc-msg', oscmsg); //broadcast -// -// //EX) -// // //method [2] : each fields -// // io.emit('osc-address', oscmsg.address); //broadcast -// // io.emit('osc-type', oscmsg.type); //broadcast -// // io.emit('osc-args', oscmsg.args); //broadcast -// // io.emit('osc-value0', oscmsg.args[0].value); //broadcast -// -// //just grab i need.. note! -// io.emit('sing-note', oscmsg.address); //broadcast -// }); - -//osc.js - start service -udp_pd.open(); -udp_pd.on("ready", function() { - console.log( - "[udp] ready (udp_pd) : \n" + - "\tlistening on --> " + udp_pd.options.localAddress + ":" + udp_pd.options.localPort + "\n" + - "\tspeaking to -> " + udp_pd.options.remoteAddress + ":" + udp_pd.options.remotePort + "\n" - ); -}); -udp_sc.open(); -udp_sc.on("ready", function() { - console.log( - "[udp] ready (udp_sc) : \n" + - "\tlistening on --> " + udp_sc.options.localAddress + ":" + udp_sc.options.localPort + "\n" + - "\tspeaking to -> " + udp_sc.options.remoteAddress + ":" + udp_sc.options.remotePort + "\n" - ); -});