Compare commits

...

864 Commits
1.2.0 ... main

Author SHA1 Message Date
Matt McWilliams 5f7fa6287f Add changes from diverged repo 2024-05-15 21:49:45 -04:00
Matt McWilliams 2af8b4b209 Merge remote-tracking branch 'origin/main' 2024-04-28 21:38:32 -04:00
Matt McWilliams 66096fa2ea Add the designs and sketches for the ACME Trebes. 2024-04-19 18:09:44 -06:00
Matt McWilliams 18875a01c6 Correctly reference common.scad and add file for camera mount. 2024-04-15 14:05:38 -06:00
Matt McWilliams 7d2c2b9d09 Use common.scad, change all cylinder entries 2024-04-15 09:42:25 -06:00
Matt McWilliams 67a290a02a Add a bellows adapter for Canon RF cameras and an ACME bellows 2024-04-14 13:34:41 -06:00
Matt McWilliams 63f4278b2b Resolve startup order issues and explanation for all the delays that were meager attempts to solve a race condition. By moving more IPC connectionts to handles, which can be awaited, there are no more attempts to send message to light object that fails because it has not yet been instantiated. 2024-04-06 23:37:30 -04:00
Matt McWilliams 6778f871db Devices, serial and type terms were updated everywhere in code except in the settings object. 2024-04-06 20:29:56 -04:00
Matt McWilliams edc72a5486 Do not overwrite data with an empty object. Overwrite values if there are keys in the object. 2024-04-06 20:15:19 -04:00
Matt McWilliams 2779258111 List of devices looks strange on laptop. Attempt at fix here 2024-04-06 20:10:14 -04:00
Matt McWilliams da735779b4 Add more trycatches add more logs. Not sure where failure is. 2024-04-06 20:00:54 -04:00
Matt McWilliams b7e2e912f4 Figure out why devices.ready() is not reaching end of method on Mono laptop 2024-04-06 19:53:04 -04:00
Matt McWilliams d34172d8e9 Use device.profile() method, seemingly not implemented properly 2024-04-06 19:37:29 -04:00
Matt McWilliams f30ce78f9d Suppress warnings from Intval and execRaw during compilation. Add logging to ready to test on Mono laptop 2024-04-06 19:18:15 -04:00
Matt McWilliams ed767aedb5 Recompile with newer modules. 2024-04-06 19:09:50 -04:00
Matt McWilliams ab35895cb3 update rails 2024-04-06 19:02:39 -04:00
Matt McWilliams 1e2b65644d Update package lock files to work with node16 and electron19 2024-04-06 18:55:46 -04:00
Matt McWilliams 3f58bbc617 Merged changes from work script into JKMM100, works on device in both work script and deployment one 2024-04-06 15:48:02 -04:00
Matt McWilliams c1da7b53a2 Fix for the canonical URL caught by Tom Murphy
Thanks Tom!
2024-01-24 05:19:07 +00:00
Matt McWilliams 4181c22995 Cleanup whitespace/semicolons and add concept for passing an exposure length to the image in millis. 2024-01-19 06:49:03 -05:00
Matt McWilliams d31ac53bd1 Back is ready to print 2024-01-09 13:54:01 -05:00
Matt McWilliams 9b954852aa Add the first draft for the CPC plug back 2024-01-08 15:49:08 -05:00
Matt McWilliams 3758916fb5 Adjust plug insert 2024-01-06 17:56:55 -05:00
Matt McWilliams 25c1395655 make insert thicker for betther overall strength of the plug 2024-01-06 14:30:00 -05:00
Matt McWilliams 440edd7b18 Add 5mm marks to bolex plate 2023-12-27 23:56:10 -05:00
Matt McWilliams a2f045841f Fix bolt countersink in bolex mounting block. Add center line to top 2023-12-27 20:04:43 -05:00
Matt McWilliams c890107e1e Experimental refactor, move commonly-used pattern of cylinder() module with 4 names arguments to cy() with 3 positional arguments, D = diameter, H = height, and FN = $fn. Might improve readability and reduce repetative use of center = true. 2023-12-26 17:37:39 -05:00
Matt McWilliams a5df1650b9 Move nuts to bottom of camera sled and bolts can drop in from the top (easier assembly, bolts can be glued in place or held in more easily). Create camera sled bolex plate and modify the bolex standoff to accomodate it. WIP. 2023-12-23 23:08:59 -05:00
Matt McWilliams 173ce499bc CPC connector work 2023-12-15 19:40:18 -05:00
Matt McWilliams 33412b0588 Merge branch 'main' of ssh://git.sixteenmillimeter.com/16mm/mcopy 2023-12-10 22:51:38 -05:00
Matt McWilliams 3c5e31a961 Work on CPC Connector plug 2023-12-10 22:48:12 -05:00
Matt McWilliams 39676f9a06 fastcsg is non-deterministic 2023-12-02 09:40:54 -05:00
Matt McWilliams 0f893d94c4 Fix the dual projector script and add notes 2023-11-30 22:32:48 -05:00
Matt McWilliams b08f5094d5 Make a solid bearing roller 2023-11-30 22:32:33 -05:00
Matt McWilliams 70e046eeb7 Fix plug diameter 2023-11-30 22:32:18 -05:00
Matt McWilliams 58d0742187 Add takeup signal terminals to the mcopy projector board. 2023-11-28 23:09:09 -05:00
Matt McWilliams f84e8b741a Developed a seemingly working fix with the "correction loop" strategy. Might be putting the motor through hell but it is consistent. 2023-11-25 20:22:44 -05:00
Matt McWilliams fcf24b5539 Add the OFFSET command to the McopySerial library 2023-11-25 20:06:16 -05:00
Matt McWilliams 128a4d2ded Update mcopy_JKMM100_work to have McopySerial library 2023-11-25 20:05:52 -05:00
Matt McWilliams b14d24e650 Prototype for Arduino Mega shield for projector. 2023-11-25 18:08:10 -05:00
Matt McWilliams 7995665c6b Add camera sled 2023-11-24 10:58:20 -05:00
Matt McWilliams a22906d3c2 Add mcopy projector board. 2023-11-22 17:33:23 -05:00
Matt McWilliams 042533dc85 Add plugs for linear bearings in rail ends. 2023-11-19 16:08:37 -05:00
Matt McWilliams 5fbefeecbf Update to the orbital brace 2023-11-13 20:43:13 -05:00
Matt McWilliams a9772ff081 Changes to the brace to allow the projector to fit. Made Y of panel larger. 2023-11-13 20:41:26 -05:00
Matt McWilliams cdf983c7c6 Render STLs for mcopy_projector and mcopy_rails. Make tweaks to orbital mount to fit bolts. 2023-11-12 15:22:23 -05:00
Matt McWilliams 03f886580f Created orbital brace corner and rendered additional stls 2023-11-09 15:54:56 -05:00
Matt McWilliams a06e2869b9 Adjust bolt voids on corner_bracket 2023-11-08 18:15:31 -05:00
Matt McWilliams 6bafb263de Projector rails added and printed 2023-11-04 09:38:20 -04:00
Matt McWilliams 493ff5fbf6 Update raisl and render all files 2023-11-01 00:27:46 -04:00
Matt McWilliams c29e0880ac Work on rails and lens gantry. First prototype is made. Rendering all. 2023-10-30 22:02:30 -04:00
Matt McWilliams 986c7a915b Tweaks to lens sled gantry 2023-10-26 18:11:35 -04:00
Matt McWilliams 68b1b8b819 Double bearings in lens sled 2023-10-24 22:20:47 -04:00
Matt McWilliams 382ba56fa7 Create a prospective "inaccurate" analogReadAverage method. 2023-10-10 22:29:02 -04:00
Matt McWilliams 24d6685047 Use I to trigger projector.home() 2023-10-10 22:12:31 -04:00
Matt McWilliams 565d2ecceb Add second dataset for testing findPeak method 2023-10-10 21:20:51 -04:00
Matt McWilliams c4456e458f Add "home" as command character "I". 2023-10-10 21:16:49 -04:00
Matt McWilliams f707dedc91 New homing behavior. Ready to port back to original. 2023-10-09 22:59:05 -04:00
Matt McWilliams 702fc4680d Had accidentally switched motors, explaining odd homing behavior. New homing behavior whips ass. 2023-10-09 22:58:48 -04:00
Matt McWilliams 99b63150ac Add more smoothing during homing step. Is running consistently but is ending with motor in wrong position each time. Very strange. 2023-10-09 20:52:58 -04:00
Matt McWilliams 6e7c226c57 Make a sample script for analyzing the array during homing step. 2023-10-09 20:52:18 -04:00
Matt McWilliams c8e5f7b742 Caught one bug after separating out code 2023-10-09 19:15:30 -04:00
Matt McWilliams 0cf147d185 Piece off homing code into its own script. 2023-10-09 19:09:50 -04:00
Matt McWilliams cf1514f53e Print lens slded at full width (140mm for now) 2023-10-09 19:07:16 -04:00
Matt McWilliams af3843a8ef Add servo functionality for rack and pinion motion. Need to fix home feature. 2023-10-09 09:59:19 -04:00
Matt McWilliams 91ce2dd450 Add BOM log lines and move rail ends into its own module 2023-10-09 09:58:55 -04:00
Matt McWilliams 71c9efae42 Tweak to the rack and pinion mechanism to allow it to fit. 2023-10-09 09:58:35 -04:00
Matt McWilliams 08ce0d792b Fix for case where this.confirmExec is not a function 2023-10-08 18:15:31 -04:00
Matt McWilliams 754ef17b74 Update servo gear to fit reinforced servo connectors. 2023-10-08 11:41:35 -04:00
Matt McWilliams 5d4fec8c81 Start adding BOM log lines to build. 2023-10-07 15:26:10 -04:00
Matt McWilliams 1e0338a77f Update rack and pinion library to one that produces valid geometry. Make first pass at rack and pinion gear 2023-10-06 13:47:15 -04:00
Matt McWilliams e6b9628746 All projector work from today 2023-10-05 17:28:01 -04:00
Matt McWilliams 6f68081dc5 Restore the home method. Now it compiles. 2023-10-03 13:44:04 -04:00
Matt McWilliams 66b18dd351 Work on LED enclosure 2023-10-03 09:16:34 -04:00
Matt McWilliams b5f5b6461a Work on LED housings 2023-09-28 22:51:55 -04:00
Matt McWilliams 6dd29d9596 Disable home feature for now. Fixed impossibly stupid bug with reverse mode. Used uint16_t rather than int16_t causing an overflow. 2023-09-28 20:46:45 -04:00
Matt McWilliams 29ba125534 Work on LED housing. 2023-09-27 21:31:35 -04:00
Matt McWilliams 144af1414c Merge remote-tracking branch 'origin/main' 2023-09-27 19:10:24 -04:00
Matt McWilliams 06906eca42 Start progress on rack and pinion nub mover 2023-09-27 19:10:13 -04:00
Matt McWilliams 0d47748d6a Saved work in progress 2023-09-27 10:07:50 -04:00
Matt McWilliams b1c8192625 Projector firmware progress: currently the homing function will not compile due to errors with reference and so the sketch method needs to be broken into workable smaller methods 2023-09-25 21:54:31 -04:00
Matt McWilliams d2c7781d79 Servo notch puller progress 2023-09-25 21:53:10 -04:00
Matt McWilliams 37d4f50ef4 Add OpenSCAD/MCAD to the project to prevent double work. Including as a submodule appears to satisfy the requirement of the LGPL and allows mcopy to remain MIT licensed. 2023-09-25 12:25:56 -04:00
Matt McWilliams 082ac85c5c Add deeper notches for 90 degree points 2023-09-25 12:14:59 -04:00
Matt McWilliams cfca56ba48 Migrate stepper block into its own module 2023-09-24 22:58:14 -04:00
Matt McWilliams c7cb4ddbc5 Create the first design of the orbital mount and make slight adjustment to panel (screws were not attaching fully). 2023-09-24 22:46:38 -04:00
Matt McWilliams 7f98d6028b Commit all work in progress 2023-09-21 21:06:31 -04:00
Matt McWilliams 401822a7bb Merge branch 'main' of ssh://git.sixteenmillimeter.com/16mm/mcopy 2023-09-15 19:18:09 -04:00
Matt McWilliams 173ba06590 Work on projector (wrong) 2023-09-14 23:30:29 -04:00
Matt McWilliams 2677118bad fix 2023-09-12 22:36:18 -04:00
Matt McWilliams 8e90456d87 LED gate should be larger 2023-09-12 21:53:38 -04:00
Matt McWilliams 0b880a5e79 Add accurateRead functions and Readme 2023-09-06 15:41:36 -04:00
Matt McWilliams 082dbc0826 Add void for motor, threaded rod (optional) and linear rod. 2023-09-06 00:01:00 -04:00
Matt McWilliams 5eccbbf6df Remove part of the 2020 ends so that it can print without supports 2023-09-05 23:29:48 -04:00
Matt McWilliams 513deb7a0a Render part of the projector. 2023-09-05 23:15:53 -04:00
Matt McWilliams 2b24dc647c Update lens assembly to start using a 2020 frame 2023-09-05 23:15:32 -04:00
Matt McWilliams f8e5968f30 Rename JK lens assembly to reflect it is a new design 2023-09-05 21:31:31 -04:00
Matt McWilliams 18b8c84fff Add additional bearings to lens sled and voids for m5 bolts to hold in side bearings. 2023-09-04 13:10:23 -04:00
Matt McWilliams 1d6ccb7838 Enlarge void for m5 bolt. Add void for m5 nut. 2023-09-04 11:43:01 -04:00
Matt McWilliams a7a63a3be7 Render all projector and rails in current state 2023-09-04 10:49:20 -04:00
Matt McWilliams 153ef9eceb Use fast-csg and parallel with 8 jobs hardcoded 2023-09-04 10:48:54 -04:00
Matt McWilliams eec7765e73 Restore settings logic 2023-08-30 01:18:10 -04:00
Matt McWilliams 03f2b55762 Fucked up the merge 2023-08-29 23:33:42 -04:00
Matt McWilliams 6714374639 restore work from tonight 2023-08-29 23:11:24 -04:00
Matt McWilliams b6b1f5d5ba Parts work 2023-08-29 22:34:55 -04:00
Matt McWilliams d7a10f9737 Enable different modes of stepping by using the settings pins. Previously was causing odd behavior because they were being used for LEDs. 2023-08-29 19:48:49 -04:00
Matt McWilliams d778adc7d0 Add LED holder concept to projector panel design 2023-08-29 17:05:53 -04:00
Matt McWilliams dcbb57f732 Rewrite mcopy_projector_firmware with AccelStepper, replacing the custom Itead firmware (not working) 2023-08-29 15:33:51 -04:00
Matt McWilliams 24452794a9 Merge remote-tracking branch 'origin/main' 2023-08-25 16:44:35 -04:00
Matt McWilliams 24fe1e8773 Work on projector: Still having issues with IteadDualStepperShield (addresses wrong motor, wrong number of steps). 2023-08-25 16:44:28 -04:00
Matt McWilliams b30c637c10 Add structures to insert 2020 Tslot into to make rails fit more snug 2023-08-23 23:35:00 -04:00
Matt McWilliams f16795b11c Render the mcopy rails parts in current form 2023-08-23 22:27:06 -04:00
Matt McWilliams 141d27599f McopyProjector lib for mcopy_projector_firmware rewrite in progress. 2023-08-23 15:21:50 -04:00
Matt McWilliams 86c88c4ac2 Printing a prototype for the lens sled 2023-08-23 00:14:47 -04:00
Matt McWilliams fbab0c043a Give up on SCAD makefile 2023-08-21 22:47:29 -04:00
Matt McWilliams 1a01a4f05e Update sprocketed_roller 2023-08-21 22:47:05 -04:00
Matt McWilliams b0305ae6da Run on all but 1 core. Update JK rails to use actual measurement 2023-08-21 22:46:42 -04:00
Matt McWilliams dd4834de04 Render rails parts (still WIP) 2023-08-21 19:39:08 -04:00
Matt McWilliams 2d90c127a3 Render existing projector panel parts 2023-08-21 19:38:55 -04:00
Matt McWilliams 51d440fccc Render all working CPC connector parts 2023-08-21 19:38:16 -04:00
Matt McWilliams 2e3ed56bb3 Update part names of bellows.scad. Render missing magnetic board. 2023-08-21 19:34:21 -04:00
Matt McWilliams 4be57f3128 Update part names for CPC connectors 2023-08-21 19:31:20 -04:00
Matt McWilliams de6f0d0495 Compile all parts in project, optionally using GNU parallel if available. 2023-08-21 19:04:39 -04:00
Matt McWilliams 98e1e73163 Update to a dynamic bash file that can render all parts in a .scad file 2023-08-21 18:23:41 -04:00
Matt McWilliams 1ae524ff31 Start making a parts list in rails end file 2023-08-21 18:23:16 -04:00
Matt McWilliams 010927c5ca Rename rails_2020 to mcopy_rails 2023-08-20 23:55:27 -04:00
Matt McWilliams 3346bf01af Work on rails having a bearing 2023-08-20 23:54:21 -04:00
Matt McWilliams 788cac7d50 All work towards creating a sled rail for the lens carriage assembly 2023-08-20 18:35:48 -04:00
Matt McWilliams 4c0fa2ba41 rails end prototype 2023-08-20 13:57:00 -04:00
Matt McWilliams 83209f466f Update all submodules 2023-08-20 12:46:36 -04:00
Matt McWilliams 10c452c1b3 Work on rails 2023-08-20 12:37:50 -04:00
Matt McWilliams a8a33a823a Update to 1.8.0 to reflect new breaking changes in app 2023-08-06 15:22:38 -04:00
Matt McWilliams e7e7f86ab3 Manual merge from capper branch: all changes to devices library. 2023-08-06 15:04:33 -04:00
Matt McWilliams 386285d48c Definition file that prevents compiler warnings on some platforms. Still unexplained because tsc is installed local to the project. 2023-08-06 14:58:26 -04:00
Matt McWilliams c4119ab7cc Manual merge from capper branch: all changes to arduino library with some improvements. 2023-08-06 14:56:42 -04:00
Matt McWilliams 176643f148 Manual merge from capper branch: all changes to display library. 2023-08-06 14:36:31 -04:00
Matt McWilliams 8b235bb6b0 mitchell work 2023-08-05 14:42:03 -04:00
Matt McWilliams 8a170f65ca Merge pull request 'canon_ble' (#82) from canon_ble into main
Reviewed-on: #82
2023-08-01 03:38:51 +00:00
Matt McWilliams 2f56dd4b8a Update the timing after delaying for 5000ms (hack) 2023-07-30 23:03:06 -04:00
Matt McWilliams 699c2dbec8 UI cleanup 1: confirm setting the exposure 2023-07-30 22:26:05 -04:00
Matt McWilliams dac720863d Resolves #80 and #81. UI will need a little cleanup. There is some string concatenation happening where it shouldn't. 2023-07-30 22:13:50 -04:00
Matt McWilliams 3b03eb70fb Add placeholder for original stepper motor 2023-07-24 21:20:06 -04:00
Matt McWilliams a173cf0d7c WIP 2023-07-23 20:00:42 -04:00
Matt McWilliams 55b39e7db3 Tweak to USB protector 2023-07-18 23:13:20 -04:00
Matt McWilliams 505a2a71e7 Add magnetic bellows models 2023-07-14 21:40:03 -04:00
Matt McWilliams fb51716e3a All work 2023-07-14 21:13:04 -04:00
Matt McWilliams bdd74fa90a Save css changes 2023-07-14 21:12:48 -04:00
Matt McWilliams 8631250b9e Ignore all apple hidden files 2023-07-13 13:00:10 -04:00
Matt McWilliams c9f35ffe90 Merge branch 'canon_ble' of ssh://git.sixteenmillimeter.com/16mm/mcopy into canon_ble 2023-07-12 22:25:17 -04:00
Matt McWilliams 18d6e2c7cd WIP on state problem 2023-07-12 22:22:46 -04:00
Matt McWilliams f47ea2d382 Work on rails ends 2023-07-10 23:07:32 -04:00
Matt McWilliams 0cc167b3a6 Incredibly close to #80 and #81. Can get state confirmation at startup. Can send exposure string and get confirmation after. Cannot get state outside of initial confirmation. Something is either locked or failing to wait? 2023-07-10 22:33:16 -04:00
Matthew McWilliams 5133295f38 Save JKMM100 work 2023-07-08 19:44:57 -04:00
Matt McWilliams 621948fbac Work on mcopy_rails concepts 2023-07-05 15:17:56 -04:00
Matt McWilliams 4539c6d897 Methods in place for setting exposure 2023-07-05 15:17:45 -04:00
Matt McWilliams a7db072dc6 Accept exposure targets as string arguments to be parsed 2023-07-05 14:46:43 -04:00
Matt McWilliams 58ce079330 Both components are working properly. 2023-07-04 22:46:37 -04:00
Matt McWilliams dd03583a27 Proof of concept works. Nano can proxy requests to ESP32 via soft serial and then receives confirmation after event. Nano has a cleaner serial interface and will not throw junk into mcopy app serial listener. 2023-07-04 18:45:51 -04:00
Matt McWilliams 3feaea74bf Do not need to declare Serial2. 2023-07-04 18:18:51 -04:00
Matt McWilliams 1d6cbe5c53 Update the serial tests 2023-07-04 17:15:26 -04:00
Matt McWilliams 318f931dbf ESP32 HardSerial note 2023-07-03 22:44:43 -04:00
Matt McWilliams 5400518ea6 Merge remote-tracking branch 'origin/canon_ble' into canon_ble 2023-07-03 22:35:37 -04:00
Matt McWilliams f73a1e3931 nano softserial note 2023-07-03 22:35:29 -04:00
Matthew McWilliams 60d7ab4b5e Add missing lines to debug sketch 2023-07-03 20:34:47 -04:00
Matthew McWilliams 95cde2907a Run the debug script 2023-07-03 20:33:32 -04:00
Matthew McWilliams 35b67f1815 Use the correct identifier on projectors 2023-07-03 20:33:18 -04:00
Matt McWilliams f958789b20 Merge remote-tracking branch 'origin/canon_ble' into canon_ble 2023-07-02 13:56:11 -04:00
Matt McWilliams 4beef04a3f Projector debug idea. 2023-07-02 13:56:03 -04:00
Matthew McWilliams 6d379d284b on site work at MONO 2023-07-01 16:34:07 -04:00
Matt McWilliams 2c21110b97 fix reference to cmdChar 2023-06-28 20:01:53 -04:00
Matt McWilliams 777db577d7 Structure of both sketches is complete, need to test on hardware 2023-06-28 15:06:11 -04:00
Matt McWilliams bf320216cf REmove remaining components from ble 2023-06-28 12:43:24 -04:00
Matt McWilliams b48c498574 Remove unneeded components from both ble sketches 2023-06-28 12:41:54 -04:00
Matt McWilliams 0b71da8e7b Canon BLE two-Arduino rewrite WIP 2023-06-27 23:16:16 -04:00
Matt McWilliams c0d6cbccec Can now detect if state is available on a device 2023-06-17 17:57:30 -04:00
Matt McWilliams 95ede98623 State string should start and end with the character 2023-06-17 13:08:00 -04:00
Matt McWilliams 3881dd4891 Update McopySerial to have a sendStr method, which is distinct from print, which should be used for debug logging. 2023-06-17 11:40:56 -04:00
Matt McWilliams 71e4bea384 Preliminary state support in arduino library. Currently confirms the negative state. Might want to push it until after verify, out of enumerate. 2023-06-16 23:04:16 -04:00
Matt McWilliams 83aa3099c4 Update the settings page with time for projector and camera actions 2023-06-16 22:07:53 -04:00
Matt McWilliams 672db32917 Put in place changes needed to receive a string from an arduino 2023-06-12 22:45:25 -04:00
Matt McWilliams 80a9c23f4d Speed down the motors 2023-05-26 07:09:00 -04:00
Matt McWilliams 49ad3c28a8 Only print projector time to state 2023-05-25 10:45:44 -04:00
Matt McWilliams a29c85628c Add bones of the dual stepper motor, JK compatible projector firmware. 2023-05-25 10:43:45 -04:00
Matt McWilliams 3ec93ab3b1 work 2023-05-16 23:05:13 -04:00
Matt McWilliams 10c29d3af1 Add a set screw to the gate_key 2023-05-15 21:48:09 -04:00
Matt McWilliams 41840b90c8 Update gitsub 2023-05-15 12:36:03 -04:00
Matt McWilliams c89e865d3d Bearing needs slight gap to allow the inner bearing wheel to rotate freely 2023-05-14 21:17:20 -04:00
Matt McWilliams c6ec54bd06 Flip projector panel to print 2023-05-14 21:01:46 -04:00
Matt McWilliams af3b1b8cbb Create first draft of projector panel redesign 2023-05-14 21:00:52 -04:00
Matt McWilliams 86273a9f09 Merge remote-tracking branch 'origin/canon_ble' into canon_ble 2023-05-02 23:58:39 -04:00
Matt McWilliams ba0241a811 Update ESP32 case 2023-05-02 23:58:31 -04:00
Matt McWilliams 1bd73876b4 Add sprocketed roller module 2023-04-28 15:35:54 -04:00
Matt McWilliams cc806cbe52 Initialize and connect only after mcopyserial connects. 2023-04-20 22:50:48 -04:00
Matt McWilliams 8f7a40075a Add connected and identified member booleans to determine when fully connected to mcopy. 2023-04-20 22:37:37 -04:00
Matt McWilliams 64faaa9427 Slight change to outer diameter. 2023-04-19 13:32:06 -04:00
Matt McWilliams d44c67ce80 Update the lens board design 2023-04-19 13:31:47 -04:00
Matt McWilliams 144b408092 Print state in the arri-s firmware 2023-04-17 16:44:04 -04:00
Matt McWilliams d2390dca30 Add a bellows board -- to be attached to bellows and then to boards with magnets. Render all STLs 2023-04-16 23:33:11 -04:00
Matt McWilliams 503a8ec92f Add magnets to bellows board design 2023-04-16 22:53:16 -04:00
Matt McWilliams ca22a3ba4b Rewrite arri_s_firmware to use McopySerial 2023-04-16 16:42:00 -04:00
Matt McWilliams ef54e61494 Use McopySerial in mcopy_arri_s_firmware 2023-04-15 22:44:33 -04:00
Matt McWilliams b1745c786b Invert logic for use with solid state relays rather than standard 2023-04-14 19:48:20 -04:00
Matt McWilliams 83efbc18c7 Fix mcopy_cam_canon_ble 2023-04-13 20:39:24 -04:00
Matthew McWilliams f47396e48c Need confirmation after mcopy_cam_relay 2023-04-12 15:25:41 -04:00
Matt McWilliams 03c27a9226 Relay logic was reversed 2023-04-12 15:15:41 -04:00
Matt McWilliams 08655898d4 Merge remote-tracking branch 'origin/canon_ble' into canon_ble 2023-04-12 14:52:40 -04:00
Matt McWilliams 5d347d23e4 Correctly reference backward LED 2023-04-12 14:52:35 -04:00
Matthew McWilliams a25d93ec55 Correctly delay between frames. 2023-04-12 14:52:05 -04:00
Matthew McWilliams bbf0cbd1c6 Add the button to the relay sketch 2023-04-11 23:43:35 -04:00
Matthew McWilliams 4aceeac1c2 Remove libraries required by TickTwo. This sketch will not use blink in this fashion ATM. 2023-04-11 23:26:12 -04:00
Matt McWilliams 1f5bb85304 Correctly reference LEDs 2023-04-11 22:39:44 -04:00
Matthew McWilliams 087fd3f763 Complete the mcopy relay sketch without variable exposure. 2023-04-11 01:13:44 -04:00
Matthew McWilliams daece3b45a Add the new mcopy_cam_relay script. 2023-04-11 00:38:06 -04:00
Matthew McWilliams 9705505285 Refactor ino.sh to loop through array of scripts to copy McopySerial library to. 2023-04-11 00:37:14 -04:00
Matthew McWilliams 9016062f70 Rename mcopy_cam_canon to mcopy_cam_canon_ble to differentiate 2023-04-11 00:28:27 -04:00
Matthew McWilliams a6de66eb66 Blink LED on startup 2023-04-11 00:24:39 -04:00
Matt McWilliams 6ada6b08ed Add LED features to projector firmware. 2023-04-10 23:28:02 -04:00
Matt McWilliams 710e178ba2 Merge branch 'canon_ble' of ssh://git.sixteenmillimeter.com/16mm/mcopy into canon_ble 2023-04-10 21:12:08 -04:00
Matt McWilliams 9e7990851e Case design work 2023-04-10 21:04:01 -04:00
Matt McWilliams ae34558f18 Add project home and mirrors to Readme 2023-04-07 09:44:51 -04:00
Matt McWilliams c1a51f1ce8 Canon EF bellows adapter 2023-04-01 19:24:29 -04:00
Matt McWilliams 13702a3d5b Add a canon_EF_body_cap script 2023-03-30 20:15:43 -04:00
Matt McWilliams 6b66cfe03f Add bolt voids to canon mount 2023-03-29 22:47:49 -04:00
Matt McWilliams cbc876c57c Case ready for production 2023-03-29 21:58:03 -04:00
Matt McWilliams 7813a8c904 First draft of Rebel case 2023-03-28 19:41:35 -04:00
Matt McWilliams 5f941e91b5 Add conecpt for arduino nano case 2023-03-26 20:19:15 -04:00
Matt McWilliams d262ed418d Add base to socket connector. 2023-03-26 20:19:00 -04:00
Matt McWilliams 2e9db4d667 Connector size is working 2023-03-26 18:53:01 -04:00
Matt McWilliams bd9317dd8f Adjust angles. Make $fn configurable (crashing the GUI on my desktop). 2023-03-26 17:53:26 -04:00
Matt McWilliams 461add1cda Start adding LEDs 2023-03-26 16:06:08 -04:00
Matt McWilliams 1528dec668 Rename bellows adapter 2023-03-24 13:51:29 -04:00
Matt McWilliams fff9d5d410 Export mcopy serial to it's own repo 2023-03-24 13:50:38 -04:00
Matt McWilliams 231c354cb1 Update McopySerial usage in both scripts that use it. 2023-03-21 20:38:45 -04:00
Matt McWilliams 4e0149e752 Fixed issue with baud being stored as const overflowed. Silly mistake.
Also storing command chars as public const variables to shorten code and allow for mc.COMMAND rather than McopySerial::COMMAND. Cleans up example code a lot.
2023-03-21 20:35:00 -04:00
Matt McWilliams 5c6b9191e5 Work in progress: Serial does not work from external library 2023-03-20 19:45:32 -04:00
Matt McWilliams 77a0f7d8a0 Use the correct pins for the projector 2023-03-18 17:36:24 -04:00
Matt McWilliams 9faae6fc36 Create the first state sender. 2023-03-18 17:25:58 -04:00
Matt McWilliams 3689eb7528 Rewrite mcopy_light to use McopySerial 2023-03-18 17:13:41 -04:00
Matt McWilliams 210dc85558 Add getString and print methods 2023-03-18 17:04:06 -04:00
Matt McWilliams 174b900cd8 Update commands 2023-03-18 17:00:13 -04:00
Matt McWilliams fbe954280f Socket connector work 2023-03-18 17:00:02 -04:00
Matt McWilliams 142c990a0e Refactored GUI into TypeScript and class-based format 2023-03-18 16:59:26 -04:00
Matt McWilliams 790ea3d551 Add guides for collar flanges 2023-03-15 22:11:48 -04:00
Matt McWilliams c6b8592490 Enlarge case and add bolt 2023-03-15 21:35:35 -04:00
Matt McWilliams f67e011d5e Canon EOS M50 mount design 2023-03-15 21:35:23 -04:00
Matt McWilliams a4bc54482d Work on canon mount 2023-03-15 19:22:18 -04:00
Matt McWilliams be50eb6fcf Work on ESP32 case and CPC socket 2023-03-14 21:45:18 -04:00
Matt McWilliams a7d784583a Case for an ESP32 dev board (Inland, Microcenter) 2023-03-13 17:46:38 -04:00
Matt McWilliams 7af1f739e4 Canon EF M bellows mount 2023-03-13 17:46:21 -04:00
Matt McWilliams 3e247703a8 More CPC connector work 2023-03-13 17:45:50 -04:00
Matt McWilliams c7e338ebff projector electronics improvements, move arduino mount, increase size, adjust resistor mount 2023-03-12 21:28:29 -04:00
Matt McWilliams cc2af435d5 First pass at esp32 case 2023-03-12 17:55:09 -04:00
Matt McWilliams 87695b173d First pass at projector controller design and refactor of sequencer case. 2023-03-12 16:36:16 -04:00
Matt McWilliams 722ff9c05e Remove unneeded comments 2023-03-10 21:19:30 -05:00
Matt McWilliams 51114df576 First draft of the JKMM100 firmware using McopySerial. Boy does this make my life easier.
Need to find a better way than copying it into all of these different projects.
Oh well.
2023-03-09 21:54:54 -05:00
Matt McWilliams 9126bc82c0 Confirm the camera command (this should happen after it expects frame is taken). 2023-03-09 21:51:49 -05:00
Matt McWilliams e09fe7d42f McopySerial now has a confirm() method which marks the end of a command. This is a wrapper around Serial.println() 2023-03-09 21:51:29 -05:00
Matt McWilliams 234e69c7a2 Canon BLE firmware now uses the McopySerial script for it's USB communication. 2023-03-09 21:30:59 -05:00
Matt McWilliams d7017af245 Move connect and identify methods to internal ones. 2023-03-09 21:26:31 -05:00
Matt McWilliams f49c70ead6 Define all command chars as static constants. Provide an identity when initializing and allow for setting with another method. 2023-03-09 21:18:10 -05:00
Matt McWilliams 9a89dbe6a5 Automatically toggle debug state internally 2023-03-09 21:08:36 -05:00
Matt McWilliams 844bb286a5 Build the skeleton of McopySerial. Contains all command chars as flags. Is now re-built with latest command flags automatically when syncing to all projects. Compiles. Will implement more in canon firmware. 2023-03-09 21:01:20 -05:00
Matt McWilliams 4eceecf139 Add ino script 2023-03-08 22:37:40 -05:00
Matt McWilliams 95e2e997e5 Move mcopy serial script. Add work (isn't working). 2023-03-08 21:28:09 -05:00
Matt McWilliams 346c303edb First pass at connector plug 2023-03-08 16:01:02 -05:00
Matt McWilliams 908fe52ad8 Simplify projector_controller.scad 2023-03-05 17:14:01 -05:00
Matt McWilliams 3fd1e47b7b Rename sleeve to collar 2023-03-05 17:13:42 -05:00
Matt McWilliams d41f082839 Update light sketch, add Pixie lib 2023-03-05 17:13:29 -05:00
Matt McWilliams 2047ce4f76 cpc connector work 2023-03-05 00:28:39 -05:00
Matt McWilliams 3ef56cab21 Compile all Arri-S parts 2023-03-04 20:20:16 -05:00
Matt McWilliams 6b77b98aad Add more files to scad.sh 2023-03-04 20:00:01 -05:00
Matt McWilliams 211101cd6b Add common SCAD lib. Add a script that compiles all scad files to stl (make is getting excessive). Canonicalize STL files after they're compiled. 2023-03-04 19:44:20 -05:00
Matt McWilliams e27cae353f Work on McopySerial library. Still having trouble with compiling. 2023-03-04 19:25:50 -05:00
Matt McWilliams b12a08e47a Rename lib to match style of others 2023-03-04 19:04:55 -05:00
Matt McWilliams 9b298ac676 Sync actual files 2023-03-04 19:01:35 -05:00
Matt McWilliams 52acb97e08 Try without symlinks 2023-03-04 18:59:47 -05:00
Matt McWilliams 78450e9e6a Add mcopy_serial library 2023-03-04 18:52:51 -05:00
Matt McWilliams dc746fe6f4 canon work 2023-03-03 10:13:40 -05:00
Matt McWilliams 0e3bc563a7 Update blink functionality. Probably will not work during start? 2023-03-01 13:51:54 -05:00
Matt McWilliams d0ef5d410d Ignore all .svd files 2023-03-01 13:38:48 -05:00
Matt McWilliams d9aa7dc698 Ignore build artifacts 2023-03-01 13:38:27 -05:00
Matt McWilliams 70ab8cb527 Improve timing. Sequence takes into account serialDelay within each command and sequenceDelay has no bearing. Was adding 120ms of error to every step 2023-03-01 13:37:22 -05:00
Matt McWilliams 512f6c86ad Resolves #73. Delay is exported in .ts file so it is non-ambient 2023-03-01 13:35:45 -05:00
Matt McWilliams d23eb290d9 Merge branch 'main' into canon_ble 2023-02-28 15:59:11 -05:00
Matt McWilliams 648bca5b2e Merge pull request 'Merge the estimates branch' (#79) from estimates into main
Reviewed-on: #79
2023-02-28 15:58:26 -05:00
Matt McWilliams 5db5d477e4 Timing is now updated via rolling average on all projector and camera actions. This data is reset when profile is changed. This data is stored in the settings.json and loaded on start so estimates will improve the more it is used. 2023-02-28 15:55:02 -05:00
Matt McWilliams 7741134917 Create the Timing class 2023-02-28 14:30:17 -05:00
Matt McWilliams 3c19cd35cf Resolves #4 (4 years ago!). Adds delay (stops scripts for X seconds), alert (displays an alert that stops script execution) and pause (displays a pre-populated alert). 2023-02-28 12:49:11 -05:00
Matt McWilliams 85832d18f6 Placeholder for notes 2023-02-27 23:16:44 -05:00
Matt McWilliams 5f0da91659 Canon BLE work 2023-02-26 22:19:07 -05:00
Matt McWilliams e1bf69e622 Add work on mcopy_cam_canon. This includes teh CanonBLERemote library, ArduinoNvs (dependency of CanonBLERemote) and TickTwo, potentially to manage a blinking UI component. Not working. Finish the firmware feature in this branch. 2023-02-25 22:24:29 -05:00
Matt McWilliams d9290f7262 Add branch_name.sh to print out only the branch name 2023-02-25 22:22:42 -05:00
Matt McWilliams 81b6846261 Only update patch on main 2023-02-25 22:22:18 -05:00
Matt McWilliams a57519adce Merge pull request 'Merge all work on server with filmout features' (#77) from server into main
Reviewed-on: #77
2023-02-25 21:16:28 -05:00
Matt McWilliams 02639466ee By doing a check for active clients during the sequencer start and stop actions, the local display is no longer used. Resolves first part of #20. 2023-02-25 17:00:11 -05:00
Matt McWilliams 6e2795d380 Remove ACK messages for ping, rely on 2023-02-25 16:33:55 -05:00
Matt McWilliams 8e35596088 Fixed the iOS issue. Also allow for fullscreen on all browsers (with no sleep). Can preview properly but normal mode does not work 2023-02-25 16:32:08 -05:00
Matt McWilliams 0162d012c5 Server can now display images and will completely preempt local display when done 2023-02-25 13:22:20 -05:00
Matt McWilliams 47fb673b78 Combined script and html into single request (problems with iOS safari).
Can get script loaded but still cannot connect to websocket server without SSL.

ALSO: Now can pre-empt opening new display if an active client is connected to server.
Otherwise will open a local link.
2023-02-25 13:11:40 -05:00
Matt McWilliams f296488bc2 Further progress on #20. TODO: Image display logic on the server side. Need to add image to proxy list and give it a properly-extensioned name and cmdAll.
ALSO: Server is not working on iOS.
2023-02-25 12:40:35 -05:00
Matt McWilliams f5392aea9f Resolves #74 2023-02-25 12:33:18 -05:00
Matt McWilliams 24b1301f9f Adding contextIsolation: false to the display module fixes the initial issue in #74, cannot use "require" but the escape button does not work due to "Cannot read properties of undefined (reading 'getCurrentWindow')" 2023-02-25 12:16:47 -05:00
Matt McWilliams 1290a8f324 Major progress on #20. Promised-based websocket command structure is completed. All functionality needs to be placed into individual classes and any new functions get added to the server.
Will create entire thin client using this method.
2023-02-25 11:59:56 -05:00
Matt McWilliams e64277e438 More work on #20. Fix typos in display code. Should re-work script into transpiled ts file. 2023-02-25 02:08:56 -05:00
Matt McWilliams c9bcb74a9f Progress on #20. Can start up a server and serve client.js 2023-02-25 02:08:05 -05:00
Matt McWilliams 42db1f81b8 Server work 2023-02-25 00:24:07 -05:00
Matt McWilliams 7222952eba Update version nubmers 2023-02-19 19:43:12 -05:00
Matt McWilliams 744f10c948 Display version in app 2023-02-19 11:36:06 -05:00
Matt McWilliams b50704a6a8 Fix minor layout issue on sequence page (on mac at least). 2023-02-19 01:28:18 -05:00
Matt McWilliams c152806511 Now it works. 2023-02-19 01:27:19 -05:00
Matt McWilliams 4d9454daf2 Patch script now working 2023-02-19 01:22:44 -05:00
Matt McWilliams e754c65602 Increment patch without npm install 2023-02-19 01:20:51 -05:00
Matt McWilliams b672921c84 Increment patch number on commit 2023-02-19 01:18:03 -05:00
Matt McWilliams 6116ada2fd Getting a new error when compiling delay library. Attempt to stop autogenerating d.ts files.
src/delay/index.ts:11:10 - error TS2384: Overload signatures must all be ambient or non-ambient.
2023-02-19 00:55:17 -05:00
Matt McWilliams d7baa4d17b Merge branch 'capper'
:w
ls
2023-02-19 00:29:40 -05:00
Matt McWilliams ebc5504998 Add commands for takeup 2023-02-19 00:29:07 -05:00
Matt McWilliams c5e66a6f40 Merge pull request 'Merge in 9 months of work on capper branch' (#71) from capper into main
Reviewed-on: #71
2023-02-19 00:28:45 -05:00
Matt McWilliams cff558ef9a Add 15mm to mount void for camera bolt 2023-02-12 14:14:03 -05:00
Matt McWilliams 325837d93e Adjustment to allow space on the right side 2023-02-12 14:10:44 -05:00
Matt McWilliams 135540b261 Remove some material for the rails 2023-02-03 20:08:18 -05:00
Matt McWilliams 49464cd25a Finished the design of the lens assembly base z attachment 2023-02-02 19:48:30 -05:00
Matt McWilliams d0fe54b429 Add m5 nut to the common lib 2023-02-02 19:48:08 -05:00
Matt McWilliams 2dce6f4b08 Merge branch 'capper' of git.sixteenmillimeter.com:16mm/mcopy into capper 2023-01-31 11:52:13 -05:00
Matt McWilliams 99794d04c2 jk assembly and arri-s wip 2023-01-31 11:52:10 -05:00
Matt McWilliams cc06655cd6 Update debug 2023-01-23 00:28:26 -05:00
Matt McWilliams ab6f517d27 Rails work 2023-01-17 12:04:03 -05:00
Matt McWilliams 682167db48 Add new commands for takeup forward and takeup backward 2023-01-15 10:09:55 -05:00
Matt McWilliams f127dc1128 Merge remote-tracking branch 'origin/capper' into capper 2023-01-14 15:26:07 -05:00
Matt McWilliams 0b816ae8e1 Adjust the position of the Z axis, move the linear bearing up and down to prevent binding on motion 2023-01-14 15:25:53 -05:00
Matt McWilliams c600fea4e1 Start rails concept 2023-01-12 19:26:05 -05:00
Matt McWilliams 92067bdbef Add top part to assembly 2023-01-11 19:17:15 -05:00
Matt McWilliams c181e003a3 First draft of base 2023-01-07 18:43:59 -05:00
Matt McWilliams 597137670d Merge base work with knob changes 2023-01-06 10:31:25 -05:00
Matt McWilliams 3036aebbc4 Knob and collar work 2023-01-06 09:18:03 -05:00
Matt McWilliams cbe6477af2 Improvements to bearing and Tnut size 2023-01-05 17:35:25 -05:00
Matthew McWilliams c2546d2bc5 Add m3 nuts and bolts to threaded z movement 2023-01-05 14:40:25 -05:00
Matt McWilliams 46be1bfd3b Assembly work. Adjusted design to simplify placement of 2 linear bearings 2023-01-04 23:11:48 -05:00
Matt McWilliams 1029885047 Update threaded Z, still needs m3 bolts 2023-01-04 18:26:22 -05:00
Matt McWilliams 164bde8cce All arri s mount and jk lens assembly work. need to do some branch cleanup on this project and tackle capper issues for merge of this branch. 2023-01-03 21:16:19 -05:00
Matt McWilliams 41504caac9 Increase the bolt size on the bellows board 2023-01-02 17:11:44 -05:00
Matt McWilliams 9b34b4e026 Adjust the height of the mount (-14.5mm) and make bolt voids larger 2023-01-02 14:33:16 -05:00
Matt McWilliams 95612c1d18 Add m3 nuts 2023-01-02 14:30:54 -05:00
Matt McWilliams 0829ec9081 Use a variable 2023-01-02 13:53:41 -05:00
Matt McWilliams ef0d246901 Increase the inner diameter of the bellows board to allow the threads to pass through cleanly and be held in place by the screw 2023-01-02 13:53:30 -05:00
Matt McWilliams 622a8a7c42 Add first concept bellows board 2023-01-01 11:43:30 -05:00
Matt McWilliams 925659ba4b Create an Arri S mount for the JK rails 2023-01-01 11:43:21 -05:00
Matt McWilliams 20c9287ac2 Work on concept JK lens assembly 2022-12-24 17:36:25 -05:00
Matt McWilliams 8aaa2b8940 Add a concept JK lens assembly 2022-12-24 01:55:11 -05:00
Matt McWilliams 30bd35e21d Add an M4 nut to the common OpenSCAD lib 2022-12-24 01:54:57 -05:00
Matthew McWilliams 0c2e39f0b2 Arri bellows work 2022-12-23 23:01:37 -05:00
Matt McWilliams cbd7001228 Save work on the JK99 shield. 2022-11-13 17:35:18 -05:00
Matt McWilliams dec96ec9be Use variable in stepper declaration 2022-11-11 15:47:58 -05:00
Matt McWilliams 3942cd05be Declare stepsPerRevolution so change is explicit when that happens 2022-11-11 15:47:43 -05:00
Matt McWilliams ee1e9c9feb Stepper firmware is working. Needed extra tape around coupling connector to add friction to connection and now it keeps. 2022-11-04 19:37:11 -04:00
Matt McWilliams fcb77232ec Create the driveCoupling module for the stepper motor design 2022-10-30 12:14:25 -04:00
Matt McWilliams 1fcbec7466 Work on stepper motor design and software. Motor still moves more slowly than it should but will investigate multiple factors leading to this result 2022-10-28 19:46:02 -04:00
Matt McWilliams 98f2c7a24a Pausing work on arri_s_DC firmware because hardware is less than ideal. Too much play in the motor position to trust right now. Steppers better approach. 2022-10-28 11:28:30 -04:00
Matt McWilliams 787e6ed06e Add a concept arri_s camera controller firmware. Using class-based approach as an experiment in Arduino code structure. 2022-10-28 07:50:30 -04:00
Matt McWilliams bb5b7c7897 Add divot to the drive coupling 2022-10-28 07:44:19 -04:00
Matt McWilliams 42b3aa767d Allow for even more space for microswritch 2022-10-28 01:32:58 -04:00
Matt McWilliams b20a6084e6 Allow for more space for the microswitch 2022-10-27 18:10:13 -04:00
Matthew McWilliams d9a8576701 Adjust size of drive coupling for the DC connector 2022-10-21 16:05:56 -04:00
Matthew McWilliams 69273d2a1c Increase scale of motor shaft void by 5% 2022-10-21 15:26:17 -04:00
Matthew McWilliams 755ea757f7 Add set screw for bearing and counter sink bolt caps for other cap m3s 2022-10-21 15:24:21 -04:00
Matt McWilliams 81fc54af8d DC motor design has all components designed, need to print, test and adjust. 2022-10-19 06:38:56 -04:00
Matt McWilliams 4281ca4390 Work on Arri-S DC motor 2022-10-16 19:03:02 -04:00
Matt McWilliams 3419172535 Arri-S work 2022-10-15 00:13:05 -04:00
Matt McWilliams 206c266b08 Added Arri-S motor and cap measurements as taken 10/8/2022 2022-10-09 11:22:12 -04:00
Matthew McWilliams 5026cf869f Arri-S work 2022-10-07 19:47:56 -04:00
Matthew McWilliams d5ecd9e057 Improve capper documentation 2022-09-16 09:45:19 -04:00
Matthew McWilliams 72b5077356 Restructure includes and type definition files so that mscript runs 2022-08-07 22:18:58 -04:00
Matthew McWilliams 6601c030f7 Refactor mscript GUI code into Typescript 2022-08-07 22:10:53 -04:00
Matthew McWilliams 3ec1373f08 Caught a possible ancient bug in the loop logic for calculating state of camera and projector backwards movements. 2022-08-07 17:23:06 -04:00
Matt McWilliams b29478cb58 Increment build patch version 2022-08-04 10:57:36 -04:00
Matt McWilliams fe61e63e76 Add secondary projector and camera commands to the mscript module 2022-08-04 10:52:00 -04:00
Matt McWilliams ee0ab663d7 Complete the alert feature. Have not created pause, but this could be done using the same alert object to prevent code duplication. 2022-08-03 09:02:47 -04:00
Matt McWilliams 1964d6002d Add mono logo as png, but might use svg instead. Render crashed PC. 2022-07-22 21:56:43 -04:00
Matt McWilliams f55b72044c Mcopy firmware with optional capper feature 2022-07-17 11:05:20 -04:00
Matt McWilliams 3f759f5678 Add the ability to detect a single capper device 2022-07-17 09:57:52 -04:00
Matt McWilliams 6582154ec6 Fix debug script and component 2022-07-17 09:56:03 -04:00
Matt McWilliams 9d0545aa4f All capper features in app, can shoot blank frames, can turn on capper independently and can schedule blank frames in the sequencer. Some cleanup may be needed but there are no noticeable regressions in the app. TODO: Finish all arduino scripts. 2022-07-15 18:11:26 -04:00
Matt McWilliams ea055d6e56 Capper case candidate 2022-07-13 23:04:00 -04:00
Matthew McWilliams bc48765b35 Start work on base 2022-07-13 18:16:43 -04:00
Matthew McWilliams 70c2c695f0 All capper work. Need to wrap all actions in the 'b' command and push functionality to a lower level to prevent unneeded complexity. 2022-07-13 15:21:26 -04:00
Matthew McWilliams 8ec5816364 Adjust settings page to support Processing input 2022-07-13 10:15:47 -04:00
Matthew McWilliams c33c6e24f6 Work on motor rod 2022-07-13 09:01:25 -04:00
Matt McWilliams b0ca15bd8d Merge branch 'capper' of git.sixteenmillimeter.com:16mm/mcopy into capper 2022-07-13 08:28:58 -04:00
Matt McWilliams 76799bd66d Capper work 2022-07-13 08:28:18 -04:00
Matthew McWilliams 18dbb72a54 Minor updates to comments 2022-07-06 14:42:53 -04:00
Matthew McWilliams c0ec81c0f9 Add Servo debug script 2022-07-06 14:42:16 -04:00
Matt McWilliams c3661d6ff1 Remove opto endstop logic, ready for hardware testing. 2022-06-28 08:58:31 -04:00
Matt McWilliams c0f056cd8d Re-render all STLs for capper, removing the opto endstop component (for now) 2022-06-28 08:38:11 -04:00
Matt McWilliams 2924efe39f Reduce the size of the void for the screw in the cap. 2022-06-28 08:34:29 -04:00
Matt McWilliams e275539fb0 Remove endstop completely and start rounding surfaces. 2022-06-22 07:45:01 -04:00
Matt McWilliams 4c13c54815 Updates to endstop mount design. Had incorrectly positioned voids for SMD chips on the endstop 2022-06-20 13:00:40 -04:00
Matt McWilliams 62a66f5f6d More mount work and start of endstop logic. Rebuilding the B&H projector unity. 2022-06-17 23:39:19 -04:00
Matt McWilliams 3a435933e3 Work on the opto endstop mount. This needs to be re-oriented before next print. 2022-06-16 00:29:31 -04:00
Matt McWilliams 78f7ac0e68 Mount work 2022-06-13 22:46:23 -04:00
Matt McWilliams 28dc19fc32 Work on endstop functionality 2022-06-13 22:46:13 -04:00
Matt McWilliams 585c47d6c7 Allow capper identifier in list of acceptable responses. 2022-06-13 08:08:42 -04:00
Matt McWilliams 04a0330327 All work on first draft of capper hardware 2022-06-12 22:26:03 -04:00
Matt McWilliams dae4e65aee Merge branch 'capper' of git.sixteenmillimeter.com:16mm/mcopy into capper 2022-06-12 13:37:52 -04:00
Matt McWilliams 129647b863 App work 2022-06-12 13:37:00 -04:00
Matt McWilliams 2f9201716a All capper work. Debug firmware for testing. STL of cap as printed. 2022-06-12 13:14:43 -04:00
Matt McWilliams f9d716552b Merge branch 'capper' of git.sixteenmillimeter.com:16mm/mcopy into capper 2022-06-11 16:06:25 -04:00
Matt McWilliams 818c8453ee Capper OpenSCAD work 2022-06-11 16:03:08 -04:00
Matthew McWilliams f7a3c52260 Silly typo: did not invoke Servo_init() and so servo was not initalizing 2022-06-10 13:19:38 -04:00
Matt McWilliams 9d3bf24627 Hardware ideas for capper mount and flag. Need to model servo and add places for endstops 2022-06-07 07:55:47 -04:00
Matt McWilliams c77201ef4e Add new commands and identifiers for the capper, start moving into capital characters 2022-06-07 07:55:26 -04:00
Matt McWilliams f585aa2a5a Upgrade electron 11 -> 19 (huge jump). Install new remote module to preserve legacy communication protocol. 2022-06-04 11:11:23 -04:00
Matt McWilliams 96e0ce6050 Merge branch 'capper' of git.sixteenmillimeter.com:16mm/mcopy into capper 2022-05-31 17:44:56 -04:00
Matt McWilliams 17d4ff459f Notes about 4pin_connectors 2022-05-31 17:43:03 -04:00
Matt McWilliams c15c376a2f Start work on capper branch 2022-05-30 18:50:18 -04:00
Matt McWilliams 22bed4632b Update the notarization process for installing mcopy 2022-04-30 18:51:33 -04:00
Matt McWilliams 8b5faaa1a4 Update global package.lock 2022-04-30 16:03:33 -04:00
Matt McWilliams 81d94fd727 update package lock 2022-04-30 16:03:03 -04:00
Matt McWilliams bbfe6fc657 Add option to use Processing with a server as a capture method triggered by the camera.
Enter a url into the Settings panel in the Processing URL input box and select the radio button.
2022-04-30 15:58:17 -04:00
Matt McWilliams 467a5c06d6 Update the projector knob design 2022-04-30 15:52:04 -04:00
Matt McWilliams 9dce9fb1f2 Add an alternate script for notarizing builds 2021-05-01 12:20:19 -04:00
Matt McWilliams e1c8ba1320 Build_linux.sh already tags the installer with the correct version number 2021-04-13 18:39:22 -04:00
mmcwilliams 4ef318c55e Rename installer after build process. 2021-04-13 14:45:15 -04:00
mmcwilliams 7f7513809a Established an app signing process for macs using electron-packager. The process takes an enormous amount of time but has so far been running without throwing an exception and the signature is confirmed by codesign. 2021-04-13 14:17:12 -04:00
Matt McWilliams b3bb07454f Add a lamp housing knob 2021-04-05 10:40:50 -04:00
Matt McWilliams faad084b2b Hide "blank" buttons because they do not have a use case in the current app. 2021-04-01 22:21:27 -04:00
Matt McWilliams 3e528c23a5 Give the filmout position input element a fixed width value 2021-04-01 19:45:08 -04:00
Matt McWilliams 6fed941441 Filmout UI was breaking on linux (all of a sudden) 2021-04-01 19:40:29 -04:00
Matt McWilliams 6fee5a803c connector case box 2021-03-19 21:32:53 -04:00
Matt McWilliams 2861bc52fd intval2 connector firmware 2021-03-19 14:09:46 -04:00
Matt McWilliams 8c14a06b96 Removed naked console.log statements that were used to debug a serial issue. If needed they can be re-added to the actual log library. 2021-03-19 12:10:07 -04:00
Matt McWilliams 3e0ac3f0d0 Added return types to Filmout library and added return types to comments where needed. 2021-03-19 12:09:03 -04:00
Matt McWilliams 394fbe2323 Update cfg.json. Not sure why this lags?? 2021-03-18 11:55:18 -04:00
Matt McWilliams 11267796ba Update links to latest release 2021-03-18 11:35:55 -04:00
Matt McWilliams aac5e5d488 Increment patch to 1.6.9 2021-03-18 11:28:46 -04:00
Matt McWilliams 8a6bc0b4f5 Fixed video export, still sequence selection 2021-03-18 11:27:53 -04:00
Matt McWilliams a2af605d37 Filmout needs to receive the whole state, not just the frame. Still broken. 2021-03-18 10:00:49 -04:00
Matt McWilliams 32f70be614 Fixes #50 - Support image sequences in filmout feature 2021-02-24 11:58:19 -05:00
Matt McWilliams 31c701734a Corrected a UI issue with selecting directories of non-supported images. Works on macOS now with videos, images and image sequences. Testing on linux again before resolving. 2021-02-24 11:50:15 -05:00
Matt McWilliams fb7b1e2fb6 Added an edge-case helper for choosing files/directories in linux. This finishes the requirement for issue #50 on linux, but will test changes on macOS before marking the issue resolved. 2021-02-24 10:05:45 -05:00
Matt McWilliams 5061a511ab Corrected an issue with the monitor selection UI where the text is cut off. 2021-02-24 00:38:11 -05:00
Matt McWilliams c0121bcfe7 Have seemingly added the ability to use image sequences with the filmout feature with a few caveats. File selection is working on mac but was not on Linux. Also using this method only jpeg and png sequences can be used. This is not unacceptable, but the UI will have to be made more explicit about this limitation. I would like to support TIFF files but even now with single images they are rendered to PNG using ffmpeg. 2021-02-24 00:22:08 -05:00
Matt McWilliams 66639e951b Allow for the selection of a video file, image or directory containing images to be selected in the filmout UI. 2021-02-23 19:54:03 -05:00
Matt McWilliams 53d147b9bc Add lstat and "directory" property onto the filmout.state object. 2021-02-23 19:53:22 -05:00
Matt McWilliams ad1ac51fc8 Need to enableRemote in the electron browser window that gets created by filmout. 2021-02-23 16:16:17 -05:00
Matt McWilliams 88a6e9f563 Update links to older builds 2021-02-22 13:48:19 -05:00
Matt McWilliams 7dc4d153be Merge remote-tracking branch 'origin/master' 2021-02-22 13:47:05 -05:00
Matt McWilliams dcc91501ee Update readme with links to latest release (1.6.7) 2021-02-22 13:46:58 -05:00
Matt McWilliams 6473f388d8 Update package-lock to latest version 2021-02-22 13:40:44 -05:00
Matt McWilliams a21fff82f1 Update license as work has been ongoing since 2018 2021-02-22 13:26:21 -05:00
Matt McWilliams 2c8eabeffd 3D printable panel for the Oxberry control box. 2021-02-22 13:24:18 -05:00
Matt McWilliams 85bfa57127 Update all modules in app to latest version, including electron. Removed electron updater because of no plans to integrate and to reduce the app size. 2021-02-22 13:23:36 -05:00
Matt McWilliams 112e6b543c Update modules at the project root level. Update to npm lock version 2. 2021-02-22 13:16:49 -05:00
Matt McWilliams 232f39b861 Remove the cli project. It was unmaintained and unnecessarily adds to the project complexity. 2021-02-22 13:15:38 -05:00
Matt McWilliams 338a60f947 Restructure function to match convention. Declare all variables in the beginning of the function rather than declaring them throughout. Small edit while I re-read the UI code and build the file sequence feature. 2021-02-22 13:12:27 -05:00
Matt McWilliams 9ab1436d49 Move dev commands into its own script. 2021-02-22 13:03:41 -05:00
Matt McWilliams 8d3c035e7b Rename "build" to "compile" to match rest of project. 2021-02-22 13:03:08 -05:00
sixteenmillimeter 10b823bca8
Merge pull request #58 from sixteenmillimeter/dependabot/npm_and_yarn/cli/systeminformation-4.27.11
Bump systeminformation from 4.16.0 to 4.27.11 in /cli
2020-11-09 23:49:17 -05:00
sixteenmillimeter 7f9020e698
Merge pull request #57 from sixteenmillimeter/dependabot/npm_and_yarn/app/electron-9.3.1
Bump electron from 9.1.1 to 9.3.1 in /app
2020-11-09 23:49:06 -05:00
sixteenmillimeter 6a563e131b
Merge pull request #56 from sixteenmillimeter/dependabot/npm_and_yarn/electron-10.1.3
Bump electron from 9.1.0 to 10.1.3
2020-11-09 23:48:56 -05:00
dependabot[bot] 1fb5c984ac
Bump systeminformation from 4.16.0 to 4.27.11 in /cli
Bumps [systeminformation](https://github.com/sebhildebrandt/systeminformation) from 4.16.0 to 4.27.11.
- [Release notes](https://github.com/sebhildebrandt/systeminformation/releases)
- [Changelog](https://github.com/sebhildebrandt/systeminformation/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sebhildebrandt/systeminformation/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-27 20:31:56 +00:00
dependabot[bot] b90a68cb39
Bump electron from 9.1.1 to 9.3.1 in /app
Bumps [electron](https://github.com/electron/electron) from 9.1.1 to 9.3.1.
- [Release notes](https://github.com/electron/electron/releases)
- [Changelog](https://github.com/electron/electron/blob/master/docs/breaking-changes.md)
- [Commits](https://github.com/electron/electron/compare/v9.1.1...v9.3.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-06 17:50:14 +00:00
dependabot[bot] 7ebfe16897
Bump electron from 9.1.0 to 10.1.3
Bumps [electron](https://github.com/electron/electron) from 9.1.0 to 10.1.3.
- [Release notes](https://github.com/electron/electron/releases)
- [Changelog](https://github.com/electron/electron/blob/master/docs/breaking-changes.md)
- [Commits](https://github.com/electron/electron/compare/v9.1.0...v10.1.3)

Signed-off-by: dependabot[bot] <support@github.com>
2020-10-06 14:48:42 +00:00
sixteenmillimeter e84f1ce8ff Add additional logging 2020-10-03 21:33:45 -04:00
sixteenmillimeter eb7e62aac7 Fixed projector function 2020-10-03 21:32:16 -04:00
sixteenmillimeter dab5c67c04
Merge pull request #54 from sixteenmillimeter/dependabot/npm_and_yarn/cli/bl-3.0.1
Bump bl from 3.0.0 to 3.0.1 in /cli
2020-09-29 15:51:26 -04:00
sixteenmillimeter 69ca62f884
Merge pull request #53 from sixteenmillimeter/dependabot/npm_and_yarn/app/bl-4.0.3
Bump bl from 4.0.2 to 4.0.3 in /app
2020-09-29 15:51:13 -04:00
dependabot[bot] 53941835cb
Bump bl from 3.0.0 to 3.0.1 in /cli
Bumps [bl](https://github.com/rvagg/bl) from 3.0.0 to 3.0.1.
- [Release notes](https://github.com/rvagg/bl/releases)
- [Commits](https://github.com/rvagg/bl/compare/v3.0.0...v3.0.1)

Signed-off-by: dependabot[bot] <support@github.com>
2020-09-29 19:50:45 +00:00
dependabot[bot] 7d4e53fe24
Bump bl from 4.0.2 to 4.0.3 in /app
Bumps [bl](https://github.com/rvagg/bl) from 4.0.2 to 4.0.3.
- [Release notes](https://github.com/rvagg/bl/releases)
- [Commits](https://github.com/rvagg/bl/compare/v4.0.2...v4.0.3)

Signed-off-by: dependabot[bot] <support@github.com>
2020-09-29 19:50:29 +00:00
sixteenmillimeter 6f19842da0
Merge pull request #49 from sixteenmillimeter/dependabot/npm_and_yarn/lodash-4.17.19
Bump lodash from 4.17.15 to 4.17.19
2020-09-29 15:49:53 -04:00
sixteenmillimeter 3692195887
Merge pull request #48 from sixteenmillimeter/dependabot/npm_and_yarn/cli/lodash-4.17.19
Bump lodash from 4.17.15 to 4.17.19 in /cli
2020-09-29 15:49:36 -04:00
sixteenmillimeter e672c2dc93
Merge pull request #47 from sixteenmillimeter/dependabot/npm_and_yarn/app/lodash-4.17.19
Bump lodash from 4.17.15 to 4.17.19 in /app
2020-09-29 15:49:24 -04:00
sixteenmillimeter 65292524b1 Edit addresses the issue implied by #52. In simple tests with improvised hardware, frame cannot complete in less than 450ms, which is half a full frame. Will add another check to proj_stop() to evaluate the time elapsed and throw an error if too high or low (+/- 20%) 2020-09-29 15:13:22 -04:00
sixteenmillimeter 5e481e77b0 Addressing the issue with the JKMM99 projector functionality where frames stop prematurely. Conceivably, the proj_microswitch() function is the only place that calls proj_stop() so the issue is with the logic there. It makes little sense that this function allows for 15ms frames because of the test that requires a 450ms elapsed time before it is stopped. 2020-09-29 14:00:54 -04:00
sixteenmillimeter 7c9543239e Rest of last commit. Renderer js 2020-09-29 13:57:59 -04:00
sixteenmillimeter 8672b6584a Work towards issue #52. Adds a statement within the arduino.end() method that watches for an 'E' char byte and will alert the UI while pausing a running sequence. Needs to be in place for firmware to be able to throw errors to UI. 2020-09-29 13:48:06 -04:00
sixteenmillimeter c5d7f9c91f Re-write of the JKMM99 which replaces the relay-based camera controller with an intval-based one. This relies on the Arduino Uno in the control box to handle all of the control logic in place of an on-board Arduino Trinket Pro. 2020-09-28 23:49:57 -04:00
sixteenmillimeter 9502d255c7 Fixed typo in Pins() where PROJECTOR_FWD was set to LOW twice instead of PROJECTOR_BWD. 2020-09-28 23:47:36 -04:00
sixteenmillimeter 08c3c23da0 Firmware for new JKMM99. Deployed for testing. 2020-08-18 14:21:27 -04:00
sixteenmillimeter 6eeeae85c8 Updated patch number, now working on 1.6.5 2020-08-18 14:21:07 -04:00
sixteenmillimeter 7c61af7043 Added logging to the arduino module to list all connected devices. 2020-08-18 14:20:43 -04:00
sixteenmillimeter d501623290 Updated projector knob for printing 2020-08-18 14:20:15 -04:00
sixteenmillimeter 0ccb29dfb0 Shape for the friction knob on the JK 106 projection system. 2020-08-10 23:52:54 -04:00
sixteenmillimeter f02782d4da Increment build to 1.6.4. Re-package and deploy for mac 2020-08-09 23:39:52 -04:00
sixteenmillimeter c2e83ab27b Added a diagram for wiring the Slo-Syn motor 2020-08-09 23:26:21 -04:00
sixteenmillimeter 32356b0037 Log doesn't need to print its own path. 2020-08-09 23:25:55 -04:00
sixteenmillimeter dd1bec8394 Firmware for controlling the JK 106 projector with a 103/104-style camera 2020-08-09 20:04:26 -04:00
sixteenmillimeter 4f2252d113 Merge remote-tracking branch 'origin/master' 2020-08-09 20:03:52 -04:00
sixteenmillimeter 0145bebb4b Turn off notifier if errors out 2020-08-09 20:03:48 -04:00
mmcwilliams 5e6fbbb43c Add armv7l architecture to dpkg for Raspian. 2020-07-30 11:28:11 -04:00
mmcwilliams 7e516a59b6 Wrong arch again 2020-07-30 11:04:02 -04:00
mmcwilliams 948b20fead Install dependencies for rpi. Package as armv71 for raspberry pi 2020-07-30 11:01:57 -04:00
mmcwilliams c61c128044 Merge remote-tracking branch 'origin/master' 2020-07-30 10:54:44 -04:00
mmcwilliams 296ef93ecb Installer for rpi 2020-07-30 10:54:35 -04:00
sixteenmillimeter 74621ef1fb Squashing notifier/notify-send errors on raspian. If the system doesnt work with node-notifier just skip 2020-07-27 11:43:55 -04:00
sixteenmillimeter 0811222d27 Normalize paths being used in filmout feature. Purpose of this is to rely on fs module to correctly handle paths for windows because it was previously broken. Will run tests. 2020-07-26 22:26:34 -04:00
sixteenmillimeter 0c364576c9 Squash errors in case of mkdir trying to create an existing directory (need mkdirp, but this works without an extra module) 2020-07-26 22:01:28 -04:00
dependabot[bot] 7ff49f0aa6
Bump lodash from 4.17.15 to 4.17.19 in /app
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-27 01:56:48 +00:00
dependabot[bot] a9b678f748
Bump lodash from 4.17.15 to 4.17.19 in /cli
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-27 01:56:36 +00:00
dependabot[bot] f2fd77a858
Bump lodash from 4.17.15 to 4.17.19
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-27 01:56:33 +00:00
sixteenmillimeter 8c97258866 Update all modules in core project and desktop app. Needed to update syntax of import in sequencer module because uuid is updated to 8.2.0 2020-07-26 21:55:36 -04:00
sixteenmillimeter 5c691a8e12 Fixed serialization error that was breaking raspberry pi 4 installation. It is apparently a real bug that should be breaking the app. 2020-07-26 21:52:53 -04:00
sixteenmillimeter e5e4c7ded7
Update Readme.md
Add reference to new Windows build of 1.6.1
2020-07-07 12:18:25 -04:00
sixteenmillimeter a748f689bd
Merge pull request #45 from sixteenmillimeter/dependabot/npm_and_yarn/app/electron-7.2.4
Bump electron from 7.1.8 to 7.2.4 in /app
2020-07-07 12:16:04 -04:00
sixteenmillimeter 5309f85638
Merge pull request #46 from sixteenmillimeter/dependabot/npm_and_yarn/electron-9.1.0
Bump electron from 4.1.1 to 9.1.0
2020-07-07 12:15:51 -04:00
sixteenmillimeter efc6d0ef03 Moving further down up the path. See previous commit. 2020-07-07 12:07:00 -04:00
sixteenmillimeter a379e4b086 Windows path differences from linux/darwin are ruining my day https://github.com/felixrieseberg/electron-wix-msi/issues/5 2020-07-07 12:05:28 -04:00
sixteenmillimeter 4a1bf417a4 Running build scripts on windows for the first time in a while. 2020-07-07 11:59:34 -04:00
mmcwilliams b702929e1f cases work 2020-07-07 11:54:20 -04:00
sixteenmillimeter d042381293 Projector work 2020-07-07 11:54:01 -04:00
dependabot[bot] 9805127387
Bump electron from 4.1.1 to 9.1.0
Bumps [electron](https://github.com/electron/electron) from 4.1.1 to 9.1.0.
- [Release notes](https://github.com/electron/electron/releases)
- [Changelog](https://github.com/electron/electron/blob/master/docs/breaking-changes.md)
- [Commits](https://github.com/electron/electron/compare/v4.1.1...v9.1.0)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-07 09:36:23 +00:00
dependabot[bot] 270862bd5f
Bump electron from 7.1.8 to 7.2.4 in /app
Bumps [electron](https://github.com/electron/electron) from 7.1.8 to 7.2.4.
- [Release notes](https://github.com/electron/electron/releases)
- [Changelog](https://github.com/electron/electron/blob/master/docs/breaking-changes.md)
- [Commits](https://github.com/electron/electron/compare/v7.1.8...v7.2.4)

Signed-off-by: dependabot[bot] <support@github.com>
2020-07-07 00:20:09 +00:00
sixteenmillimeter 53e012018f JK projector WIP 2020-07-01 18:04:17 -04:00
sixteenmillimeter 420a3fbd50 Sequencer case 2020-07-01 18:04:10 -04:00
sixteenmillimeter 5258fcbf30 Rails work 2020-07-01 18:04:03 -04:00
sixteenmillimeter 4db3ce8b88 jk camera controller case 2020-07-01 18:03:40 -04:00
sixteenmillimeter e3d36a1f27 Merge remote-tracking branch 'origin/master' 2020-07-01 18:03:26 -04:00
sixteenmillimeter 67d0e750c2 Mcopy camera firmware 2020-07-01 18:03:20 -04:00
mmcwilliams f4eb066725 camera conjtroller mod work 2020-05-27 16:47:14 -04:00
mmcwilliams fb63bade2f Fix windows build process (avoid asar) 2020-04-29 10:06:51 -04:00
Matt ed0175b733
Update Readme.md 2020-04-25 16:27:02 -04:00
mmcwilliams 8163f7d454 Merge remote-tracking branch 'origin/master' 2020-04-24 22:38:35 -04:00
mmcwilliams 5ec50713ba Remove extraneous build config from package.json. 2020-04-24 22:38:32 -04:00
Matt 37719b9974
Added latest release to Readme.md 2020-04-24 22:38:11 -04:00
sixteenmillimeter 3fd2b04e75 Update build script on mac to not throw an error 2020-04-24 22:26:00 -04:00
mmcwilliams c15cd512ae The trick on linux is to not build as an asar. Go figure. 2020-04-24 22:17:10 -04:00
mmcwilliams cc41b75130 FFMPEG not working yet 2020-04-24 22:12:56 -04:00
mmcwilliams f929ea2cc2 No, use ffmpeg-static and ffprobe-static but explcitly whitelist the node_modules bin folder where the binaries actually sit 2020-04-24 17:22:58 -04:00
mmcwilliams d4987ed3a3 Replace ffmpeg-static and ffprobe-static with ffmpeg-static-electron and ffprobe-static-electron. These will allow for packaging ffmpeg and ffprobe binaries that can be accessed from within the build. The path replace string hacks weren't cutting it. 2020-04-24 16:01:09 -04:00
mmcwilliams da00c62db3 FFMPEG and FFPROBE need to be stored unpacked in asar for build. 2020-04-24 15:09:51 -04:00
sixteenmillimeter 55c460fbb4 Install new frame module in electron app package 2020-04-24 14:46:05 -04:00
sixteenmillimeter 01cac728f5 Remove ImageMagick dependency. Replace sharp with jimp (prevent linux build issues). Jimp will also perform the same composite step as convert was. Light module is still disabled globally. 2020-04-24 14:33:58 -04:00
sixteenmillimeter 8d5663d3a2 Drop unnecessary console.dir statement 2020-03-09 15:58:36 -04:00
sixteenmillimeter 1c940d6df7 Display export progress and time estimate while all frames are being exported 2020-03-09 15:46:06 -04:00
sixteenmillimeter 891c34ad88 Correct the link to build tagged 1.5.2 2020-02-22 23:34:38 -05:00
sixteenmillimeter aec5b79f90 Update README.md to list new builds and new features. TODO: add a how-to and hardware section. 2020-02-22 23:29:20 -05:00
sixteenmillimeter e25a8bbc7c Use the gui.confirm dialog and not the native confirm function. 2020-02-21 16:58:35 -05:00
sixteenmillimeter d70de98256 Pre-export all frames in video (with confirmation dialog). Greatly improves sequence times and reliablity in conjunction with last commit. Resolves #36 and resolves #39. 2020-02-21 13:34:22 -05:00
sixteenmillimeter aec3e29476 Wait until image is loaded in a temp element and then report back to main process using ipc. This uses the "display_load" ipc channel to call back to the Display class and resolve a promise made in the .show() method. Resolves #38. 2020-02-21 02:28:26 -05:00
sixteenmillimeter 32fe873707 Allow for longer videos by using longer padded numbers for sequences 2020-02-21 01:58:56 -05:00
sixteenmillimeter 549cd3cc04 1.5.2 changes. Build includes code not in repo :( 2020-01-21 11:38:50 -05:00
sixteenmillimeter 8dc955a5e7 FFprobe added as static binary. Needed for filmout feature. 2020-01-20 11:51:15 -05:00
sixteenmillimeter ed75924e24 Filmout release 1.5.0. 2020-01-20 01:37:38 -05:00
sixteenmillimeter 49ba9a090b Turn off light feature for all cfgs. None support it. 2020-01-20 01:20:56 -05:00
sixteenmillimeter 691e741d70 Add check for convert. Never used. 2020-01-20 01:15:20 -05:00
sixteenmillimeter 35b8b0def2 Fixed some counter confusion. Setting the primary and secondary projectors with correct variables. 2020-01-19 01:39:57 -05:00
mmcwilliams 529c275c0f Filmout needed update in use of dialog class. ffmpeg-static needed to reference the required module, not .path 2020-01-19 00:36:58 -05:00
mmcwilliams d604f2aab5 Resolved #28 issues with color selection in the GUI. Performing final tests before 1.5 release. On release will use new repo tagging methods and will build more frequently. 2020-01-14 12:48:15 -05:00
mmcwilliams b0c7e4eed4 Created a new, custom superior log format with timestamps and "splat()" objects. Tired of parsing json from logfiles for analysis. Now can easily grep through logfiles. 2020-01-14 11:51:25 -05:00
mmcwilliams c6d0256929 Compile renderer js with tsconfig.json file. Add maps. 2020-01-10 16:43:12 -05:00
mmcwilliams b74fd270e2 Update modules to resolve typescript compile issue on linux (doesn't work). 2020-01-10 16:23:05 -05:00
mmcwilliams 4d022883ff Update cfg files 2020-01-09 20:19:13 -05:00
sixteenmillimeter b595225870 Increment patch to 1.4.20 2020-01-09 18:43:16 -05:00
sixteenmillimeter fc2593c6ee Resolves #34. Added delay lib to renderer and added a magic delay before ending devices.ready(). Just works. Move on and don't question it. 2020-01-09 18:06:18 -05:00
sixteenmillimeter 4c0aa4220c Log with "simple" format, no more json in the console. 2020-01-09 18:05:10 -05:00
mmcwilliams 42621bbf71 Devices discovery WIP 2020-01-05 12:40:38 -05:00
mmcwilliams 4c8c2b66f3 Serialport library was updated and changed to Promise-based returns from callbacks as was being used in the arduino lib. 2019-12-18 17:17:48 -05:00
mmcwilliams c6ebab4032 Post upgrade, log library needs to be upgraded to support winston 3.x API 2019-12-18 16:05:58 -05:00
mmcwilliams 3fb276f401 Automatically create and remove lib 2019-12-18 14:14:58 -05:00
mmcwilliams bf4ef96a06 Remove staging lib directory from root directory. Was duplicate code. 2019-12-18 14:14:40 -05:00
sixteenmillimeter 6ec81a3429 Timing tweaks for Oxberry firmware. Successfully ran 2000 frames with these settings. 2019-12-18 13:48:33 -05:00
sixteenmillimeter 00ccf4cb8f Merge remote-tracking branch 'origin/master' 2019-12-17 14:54:08 -05:00
sixteenmillimeter 09da9500b5 Oxberry camera firmware. 2019-12-17 14:54:01 -05:00
mmcwilliams de7015022f Bump lodash dependency in cli. 2019-12-16 19:47:01 -05:00
mmcwilliams e59d165689 Update modules in cli. 2019-12-16 19:45:09 -05:00
mmcwilliams 1075c7ff4a Abandon native experiment... (for now). 2019-12-16 19:44:46 -05:00
mmcwilliams 4461670e14 Fixes security concerns. Resolves #24 and #27 2019-12-16 19:25:51 -05:00
mmcwilliams 8e4c32073a Sequencer now blocks system sleep while running a sequence. Made me upset last night when it happened during a filmout and I shot 1000 frames of black. Resolves #26 2019-10-04 14:36:26 -04:00
sixteenmillimeter ac1da17b8d Handle different aspect ratio images and screens. Add additional counts on fields and thicken lines. Resolves #19 2019-08-25 15:54:50 -04:00
sixteenmillimeter 9b2ed018bf If filmout picture source is set, set the field guide to match the aspect ratio of the image. Right now that only works if ratio is lower than the screen. Need to add case in display.html that corrects for when screen ratio is lower than image ratio. 2019-08-25 15:26:43 -04:00
sixteenmillimeter 51acbdfd30 Add comments to filmout lib. 2019-08-25 14:59:39 -04:00
mmcwilliams 5ce0aed2ff Use module "ffmpeg-static" to use a binary of ffmpeg stored in node_modules, rather than rely on the system version. 2019-08-23 15:39:38 -04:00
sixteenmillimeter f0c28b8624 Properly count number of frames in animated gifs using `identify` from imagemagick because ffprobe was failing. 2019-08-15 15:25:33 -04:00
mmcwilliams 5f701ccecb Increment patch number. 2019-08-04 19:53:51 -04:00
mmcwilliams cfa22d3a1d Replace native js confirm() with a new gui.confirm() method that uses electrons "dialog" module. Resolves issue #25 2019-08-04 19:52:52 -04:00
mmcwilliams 1b83fe6937 Downgrade winston from 3 to 2 because it prints better in the console. Change all require statements to imports, requiring only what's used. 2019-08-04 19:38:45 -04:00
mmcwilliams 2ff98a2148 Refactor ffprobe into a class. Add jsdoc comments to all methods. 2019-08-04 18:04:06 -04:00
mmcwilliams 30c36baa9c Add comments and switch in logger module for console.log 2019-08-04 17:54:38 -04:00
mmcwilliams bd79025305 Refactored ffmpeg module into a class. Add a logger, not implemented. Not tested. 2019-08-04 17:42:27 -04:00
mmcwilliams 7c4e9d5823 Add jsdoc comments to ffmpeg lib. Also added types for tsc where they were implicit any type. Also added some semi-colons. Whoops. 2019-08-04 17:31:27 -04:00
mmcwilliams 5695bfd645 App was throwing error during filmout. Re-wrote the resizing logic so that if it can't find dimensions in the info, don't resize the image. This may lead to squashing, as I've seen in frameloom, but I suspect this problem is with the UI and the superfluous "USE FILE" button. 2019-08-04 17:20:45 -04:00
mmcwilliams c5f3c72f73 All workshop work. Freeze dev on mac and test on linux 2019-07-29 12:45:13 -04:00
mmcwilliams 7e05b5f680 Fix dual projector bug and increment patch. 2019-07-27 08:47:35 -04:00
mmcwilliams 741d4619ee Replace all references to dig with filmout 2019-07-27 08:39:39 -04:00
mmcwilliams 7c50b66499 Updated gui mscript lib to use .meta instead of .light when preparing an mscript sequence. 2019-07-26 19:59:16 -04:00
mmcwilliams 96d0897f65 Made a breaking change to the mscript module: light array is now the "meta" array to allow for types of commands other than camera movements to have associated metadata. The two driving motivations for this change are the proposed alert feature which will have a string message as its metadata and the proposed pause feature, which will have seconds as its metadata.
Updated tests as well. Still need to change behavior in the mscript.js gui lib.
2019-07-26 19:54:22 -04:00
mmcwilliams c01f3ceff8 Add jsdoc comments AND semi-colons to sequencer module. 2019-07-26 19:03:42 -04:00
mmcwilliams 4023704d31 Added missing jsdoc comment to method "fade_rgb". 2019-07-26 18:57:17 -04:00
mmcwilliams 798e9ce1a3 Fixed comments in system module to reflect the fact that dependency check happens by executing 'which {cmd}' and storing the response as the absolute path to the binary. If which returns a blank string, dependency is marked not present. 2019-07-26 18:31:22 -04:00
mmcwilliams 6612ffa6d1 Add jsdoc comments to cmd module 2019-07-26 18:30:10 -04:00
mmcwilliams 07100a588c Add jsdoc comments to remaining methods. 2019-07-26 18:12:06 -04:00
mmcwilliams 0b2d386ca2 Compile mscript with Typescript 2019-07-26 17:28:27 -04:00
mmcwilliams 4b5dd4868b Refactored mscript module into Typescript. Have not finished documentation. Typescript ompiles without errors. All mscript tests in /app pass. 2019-07-26 17:27:58 -04:00
mmcwilliams f0804fe23b Incorrectly bound counter to wrong device. 2019-07-24 22:00:53 -04:00
mmcwilliams 97591b1c1d Support gifs and stills in filmout 2019-07-24 22:00:23 -04:00
mmcwilliams b5da7ba233 Filmout supports still images. Uses FFMPEG to convert to png, still. Should use sharp and re-sample the image to the maximum allowed for the screen in the smallest dimension. 2019-07-07 00:02:01 -04:00
mmcwilliams 0f52812767 Add path to main GUI process 2019-07-07 00:00:45 -04:00
mmcwilliams 0d6c3e44b0 Rename "video" to "file" in UI 2019-07-07 00:00:33 -04:00
mmcwilliams 60147e3b0f Increment patch 2019-07-07 00:00:14 -04:00
mmcwilliams f8c64b45a7 Install sharp and animated-gif-detector 2019-07-06 19:53:03 -04:00
mmcwilliams 504912009b Increment patch number of version across the project. 2019-06-26 20:10:18 -04:00
mmcwilliams 084916c317 Preview a frame using the webview. Select monitor to display images on. Wooo! 2019-06-26 20:08:49 -04:00
mmcwilliams 073e778a3b Visual tweaks for linux 2019-06-26 18:03:54 -04:00
mmcwilliams b5465384ce Increment package version 2019-06-26 16:10:04 -04:00
mmcwilliams 45f96e6537 Give macOS an extra 300ms to open and fullscreen a webview 2019-06-26 16:09:14 -04:00
mmcwilliams f8fc9fded6 Fixed the siemen's star focusing screen with magic numbers. Better than it was before! 2019-06-26 16:07:00 -04:00
mmcwilliams f239f862e8 Fixed frame counting optimization, resolving issue #17. Also added a Siemens Star focusing screen, a middle gray metering screen and a field guide screen for use with the filmout feature. TODO: actually change monitors when selected. 2019-06-25 12:13:15 -04:00
mmcwilliams 872b46d4a5 Filmout display monitor size with stats 2019-06-24 21:11:14 -04:00
mmcwilliams ddfc46a48f Delete devices.js backup 2019-06-24 15:04:24 -04:00
mmcwilliams ad67e2f010 Add devices module after refactor 2019-06-24 14:31:26 -04:00
mmcwilliams 9331a766df Compiled 2019-06-24 13:25:34 -04:00
mmcwilliams 6b10e9c28d System module phones home 2019-06-24 12:42:27 -04:00
mmcwilliams d15fe37de5 Add a dependency check for the convert command 2019-06-24 11:37:07 -04:00
mmcwilliams 5014a2db38 Remove systeminformation module from system lib 2019-06-24 11:26:28 -04:00
mmcwilliams f3e885df35 Rename DOM elements filmout, instead of "video" 2019-06-24 11:20:08 -04:00
mmcwilliams 98a0eff503 Uninstall systeminformation, which was the original module being used to determine monitor stats. Now use the internal electron.screen module, which I was using originally? Yikes. 2019-06-22 12:07:07 -04:00
mmcwilliams 6cda9aed1d Beginnings of the film out display selection UI 2019-06-22 11:52:36 -04:00
mmcwilliams 9a464a2fcf Unsafe-eval was throwing an error on compile 2019-06-22 11:52:14 -04:00
mmcwilliams a4f8ffc3c6 Merge remote-tracking branch 'origin/master' 2019-06-22 10:49:36 -04:00
mmcwilliams 23a7896db9 Update version on lock file. 2019-06-20 14:39:05 -04:00
mmcwilliams e25054117f Only require join method from path. Don't need the whole dang thing. 2019-06-18 16:57:35 -04:00
mmcwilliams 2e4ef09a60 Apply new patch version everywhere. 2019-06-18 16:54:22 -04:00
mmcwilliams 717cf77e55 Rename all uses of the previously-named "digital" module to "filmout" in sequence module. Woo! Let's call that a patch. 2019-06-18 16:54:08 -04:00
mmcwilliams ede6fcdfb8 Rename all uses of the previously-named "digital" module to "filmout" in proj module. 2019-06-18 16:52:26 -04:00
mmcwilliams 6fcb85bca2 Remove unused "digital" attribute from camera state. 2019-06-18 16:50:28 -04:00
mmcwilliams 0cff7c5794 Rename all uses of the previously-named "digital" module to "filmout" in cam module. 2019-06-18 16:49:49 -04:00
mmcwilliams 9b17d5cd47 Meant to commit this as last commit. Oh well. 2019-06-18 16:48:54 -04:00
mmcwilliams 8ebbd0ac47 Remove unused modules and only require used exports within path and events. 2019-06-18 16:47:26 -04:00
mmcwilliams 49f9f7f160 Display will now show a meter screen (middle grey) when instructed. Not wired to anything, got distracted by the re-naming shenanigans. 2019-06-18 15:47:17 -04:00
mmcwilliams 22187777e7 Remove node-side digital lib and replace with filmout lib. Still remaining: rename internal uses of "dig" or "digital" to "filmout", including markup on the frontend. 2019-06-18 15:42:30 -04:00
mmcwilliams 00b26719f6 Finish renaming UI files digital->filmout 2019-06-18 15:40:09 -04:00
mmcwilliams d6da1824cd Rename UI files 2019-06-18 15:25:28 -04:00
mmcwilliams 23d663c3e7 Create digital.ts and devices.ts. Begin rewriting devices as-is and then refactor the existing digital features into digital.ts. Gonna rename, screw it. 2019-06-18 15:19:57 -04:00
mmcwilliams 1e2b542e4c Begin refactoring devices.js and create a new digital.js lib for the film-out features. Maybe think of renaming now, before it hurts. 2019-06-18 15:18:08 -04:00
mmcwilliams 5cd6b22ea4 Only use webview in full screen mode for now on all platforms. EOG is trickier and flickers the entire screen into view between frames, which is unsettling. Will look for a lower-level solution than webviews, but works for now. Also, uses real fullscreen on macOS instead of just maximizing the window. 2019-06-18 13:47:55 -04:00
mmcwilliams 32f02d42ce During the film out mode, the webview now correctly handles "closed" events when the user manually closes the window. The window also now closes at the end of a sequence (caught a typo) and correctly removed the webview from the WebView object when it does not exist. Resolves #15 2019-06-18 13:35:50 -04:00
mmcwilliams 7740dc39ec Include in last commit 2019-06-15 11:06:57 -04:00
mmcwilliams 07940bc2c6 All film out work from Friday. Re-structure the display module into 3 classes instead of a mess of functions. 2019-06-15 11:06:39 -04:00
mmcwilliams 7c43f2de2c Add the film out screen and begin styling. 2019-06-15 11:05:29 -04:00
mmcwilliams 39e6ab5247 Update all modules, and update gulpfile to gulp4 syntax. 2019-06-14 13:11:28 -04:00
mmcwilliams 76c7b49142 Import delay and add comments to digital. Starting work on film-out improvements. 2019-06-14 12:00:22 -04:00
mmcwilliams 5b418aeccd Camera module imports intval class properly. 2019-06-14 11:59:47 -04:00
mmcwilliams b5fbe0153b Refactor intval module into Typescript. 2019-06-14 11:58:35 -04:00
mmcwilliams da7d14e898 add delay to module 2019-06-14 11:31:27 -04:00
mmcwilliams 3aeb971b4d Merge remote-tracking branch 'origin/master' 2019-06-14 11:31:13 -04:00
mmcwilliams dab5c34bad stash progress 2019-06-14 11:29:52 -04:00
mmcwilliams 596832119b Uninstall node-media-server. What was I thinking? Oh yeah, I wasn't. Instead of using the system to pipe an RTMP stream to nms, I'm just going to use electron's built in navigator.getUserMedia or somesuch. Silly of me. 2019-06-11 16:30:44 -04:00
mmcwilliams 6442d99817 Update delay, exec and exit usage and require statments. 2019-06-08 21:43:14 -04:00
mmcwilliams a7c7715207 Add fs-extra types to dev 2019-06-08 21:40:34 -04:00
mmcwilliams e3d213e4f1 Ported ffmpeg, ffprobe, exit and exec modules to typescript 2019-06-08 20:51:00 -04:00
mmcwilliams c169b7fbae Update mscript tests. Increase coverage. 2019-05-28 22:40:50 -04:00
mmcwilliams d8e5e4521a Increment patch number. Commit 418670ce33 resolves #14; 2019-05-28 17:53:23 -04:00
mmcwilliams 418670ce33 Time a sequence and pass back value of milliseconds back when sequence stops. 2019-05-28 17:48:42 -04:00
mmcwilliams 8ddc6e5a20 Promisify gui.notify. Will not run it synchronously, but is nice to have. 2019-05-28 17:47:39 -04:00
mmcwilliams f015a6f2c5 Display the time of the completed sequence when passed from main process. 2019-05-28 17:46:53 -04:00
mmcwilliams 7907ba9533 Update typescript config to work on macOS. Basically just add a bunch of dirs to the exclude array. 2019-05-28 17:46:24 -04:00
mmcwilliams 1fd3b83ca1 Mscript does not need a callback. Remove from compile() method 2019-05-28 17:42:42 -04:00
mmcwilliams 35a540f5df Update processing script cfg.json 2019-05-28 17:42:00 -04:00
mmcwilliams da6fef6080 Notify on mock device connectio 2019-05-28 17:41:39 -04:00
mmcwilliams 9a0ebcca06 cfg has latest version number 2019-05-28 17:41:23 -04:00
mmcwilliams 93144322db Re-writing mscript tests. 2019-05-28 17:40:59 -04:00
Matt 8e832d0aa3
Added link to latest release. 1.4.9 2019-05-28 14:18:15 -04:00
mmcwilliams 02ca59ea7e Removed the "undefined" lines from occurring. Code is a mess, but won't break anything else... for now. 2019-05-28 14:10:00 -04:00
mmcwilliams ce226a7f86 Calculate stats on device.ready 2019-05-28 13:41:25 -04:00
mmcwilliams 4ea390897a Refactored seq.js to Typescript and fixed stats for 1 cam 1 proj. Will need further work to add in multiple devices. Resolves #6. 2019-05-28 13:33:16 -04:00
mmcwilliams c942d89572 Wire goto button on projector 2 and camera 2 to cmd.projector_second_to and cmd.camera_second_to. Resolves #9 2019-05-28 12:52:50 -04:00
mmcwilliams d0cc8eca70 GOTO counter error on projector 2 was due to a CSS error. Resolved #8. Increment patch number. 2019-05-28 12:28:45 -04:00
mmcwilliams 2e8d20f40a Update comments on devices module. 2019-05-28 12:16:01 -04:00
mmcwilliams 5c9091d957 Can't reproduce issue #13. Appeared on installation of unknown version. Close #13 for now. 2019-05-28 10:33:31 -04:00
mmcwilliams 1b3f554492 Caught the "to sequence" bug. Had not fully updated code. Resolves #5 2019-05-28 10:15:57 -04:00
mmcwilliams 67a009ae8d Increment patch to reflect changes that resolved issue 3 2019-05-28 09:15:29 -04:00
mmcwilliams 4dd69319e5 Add verbose output to typescript compile. 2019-05-28 09:07:26 -04:00
mmcwilliams 39301f5b59 FOUND THE BUG causing #3. Mscript still needs full conversion to typescript. This would have been caught on compile. Resolves #3, create a new issue for mscript refactor. 2019-05-28 09:06:59 -04:00
mmcwilliams ab8d7f57e9 Add a mocha-style test for mscript, related to issue #3 2019-05-28 09:02:55 -04:00
mmcwilliams 867d6a4069 Update cases 2019-05-06 13:24:40 -04:00
mmcwilliams f33dbb2f1b Enlarge box 2019-05-06 13:24:40 -04:00
mmcwilliams 1111800383 Merge remote-tracking branch 'origin/master' 2019-04-27 22:28:32 -04:00
mmcwilliams abaeb1cbda Update loop progress styles 2019-04-27 22:28:23 -04:00
mmcwilliams 4f9de487cc Move all scad files into scad dir 2019-04-24 14:06:35 -04:00
mmcwilliams e15d03a536 Semicolon 2019-04-20 19:52:26 -04:00
mmcwilliams ad558608ee All remaining dual projector, dual camera work. 2019-04-20 10:15:28 -04:00
mmcwilliams 1a612376cb Grid works for dual projectors. cam needs to be examined. 2019-04-20 10:15:01 -04:00
mmcwilliams a241ef0a2a Update config 2019-04-20 10:14:22 -04:00
mmcwilliams 687e1887ee Grid is reasonably functional with dual projectors. 2019-04-19 22:55:57 -04:00
mmcwilliams 5e0947d343 As much as I could do. Still doesn't work. Last commit. 2019-04-18 21:58:11 -04:00
mmcwilliams 1fe71cefca Two cases 2019-04-16 15:26:41 -04:00
mmcwilliams 88e470c5ac Installed 2019-04-16 14:36:55 -04:00
mmcwilliams 2d7599472e Add box laser for making cases. 2019-04-16 14:35:39 -04:00
mmcw-dev bb2bfabf9c 2 2019-04-16 10:01:54 -04:00
mmcw-dev b33ef36ab4 Work on multiple device UI 2019-04-16 10:01:42 -04:00
mmcw-dev ed14564de7 Fix issue of false positives on detecting second cmaeras and projectors 2019-04-15 16:15:34 -04:00
mmcw-dev 9603f82c49 Use mocha for testing, instead of qunit 2019-04-15 16:14:07 -04:00
mmcw-dev 52aac3f8b0 Settings module restores state to a default on "restore" 2019-04-15 16:13:28 -04:00
mmcw-dev 4f7dd92311 Update the silent log methods to return false. 2019-04-15 16:11:18 -04:00
mmcw-dev 265f383f65 Create new tests for mocha and chai 2019-04-15 15:10:29 -04:00
mmcw-dev 11b389172c Stash old tests 2019-04-15 15:08:28 -04:00
mmcw-dev dac70a122f Begin testing with mocha and chai. 2019-04-15 13:07:47 -04:00
mmcwilliams 7a52bc7c6e Secondary projector and secondary camera behaviors have been added to the main process. This is not represented in the UI... yet. All renderer code is still in flux. 2019-04-04 18:49:07 -04:00
mmcwilliams 18c515402e Installed on mac and ran build on mac. Works! 2019-04-04 01:07:30 -04:00
mmcwilliams cda100b3e6 Electron build works again on debian-based linux. 2019-04-03 18:58:13 -04:00
mmcwilliams 63e42f2dd3 Need to install request now, locally, for latest electron build. 2019-04-03 18:54:37 -04:00
mmcwilliams fd09e7c024 Add a processing sketch which connects to basic 2019-04-02 17:49:56 -04:00
mmcw-dev d995a4800d Update install process. 2019-04-02 11:11:26 -04:00
mmcwilliams 96754fcf49 Work on progress bar. 2019-04-02 10:21:01 -04:00
mmcwilliams d1480181b3 Remove exasperated comment. 2019-04-01 11:07:25 -04:00
mmcwilliams d6fd83762e Remove mcopy.state.camera and mcopy.state.projector. 2019-03-31 15:13:21 -04:00
mmcwilliams 7d2033db3d Remove comment containing documentation for the dialog.showMessageBox method from electron. That API is ever-evolving and it's best to rely on their published docs. 2019-03-31 12:13:15 -04:00
mmcwilliams 072c67fd0f Update counters. Use local state within objects cam and proj instead of mcopy.state 2019-03-30 20:29:01 -04:00
mmcwilliams 3e5bda77db Move docs generation to host repo 2019-03-30 17:56:31 -04:00
mmcwilliams 1510762fbb Sequencer uses class variables that are either set using arguments passed from the renderer, or uses the variables named "grid" referring to the grid.js gui. 2019-03-29 20:44:12 -04:00
mmcwilliams 429e66717d Files from previous commit 2019-03-24 00:25:16 -04:00
mmcwilliams c129739394 Sequence module is controlled from the UI. Everything runs in the main.js on the main process. The DOM changes when ipc messages are sent from the sequence module to the render process. 2019-03-24 00:24:39 -04:00
mmcwilliams 43ee0d0672 Sequence now runs entirely in the main process. Renderer no longer stores the sequence, it is a for loop inside the main process. 2019-03-23 21:58:22 -04:00
mmcwilliams 11e9176cb8 Bump patch and add uuid types for typescript 2019-03-23 10:49:18 -04:00
mmcwilliams 4d62421446 Remove non-source files from src lib of system module 2019-03-23 10:48:43 -04:00
mmcwilliams e35c41791b Create a system lib that can be used in the UI and cli. 2019-03-22 20:29:36 -04:00
mmcwilliams b02b92c1c7 Update version across the repo. 2019-03-22 20:29:09 -04:00
mmcwilliams 372ab01d57 Pull version features from build script 2019-03-22 20:28:16 -04:00
mmcwilliams 79e16fb166 Add a "version.sh" shell script to bump the version of the app and distribute it throughout the repo. 2019-03-22 20:27:55 -04:00
mmcwilliams 74e6b9c1b2 Install systeminformation module. This will allow a cross platform solution that doesnt use the electron api for enumerating displays 2019-03-22 19:53:44 -04:00
mmcwilliams 1413e323f0 Install private modules in the cli project 2019-03-22 19:52:59 -04:00
mmcwilliams f09ada2cd2 Build and version the package json files on each npm run build 2019-03-22 19:52:21 -04:00
mmcwilliams 283085cb8d Move the cfg.json file master to the root. 2019-03-22 19:51:06 -04:00
mmcwilliams 5717fc8cfe Add a build script to build cli with pkg. 2019-03-22 19:50:46 -04:00
mmcwilliams 42691c1577 All work on grid + sequencer rewrite. 2019-03-22 17:06:57 -04:00
mmcwilliams cfbeeb3ce9 Add a pause button that is hidden by default. 2019-03-22 17:04:29 -04:00
mmcwilliams dcca364b78 Update to electron 4. Updated electron-rebuild and electron-packager. Removed sqlite because it is currently unused and takes forever to rebuild. Originally intended to store timings of actions to optimize performance. Putting those plans on ice for now. 2019-03-22 17:01:54 -04:00
mmcwilliams 553d2bbb0d Made progress on sequencer module, renamed from sequence. 2019-03-22 04:33:53 -04:00
mmcwilliams 425dd9fd6a Initial updates to sequence module. Will try to simplify into a for loop, but if tests fail will re-write to a similar form as the renderer seq.js module 2019-03-22 03:22:33 -04:00
mmcwilliams c436406e9e Add todo in grid.js. This will be the biggest change in the rewrite. All ui/cmd.js commands must be re-written to be entirely ipc based and then all seq commands will be re-written to be ipc based as well. 2019-03-22 03:15:43 -04:00
mmcwilliams 52e6431d65 Rename seq.cmd object keys to new full-length strings 2019-03-22 03:14:16 -04:00
mmcwilliams ddb33e7f35 Require the Commands module as cmd in main.js 2019-03-22 03:13:46 -04:00
mmcwilliams 3dcfa708d2 Add shortened commands to the cfg.json file 2019-03-22 03:12:42 -04:00
mmcwilliams aff3678daf Rename "RUN" button to "START" to match internal terminology and make it clearer to me. 2019-03-22 03:12:04 -04:00
mmcwilliams 4356abc820 Disable light from the UI if necessary. Kind of circuitous, will refactor. 2019-03-21 22:55:12 -04:00
mmcwilliams 41a5fd087d Last work on display for tonight. Add a boolean attribute "opened" to re-open the digitalWindow if closed. 2019-03-21 22:54:49 -04:00
mmcwilliams 742adccf34 Took a tiny detour on the film out feature, or "digital projector". This now avoids showing a browser window fullscreen on mac, which is having performance issues when opening and then running sequences. There is a major source of lag, seemingly coming from the camera? Need to test with fake projector to see if there's a problem with the arduino lib. 2019-03-21 22:33:30 -04:00
mmcwilliams 97f1464106 Print the current active version into the mcopy.state object 2019-03-21 21:32:33 -04:00
mmcwilliams aef8709ab0 Add placeholders for exec and spawn modules 2019-03-21 21:18:27 -04:00
mmcwilliams 0ff1b5ff7d Refactor display module into typescript 2019-03-21 21:18:13 -04:00
mmcwilliams d264429726 Create new doc files for new libs or ones with jsdoc 2019-03-21 21:03:03 -04:00
mmcwilliams 65ba1f8c18 Add new grid file 2019-03-21 21:02:41 -04:00
mmcwilliams 48e8415ee4 Rename all keys to full "camera_" vs "cam_" and "projector_" vs "proj_" for consistency across the app.
Successfully separate and refactor gui.grid object to gui.
2019-03-21 21:02:28 -04:00
mmcwilliams e5a1654341 Use local id string so that duplicate instances of the classes can talk to one another. 2019-03-21 19:45:48 -04:00
mmcwilliams 6d1e9ec78f Print state for now. Need to store position in it? Make resetting it simple. 2019-03-21 19:36:37 -04:00
mmcwilliams fe046027da In camera and projector modules, for both main and renderer, use a string id to bind ipc paths and set up the ability to then have multiple of the proj, cam or even light class. Need to do light. 2019-03-21 19:34:56 -04:00
mmcwilliams 600a0abc72 Create and install main process lib to control the cmd.js module 2019-03-21 19:33:01 -04:00
M McWilliams 7a87ac924a Windows install seems to swap some https/http calls ins package-lock.json. Fascinating. 2019-03-21 18:14:53 -04:00
mmcwilliams 7ce3fa854a Remove dev object and replace with new devices module. Log an error on failure to enumerate devices that isn't caught within the method. 2019-03-21 18:09:14 -04:00
mmcwilliams 82e10bb4a4 Increment minor version. This marks the "feature complete" refactor of the core functionality in typescript using classes instead of objects in the main.js process.
Also, install the new devices module that was refactored into a class from an object. This has been tested with firmware, but additional development on this minor version will pull more UI elements into the main process. This will allow a CLI app to be created more efficiently and kept in sync with the rest of the project. Interface with the firmware will be expanded to control multiple projectors or multiple cameras in the next minor version.
2019-03-21 18:08:24 -04:00
mmcwilliams fc3cc96cd8 Use the import Log = require() method of including log lib. This is cleaner and easier to read when parsing dependencies. 2019-03-21 18:03:53 -04:00
mmcwilliams 478799965e Update log format, remove timestamp and use file "mcopy.log" in mcopy dir, not mcopy-cli. 2019-03-21 18:01:41 -04:00
mmcwilliams 099cd3052a Refactor settings into Typescript class module.
Refactor devices into Typescript class module from object.
2019-03-21 18:00:34 -04:00
mmcwilliams ea91ea5ff5 Remove console logging from arduino lib. Reject or throw to log errors 2019-03-21 15:59:50 -04:00
mmcwilliams 6a31eda3c4 Add label to cam, light and proj module logging 2019-03-21 15:57:16 -04:00
mmcwilliams d74e756b05 Rest of last commit 2019-03-21 15:57:10 -04:00
mmcwilliams 91ee19f2ab Add correct alias strings to arduino lib 2019-03-21 15:56:33 -04:00
mmcwilliams c563bf0dd3 Add a label argument to the log module. 2019-03-21 15:54:55 -04:00
mmcwilliams 87d43fc15b Only use log module in main 2019-03-21 15:47:25 -04:00
mmcwilliams 94942d86f9 Remove log from UI. Just use console and write directly to system log. 2019-03-21 15:47:07 -04:00
mmcwilliams bfb9bcbbe4 All vars become consts to prevent redeclaration during this rewrite (and they should be that anyway) 2019-03-21 15:43:03 -04:00
mmcwilliams f5f23284a3 Uncomment digital state interaction in proj module 2019-03-21 15:31:17 -04:00
mmcwilliams 9472527c70 Merge broke the UI, whoops 2019-03-21 15:13:48 -04:00
mmcwilliams 6faf78b92e Merge remote-tracking branch 'origin/master' 2019-03-21 15:08:54 -04:00
mmcwilliams 1b6c56b2ad Sequence module compiled 2019-03-21 15:06:37 -04:00
mmcwilliams 42358e98eb Add a package to the log module 2019-03-21 15:03:42 -04:00
mmcwilliams 746f0e2753 Add global typescript d file to prevent compiler errors. It's a hack, yeah, yeah. 2019-03-21 15:03:24 -04:00
mmcwilliams cf7664fb2a Remove objects cam, proj, light and replace with new modules 2019-03-21 15:02:54 -04:00
mmcwilliams 05d1bc3ae2 Refactor delay into typescript 2019-03-21 15:02:05 -04:00
mmcwilliams e9ccdfc191 Refactor light module into typescript-compiled class 2019-03-21 15:01:29 -04:00
mmcwilliams dc080b8566 Refactor proj module into typescript-compiled proj module. 2019-03-21 15:00:47 -04:00
mmcwilliams 56aba1eaba Refactor cam module into cam module. 2019-03-21 14:59:46 -04:00
mmcwilliams c276525d3a Refactor arduino library as a class, using Typescript now. 2019-03-21 14:58:52 -04:00
mmcwilliams fce259d29b Create a "digital" module, moving the "dig" object from the main.js process to it's own class. 2019-03-21 14:58:00 -04:00
mmcwilliams 72575ce2a4 Update tsconfig to use ./lib as a reference 2019-03-21 14:55:52 -04:00
mmcwilliams 2408456d47 Install cam, log and mscript modules. 2019-03-20 23:04:52 -04:00
mmcwilliams f2c2d6ce43 WIP wednesday 2019-03-20 18:37:00 -04:00
mmcwilliams 7f0ab0fee3 Layout all commands that need to be added for dual projector functionality. 2019-03-20 15:44:07 -04:00
mmcwilliams 4236651a09 Move all relevant code into comments 2019-03-20 15:33:51 -04:00
mmcwilliams fe85cc1b37 Re-write of the sequence module will require incorporating more moving parts than I anticipated. I will move forward with the temporary rewrite and then later focus on the long-term rewrite. 2019-03-20 15:30:45 -04:00
mmcwilliams d308b8a59e Merge remote-tracking branch 'origin/master' 2019-03-19 22:33:23 -04:00
mmcwilliams cc227e9a66 Rewrite seq.js front-end "module" as a main process module in the lib. Can be used by the CLI without a second rewrite. Remove all DOM logic, but make API compatible with seq.js so GUI does not have to change. 2019-03-19 22:33:15 -04:00
mmcwilliams a4682ed9d3 Simplify logs. Still prints timestamp as json. 2019-03-19 14:48:01 -04:00
mmcwilliams d19e83d616 Increment patch number and run `npm audit fix` 2019-03-18 19:43:27 -04:00
mmcwilliams 9bfc133a67 Add a function to cancel a sequence. This should only be used during "seq.exec()". 2019-03-18 19:42:12 -04:00
mmcwilliams f89ad53235 Caught a silly mistake. Accidentally referenced setDir instead of setExposure in intval exposure function. It's ok because that's dormant anyway. 2019-03-18 19:11:05 -04:00
mmcwilliams 0fbe45073c Add a seq.cmds object to map named actions to functions. This creates targets for MSCRIPT to compile to, and allows the sequence to be stored in a string array. 2019-03-18 18:42:31 -04:00
mmcwilliams 415306d7a8 Add comments to existing sequencer gui file. Question arises here: should this logic be pushed back into the main process so that there is less reliance on the renderer and all command logic takes place in main (or a sub-module) with the renderer being used only for display and not sequencing. This seems to be the path going forward, but will take a re-write that allows for GUI to interrupt the process as it does now. A proof of concept will have to be written to demonstrate that using `await delay(ms)` is viable and the process does not completely lock. 2019-03-18 18:41:35 -04:00
mmcwilliams b1e4015630 If light is not enabled when digital projector is selected, enable light. Otherwise, the light value will stay default 0,0,0 and all frames are rendered as black. 2019-03-18 18:35:49 -04:00
mmcwilliams ad97086bf0 Overwrite any exported frame by adding -y flag to the ffmpeg command. 2019-03-18 18:28:31 -04:00
mmcwilliams 1d993b85d3 Create a scad file for extra odds and ends for the JK 2019-03-18 18:28:09 -04:00
mmcwilliams 46da2e6541 Add the new firmware identifiers as accepted responses. Also add text identifiers for firmware identified as the 4 new types. 2019-03-18 17:21:17 -04:00
mmcwilliams d4c2f5b678 Rebuild docs for arduino library after refactor into class. 2019-03-18 16:51:16 -04:00
mmcwilliams 9b4525e5a7 Refactor logFile function for readability.
Add comments to the log library. Build logs.
2019-03-18 16:50:40 -04:00
mmcwilliams 1a31767572 Fix the build script 2019-03-18 16:49:11 -04:00
mmcwilliams 74b326caeb Add ANYEYE scad work. Contains the motor key for connecting the INTVAL2/3 style motor mount and microswitch to a Revere 16mm projector. 2019-03-18 16:49:00 -04:00
mmcwilliams 029dd628b6 Add comments to cmd 2019-03-13 15:28:17 -04:00
mmcwilliams cf6e4f9de9 Disable light on projector 2019-03-13 15:28:07 -04:00
mmcwilliams e47abeaaa5 Hid light pads if light is disabled. 2019-03-10 13:18:59 -04:00
mmcwilliams 4eee61ab1b Hide labels if light is disabled. Hide navigation element if light is disabled. 2019-03-10 01:25:59 -05:00
mmcwilliams 4202d01630 Calling this a patch commit lets go! 2019-03-09 15:47:26 -05:00
mmcwilliams 00b5efa484 Logging still sucks. 2019-03-09 13:17:32 -05:00
mmcwilliams 15bb696b59 Await log require in cli app because of changes to local module. 2019-03-08 22:33:23 -05:00
mmcwilliams 95b6f77848 Try to improve logging. It's not there, yet. 2019-03-08 22:33:03 -05:00
mmcwilliams e186b1b9fc Write arg.profile and not the HTML element profile to log 2019-03-08 22:32:43 -05:00
mmcwilliams ede29216f7 Update arduino lib in app and cli 2019-03-08 22:32:25 -05:00
mmcwilliams faeddb84ab Build log 2019-03-08 22:31:51 -05:00
mmcwilliams 87f3bcef6f Copy build libraries to cli app 2019-03-08 22:31:29 -05:00
mmcwilliams f0fae8ce1b Refactor arduino library as class, rather than object. 2019-03-08 11:27:24 -05:00
mmcw-dev febb39aef7 Change class notepad to mcopy 2019-03-07 20:57:57 -05:00
mmcw-dev b93266d1eb Start a proton-native app. Begin using the Notepad example from the proton-native repository 2019-03-06 17:34:28 -05:00
mmcwilliams c3f24b125e Update cli description 2019-03-04 22:10:23 -05:00
mmcwilliams fcdc6ebb1d Typescript adding commas to compiled code. 2019-03-04 22:10:15 -05:00
mmcwilliams ec0b8e3b4f Run docs as shell, not bash 2019-03-04 22:09:26 -05:00
mmcwilliams aa5bbfc9fd Port shared modules to typescript. Migrate shared modules first, then look at individual needs of sub-projects. 2019-03-04 22:09:12 -05:00
mmcwilliams 806342b623 Ignore node_modules 2019-03-04 22:07:04 -05:00
mmcwilliams 307ef33a10 Update description as project expands and reshapes. Now will develop shared modules for the app, cli and then the "native" experimental app written in proton-native. 2019-03-04 22:06:40 -05:00
mmcwilliams f276d5ce83 Add commands for controlling a secondary projector. 2019-03-01 20:14:20 -05:00
mmcwilliams 200671b1cf Increment patch number for new build. 2019-03-01 18:02:39 -05:00
mmcwilliams 46ce99ec18 Add an alternate camera firmware for MONO NO AWARE's JK. 2019-03-01 18:01:45 -05:00
mmcwilliams fcc4da3672 Add additional cases to the arduino filter when looking for devices to connect with. 2019-03-01 18:01:16 -05:00
mmcwilliams c93413bae4 Hide video feature until better fleshed out. 2019-03-01 18:00:49 -05:00
mmcwilliams ac888b1fc4 Firmware first drafts for MONO NO AWARE optical printer 2019-02-28 17:50:39 -05:00
mmcwilliams b9bd62bb78 Add mp4 to allowable file extension filter 2019-02-28 17:50:13 -05:00
mmcwilliams 1612d737a1 Add second UI element behavior for new video screen. 2019-02-26 21:58:26 -05:00
mmcwilliams 7a901b31c4 Add log to device module. This cli app is turning into a dog fast. Need to take a step back and reconsider. 2019-02-26 21:57:43 -05:00
mmcwilliams aff06619a0 Add video screen to UI 2019-02-26 21:57:07 -05:00
mmcwilliams da7faf59a5 Add documentation to code on GUI grid features, needed to because I will be modifying this extensively. 2019-02-26 21:56:39 -05:00
mmcwilliams a5a9a4ea86 Refactor arduino module to not use the mcopy. prefix. This should really be a class, not an object. We'll get there. 2019-02-26 21:55:52 -05:00
mmcwilliams b481906c86 Add video screen, to be used for better control of the digital projector. 2019-02-26 21:54:46 -05:00
mmcwilliams b19b20dad9 Use exit and arduino modules properly 2019-02-26 21:54:04 -05:00
mmcwilliams a9dd45a464 Add some docs to the code. Work in progress 2019-02-26 21:53:32 -05:00
mmcwilliams bc9e882a37 Install exit module 2019-02-26 21:10:11 -05:00
mmcwilliams fa477aec83 Install exit module in cli app 2019-02-26 21:09:35 -05:00
mmcwilliams 8b2095227c Add case for updating the UI when second projector connected. 2019-02-26 16:43:38 -05:00
mmcwilliams 6622a72241 Resize app when second projector connected 2019-02-26 16:43:14 -05:00
mmcwilliams c964410f7b Add variable for tracking whether or not light feature is disabled. 2019-02-26 16:42:54 -05:00
mmcwilliams b98b831ae4 Fix projector_second component code. 2019-02-26 16:42:04 -05:00
mmcwilliams 643e88aef3 Add a placeholder config profile for the MONO JK 2019-02-26 16:00:59 -05:00
mmcw-dev aff070cdc4 Connect second projector 2019-02-26 11:49:00 -05:00
mmcw-dev 955e49fff2 Add exit module to cli tool 2019-02-25 20:24:42 -05:00
mmcwilliams 7398f7993d Start work on secondary projector feature 2019-02-25 18:14:29 -05:00
mmcwilliams 48b86ebc93 Got basic arduino functionality working. Can enumerate devices. 2019-02-24 08:45:13 -05:00
mmcwilliams bee40965b1 Make modules local because modules in /app directory are recompiled for electron. Throws error on load in node 10. 2019-02-24 08:32:16 -05:00
mmcwilliams fb08a28543 Update mscript tests. Could not repro error because it is due to escaping. 2019-02-24 08:31:22 -05:00
mmcwilliams 4947cbcc9d Found range error in common usage example. Check test coverage 2019-02-24 08:23:57 -05:00
mmcwilliams bf3adec727 Interpret mscript commands on input. 2019-02-24 08:22:59 -05:00
mmcwilliams 58ade0518e Return mscript output if no callback defined 2019-02-24 08:22:41 -05:00
mmcwilliams 56a83615a9 Begin mcopy-cli for a simple command line interface 2019-02-24 08:13:47 -05:00
mmcwilliams 73ae599cff Uninstall and remove references to async module 2019-02-23 22:40:59 -05:00
mmcw-dev 723b23fa41 Fix intval bug and apply UI projector value change to digital file state. 2019-02-23 22:19:42 -05:00
mmcw-dev bf148c6784 Set value to digital projector feature when changing it in UI 2019-02-23 22:19:03 -05:00
mmcwilliams 7fd449724b Convert comment to string on light object. Will use in a modal. 2019-02-23 12:25:47 -05:00
mmcwilliams 8ebdbf9f6f Add docs script to package.json 2019-02-23 12:25:47 -05:00
mmcwilliams 54ab121e89 Feeble first attempt at documenting code 2019-02-23 12:25:47 -05:00
mmcwilliams 16dcd1e3d4 Move all scripts into scripts directory 2019-02-23 12:25:47 -05:00
mmcwilliams 8bd505da36 Save and restore settings, including profiles. 2019-02-23 12:25:46 -05:00
Matt b99491909b
Update Readme.md
Add latest build to Readme
2019-02-13 19:01:39 -05:00
mmcwilliams 4de536e2e8 Incrementing patch. Fixed color and timing issues with "digital" sequences. 2019-02-13 19:00:10 -05:00
mmcwilliams 8fd29e89d8 Okay. Removed the light.state.on behavior. Now, a frame is rendered to the set color state of the "light" only when the camera is moving. Unnecessary frames don't display AND the correct color is represented at the right time. No juggling state values between steps in the sequence. 2019-02-13 18:57:18 -05:00
mmcwilliams e7ac873f41 Two birds, one commit. Can even pull out the bad logic of the light.state.on value, but that's not hurting anybody. 2019-02-13 18:49:59 -05:00
mmcwilliams ed8f1add35 Merge remote-tracking branch 'origin/master' 2019-02-11 01:34:38 -05:00
mmcwilliams dbe96491f9 Update version in package-lock.json 2019-02-11 01:34:28 -05:00
mmcw-dev 962a7c8213 Fix loop bug. When selection a video as a projector (need to work on this metaphor) the loops are automatically set. Previous issues were due to id re-use.
Also, (almost) you can choose a light color value that a frame will be overlayed on with a Darken composite mode. This is almost working but is kludgey because the first frame is always coming up black. Will need to make adjustments in the light module.
2019-02-11 01:08:20 -05:00
mmcw-dev 3493759998 Scale frame export to video's advertized size 2019-02-10 14:07:07 -05:00
mmcw-dev b6a6b8a81e Reverse High/low for relay 2019-02-09 09:30:11 -05:00
416 changed files with 3279489 additions and 9606 deletions

13
.gitignore vendored
View File

@ -1,3 +1,12 @@
*.DS_Store
dist/
*.Parent
.AppleDouble
*.Parent
node_modules
dist
*.svd
*debug_custom.json
*debug.cfg
notes/mphd

9
.gitmodules vendored Normal file
View File

@ -0,0 +1,9 @@
[submodule "scad/common"]
path = scad/common
url = https://git.sixteenmillimeter.com/modules/common.git
[submodule "scad/sprocketed_roller"]
path = scad/sprocketed_roller
url = https://git.sixteenmillimeter.com/modules/sprocketed_roller.git
[submodule "scad/MCAD"]
path = scad/MCAD
url = https://github.com/openscad/MCAD.git

View File

@ -1,4 +1,4 @@
Copyright 2018 M McWilliams
Copyright 2018-2021 M McWilliams
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:

166
Readme.md
View File

@ -1,73 +1,93 @@
# mcopy
An open platform for controlling small-gauge film optical printers (16mm, Super8, 8mm).
-------
1. <a href="#intro">Introduction</a>
2. <a href="#downloads">Downloads</a>
1. <a href="#usage">Usage</a>
2. <a href="#software">Software</a>
3. <a href="#firmware">Firmware</a>
3. <a href="#hardware">Hardware</a>
4. <a href="#why">Why?</a>
-------
## Introduction <a name="intro"></a>
The `mcopy` project is comprised of software and hardware for optical printers, built with re-purposed broken projectors.
#### Components
* Sequencer desktop app
* Scripting language, called `mscript`, for orchestrating complex sequences
* Arduino firmware for projectors, cameras, lights and existing printers
* 3D models of parts used for modifying projectors and printers
* Schematics for simple Arduino-based electronics
## Downloads <a name="downloads"></a>
* [1.0.3](https://github.com/sixteenmillimeter/mcopy/releases/tag/1.0.3) for macOS and Linux (.deb)
For Windows, you can [install from source](https://github.com/sixteenmillimeter/mcopy/tree/master/app#mcopy-desktop-app) for now.
## Usage <a name="usage"></a>
The software requires your hardware to be in place before the mcopy control app is useful.
![mcopy app](docs/mcopy.png?raw=true "mcopy app")
## Software <a name="software"></a>
The mcopy desktop app is an Electron-based project which can be built for Linux, Windows and macOS.
Pre-built packages will be made available for macOS, initially, with the other two target platforms to follow.
To build the desktop app from source, see the [installation and running instructions](https://github.com/sixteenmillimeter/mcopy/tree/master/app#mcopy-desktop-app).
The desktop software also interoperates with two related projects; the Bluetooth + Wifi capable, Raspberry Pi-based [INTVAL3](https://github.com/sixteenmillimeter/intval3) and the Arduino-based [intval2](https://github.com/sixteenmillimeter/intval2).
## Firmware <a name="firmware"></a>
This project contains Arduino formware for controlling:
* a projector
* a camera (see [intval2](https://github.com/sixteenmillimeter/intval2) for more info)
* a light
* a projector + a camera
* a projector + a light
* a camera + a light
* a camera + a projector + a light
Using a simple serial interface, this modular platform can be used to control DIY components, modified existing optical printers or a mixture of components.
The desktop app can connect to multiple serial devices, so your mcopy optical printer can be built from various designs that suit your hardware tastes/needs/available parts.
## Hardware <a name="hardware"></a>
All non-electronic hardware for this project is available as plaintext OpenSCAD files and 3D print-able .STL files.
The hardware component of this project is aimed at modifying broken Bell & Howell projectors into USB serial-controlled projectors to be used in optical printing.
As a secondary capability, this desktop software and firmware package can be used to replace the sequencers for early-model JK optical printers, with some modification.
## Why? <a name="why"></a>
I'm interested in expanding the viability and access of the 16mm film format and to repurpose thre rising tide of discarded film technology.
# mcopy
An open platform for controlling small-gauge film optical printers (16mm, Super8, 8mm).
## [Project Home - git.sixteenmillimeter.com/16mm/mcopy](https://git.sixteenmillimeter.com/16mm/mcopy)
* Github Mirror - [github.com/sixteenmillimeter/mcopy](https://github.com/sixteenmillimeter/mcopy)
* Gitlab Mirror - [gitlab.com/16mm/mcopy](https://gitlab.com/16mm/mcopy)
-------
1. <a href="#intro">Introduction</a>
2. <a href="#downloads">Downloads</a>
1. <a href="#usage">Usage</a>
2. <a href="#software">Software</a>
3. <a href="#firmware">Firmware</a>
3. <a href="#hardware">Hardware</a>
4. <a href="#why">Why?</a>
-------
## Introduction <a name="intro"></a>
The `mcopy` project is comprised of software and hardware for optical printers, built with re-purposed broken projectors.
#### Components
* Sequencer desktop app
* Scripting language, called `mscript`, for orchestrating complex sequences
* Arduino firmware for projectors, cameras, lights and existing printers
* 3D models of parts used for modifying projectors and printers
* Schematics for simple Arduino-based electronics
* Filmout feature for digitally transferring video and images to analog film
* Interoperability with the [intval3](https://github.com/sixteenmillimeter/intval3) intervalometer
## Downloads <a name="downloads"></a>
### Latest Installers
* [1.6.9](https://github.com/sixteenmillimeter/mcopy/releases/tag/1.6.9) for macOS, Linux (.deb) and Windows (.msi)
### Older Versions
* [1.6.7](https://github.com/sixteenmillimeter/mcopy/releases/tag/1.6.7) for macOS and Linux (.deb)
* [1.6.4](https://github.com/sixteenmillimeter/mcopy/releases/tag/1.6.4) for macOS, Linux (.deb) and Windows (.msi)
* [1.6.2](https://github.com/sixteenmillimeter/mcopy/releases/tag/1.6.2) for macOS
* [1.6.1](https://github.com/sixteenmillimeter/mcopy/releases/tag/1.6.1) for macOS
* [1.5.2](https://github.com/sixteenmillimeter/mcopy/releases/tag/1.5.2) for macOS
* [1.4.9](https://github.com/sixteenmillimeter/mcopy/releases/tag/1.4.9) for macOS and Linux (.deb)
* [1.2.0](https://github.com/sixteenmillimeter/mcopy/releases/tag/1.2.0) for macOS and Linux (.deb)
* [1.0.3](https://github.com/sixteenmillimeter/mcopy/releases/tag/1.0.3) for macOS and Linux (.deb)
For Windows, you can [install from source](https://github.com/sixteenmillimeter/mcopy/tree/master/app#mcopy-desktop-app) for now.
## Usage <a name="usage"></a>
The software requires your hardware to be in place before the mcopy control app is useful.
![mcopy app](docs/mcopy.png?raw=true "mcopy app")
## Software <a name="software"></a>
The mcopy desktop app is an Electron-based project which can be built for Linux, Windows and macOS.
Pre-built packages will be made available for macOS, initially, with the other two target platforms to follow.
To build the desktop app from source, see the [installation and running instructions](https://github.com/sixteenmillimeter/mcopy/tree/master/app#mcopy-desktop-app).
The desktop software also interoperates with two related projects; the Bluetooth + Wifi capable, Raspberry Pi-based [INTVAL3](https://github.com/sixteenmillimeter/intval3) and the Arduino-based [intval2](https://github.com/sixteenmillimeter/intval2).
## Firmware <a name="firmware"></a>
This project contains Arduino formware for controlling:
* a projector
* a camera (see [intval2](https://github.com/sixteenmillimeter/intval2) for more info)
* a light
* a projector + a camera
* a projector + a light
* a camera + a light
* a camera + a projector + a light
Using a simple serial interface, this modular platform can be used to control DIY components, modified existing optical printers or a mixture of components.
The desktop app can connect to multiple serial devices, so your mcopy optical printer can be built from various designs that suit your hardware tastes/needs/available parts.
## Hardware <a name="hardware"></a>
All non-electronic hardware for this project is available as plaintext OpenSCAD files and 3D print-able .STL files.
The hardware component of this project is aimed at modifying broken Bell & Howell projectors into USB serial-controlled projectors to be used in optical printing.
As a secondary capability, this desktop software and firmware package can be used to replace the sequencers for early-model JK optical printers, with some modification.
## Why? <a name="why"></a>
I'm interested in expanding the viability and access of the 16mm film format and to repurpose thre rising tide of discarded film technology.

5
app/.gitignore vendored
View File

@ -1,3 +1,6 @@
node_modules/*
logs/*
data/transfer*.json
data/transfer*.json
.appleId*
.applePwd*
.appleIdentity*

View File

@ -1,11 +0,0 @@
#!/bin/bash
./node_modules/.bin/electron-packager . --overwrite --platform=darwin --arch=x64 --icon=assets/icons/icon.icns --prune=true --out=../dist
#build dmg for mac install
sleep 5s
mkdir ../dist/installers
./node_modules/.bin/electron-installer-dmg ../dist/mcopy-app-darwin-x64/mcopy-app.app mcopy-app --out=../dist/installers --icon=assets/icons/icon.icns --overwrite
# Path to the icon file that will be the app icon in the DMG window.
# --icon-size=<px> How big to make the icon for the app in the DMG. [Default: `80`].
# --background=<path> Path to a PNG image to use as the background of the DMG.
#--overwrite Overwrite any existing DMG.

View File

@ -1,18 +0,0 @@
const { MSICreator } = require('electron-wix-msi');
// Step 1: Instantiate the MSICreator
const msiCreator = new MSICreator({
appDirectory: '../dist/mcopy-win32-x64',
description: 'mcopy optical printer GUI',
exe: 'mcopy',
name: 'mcopy',
manufacturer: 'sixteenmillimeter.com',
version: '2.0.0',
outputDirectory: '../dist/'
});
// Step 2: Create a .wxs template file
msiCreator.create();
// Step 3: Compile the template to a .msi file
setTimeout(msiCreator.compile, 30000)

View File

@ -1,7 +0,0 @@
#!/bin/bash
./node_modules/.bin/electron-packager . mcopy --overwrite --asar=true --platform=win32 --arch=x64 --icon=assets/icons/icon.ico --prune=true --out=../dist --version-string.CompanyName="sixteenmillimeter.com" --version-string.FileDescription="Open Source Optical Printer Platform" --version-string.ProductName="mcopy"
mkdir ../dist/installers
node ./build_win.js

View File

@ -194,8 +194,8 @@ button:focus {
width: 66px;
height: 66px;
position: absolute;
top: 7px;
left: 7px;
top: 14px / 2;
left: 14px / 2;
}
.dial-wrapper input {
margin-top: 94px;
@ -210,10 +210,10 @@ button:focus {
top: 0;
bottom: 0;
overflow: hidden;
width: 40px;
width: 80px / 2;
}
.dial-container.dial-container1 {
left: 40px;
left: 80px / 2;
}
.dial-container.dial-container1 .dial-wedge {
transform: rotateZ(0deg);
@ -227,16 +227,16 @@ button:focus {
.dial-container.dial-container2 .dial-wedge {
transform: rotateZ(0deg);
border-radius: 80px 0 0 80px;
transform-origin: 40px 40px;
transform-origin: 80px/2 80px/2;
}
.dial-wedge {
height: 80px;
width: 40px;
width: 80px / 2;
}
.dial-marker {
border-radius: 50%;
height: 7px;
width: 7px;
height: 14px / 2;
width: 14px / 2;
position: absolute;
top: 0;
left: calc(50% - (14px * 2));
@ -367,6 +367,7 @@ button:focus {
float: right;
width: 90px;
margin-right: 60px;
height: 32px;
}
#seq_stats {
width: 40%;
@ -381,16 +382,16 @@ button:focus {
font-weight: 600;
float: right;
}
#seq_loop {
#seq_loop_wrap {
width: 40%;
float: left;
padding: 0 0 0 56px;
}
#seq_loop h3 {
#seq_loop_wrap h3 {
font-size: 20px;
margin: 12px 0 3px;
}
#seq_loop input {
#seq_loop_wrap input {
font-family: 'Menlo', monospace;
background: rgba(255, 255, 255, 0.05);
color: #fff;
@ -402,48 +403,91 @@ button:focus {
#sequence {
width: 970px;
padding-bottom: 21px;
padding-left: 70px;
padding-left: 92px;
}
#sequence #cam_forward,
#sequence #proj_forward,
#sequence #camera_forward,
#sequence #camera_second_forward,
#sequence #projector_forward,
#sequence #projector_second_forward,
#sequence #black_forward {
clear: both;
}
#sequence #cam_forward input[type=checkbox],
#sequence #proj_forward input[type=checkbox],
#sequence #camera_forward input[type=checkbox],
#sequence #camera_second_forward input[type=checkbox],
#sequence #projector_forward input[type=checkbox],
#sequence #projector_second_forward input[type=checkbox],
#sequence #black_forward input[type=checkbox] {
border: 2px solid #00C4A0;
}
#sequence #cam_forward input[type=checkbox]:checked,
#sequence #proj_forward input[type=checkbox]:checked,
#sequence #camera_forward input[type=checkbox]:checked,
#sequence #camera_second_forward input[type=checkbox]:checked,
#sequence #projector_forward input[type=checkbox]:checked,
#sequence #projector_second_forward input[type=checkbox]:checked,
#sequence #black_forward input[type=checkbox]:checked {
background: #00C4A0;
}
#sequence #cam_forward > div,
#sequence #proj_forward > div,
#sequence #camera_forward > div,
#sequence #camera_second_forward > div,
#sequence #projector_forward > div,
#sequence #projector_second_forward > div,
#sequence #black_forward > div {
color: #00C4A0;
}
#sequence #cam_backward,
#sequence #proj_backward,
#sequence #camera_backward,
#sequence #camera_second_backward,
#sequence #projector_backward,
#sequence #projector_second_backward,
#sequence #black_backward {
clear: both;
}
#sequence #cam_backward input[type=checkbox],
#sequence #proj_backward input[type=checkbox],
#sequence #camera_backward input[type=checkbox],
#sequence #camera_second_backward input[type=checkbox],
#sequence #projector_backward input[type=checkbox],
#sequence #projector_second_backward input[type=checkbox],
#sequence #black_backward input[type=checkbox] {
border: 2px solid #AB1A25;
}
#sequence #cam_backward input[type=checkbox]:checked,
#sequence #proj_backward input[type=checkbox]:checked,
#sequence #camera_backward input[type=checkbox]:checked,
#sequence #camera_second_backward input[type=checkbox]:checked,
#sequence #projector_backward input[type=checkbox]:checked,
#sequence #projector_second_backward input[type=checkbox]:checked,
#sequence #black_backward input[type=checkbox]:checked {
background: #AB1A25;
}
#sequence #cam_backward > div,
#sequence #proj_backward > div,
#sequence #camera_backward > div,
#sequence #camera_second_backward > div,
#sequence #projector_backward > div,
#sequence #projector_second_backward > div,
#sequence #black_backward > div {
color: #AB1A25;
}
#sequence #camera_second_forward input[type=checkbox],
#sequence #projector_second_forward input[type=checkbox] {
border: 2px solid #14d8b4;
}
#sequence #camera_second_forward input[type=checkbox]:checked,
#sequence #projector_second_forward input[type=checkbox]:checked {
background: #14d8b4;
}
#sequence #camera_second_forward > div,
#sequence #projector_second_forward > div {
color: #14d8b4;
}
#sequence #camera_second_backward input[type=checkbox],
#sequence #projector_second_backward input[type=checkbox] {
border: 2px solid #bf2e39;
}
#sequence #camera_second_backward input[type=checkbox]:checked,
#sequence #projector_second_backward input[type=checkbox]:checked {
background: #bf2e39;
}
#sequence #camera_second_backward > div,
#sequence #projector_second_backward > div {
color: #bf2e39;
}
#sequence #black input[type=checkbox]:checked {
background: white;
}
#sequence input[type=checkbox] {
-webkit-appearance: none;
-moz-appearance: none;
@ -460,6 +504,10 @@ button:focus {
box-sizing: border-box;
cursor: pointer;
}
#sequence input[type=checkbox].disabled {
cursor: not-allowed;
border-color: #646464;
}
#sequence .L {
display: inline-block;
width: 35px;
@ -504,10 +552,10 @@ button:focus {
font-family: 'Menlo', monospace;
background-color: #272b30;
position: absolute;
top: 115px;
top: 113px;
padding-top: 2px;
padding-bottom: 15px;
width: 54px;
width: 75px;
}
#seq_labels div {
height: 43px;
@ -518,16 +566,41 @@ button:focus {
display: inline-block;
margin-right: 5px;
}
#seq_labels i.fa {
right: 3px;
position: absolute;
margin-top: 10px;
}
#loop_current {
margin-top: 54px;
width: 121px;
font-family: 'Menlo', monospace;
font-size: 22px;
margin-top: 13px;
margin-right: 50px;
width: 93px;
text-align: center;
position: relative;
float: right;
color: #DAE035;
}
#buttons > div {
#seq_pause {
display: none;
}
#seq_progress {
width: 100%;
height: 15px;
position: fixed;
left: 0;
bottom: 0;
}
#buttons > div,
#buttons_2 > div {
width: 50%;
float: left;
}
#buttons .proj2,
#buttons_2 .proj2 {
float: right !important;
}
.cmd {
width: 240px;
text-align: center;
@ -562,6 +635,11 @@ button:focus {
background: #AB1A25;
border-color: #AB1A25;
}
.cmd:active.capper,
.cmd.active.capper {
background: white;
color: #272b30;
}
.cmd:active i,
.cmd.active i {
color: #272b30;
@ -585,14 +663,44 @@ button:focus {
::-webkit-scrollbar-thumb:window-inactive {
background: rgba(0, 0, 0, 0.05);
}
#settings h4 {
margin-bottom: 1px;
}
#settings > div {
width: 300px;
margin: 0 auto;
}
#settings > div.left {
float: left;
padding-left: 30px;
}
#settings > div.right {
float: right;
padding-right: 30px;
}
#settings > div.right input[type=number] {
min-width: 200px;
width: 200px;
}
#settings > div.right input[readonly] {
cursor: not-allowed;
}
#settings > div.right .spacer {
height: 62px;
}
#settings > div.right .proj_time {
height: 111px;
}
#settings > div.right .cam_time {
height: 111px;
}
#settings > div.right > div {
width: 270px;
}
#settings > div > div {
width: 360px;
}
#settings input[type=text],
#settings input[type=number],
#settings select {
display: block;
border-radius: 5px;
@ -607,33 +715,43 @@ button:focus {
padding: 6px 12px;
font-size: 21px;
min-width: 300px;
max-width: 300px;
}
#settings input[type=text] span,
#settings input[type=number] span,
#settings select span {
display: block;
font-size: 16px;
font-weight: 200;
}
#settings input[type=text]:active,
#settings input[type=number]:active,
#settings select:active,
#settings input[type=text] .active,
#settings input[type=number] .active,
#settings select .active {
background: #fff;
color: #272b30;
outline: none;
}
#settings input[type=text]:focus,
#settings input[type=number]:focus,
#settings select:focus {
outline: none;
}
#settings input[type=text].active,
#settings input[type=number].active,
#settings select.active {
border-color: #DAE035;
color: #DAE035;
}
#settings input[type=text] {
width: 200px;
}
#settings button {
margin-top: -1px;
margin-top: 0px;
float: right;
padding: 8px 16px 9px;
}
#settings input[type=radio] {
float: right;
@ -642,6 +760,17 @@ button:focus {
#settings .spacer {
margin-top: 10px;
}
#settings #version {
position: absolute;
right: 20px;
bottom: 10px;
z-index: 1000;
height: 14px;
width: auto;
font-size: 14px;
line-height: 14px;
color: #999;
}
.cm-s-monokai.CodeMirror {
background: #272b30 !important;
}
@ -674,10 +803,148 @@ button:focus {
background: black;
color: #fff;
}
#log {
position: fixed;
#video input,
#video select {
display: block;
border-radius: 5px;
border: 2px solid #fff;
text-align: center;
background: transparent;
color: #fff;
padding: 8px 0;
font-size: 12px;
font-weight: 400;
display: inline-block;
padding: 6px 12px;
font-size: 21px;
min-width: 300px;
}
#video input span,
#video select span {
display: block;
font-size: 16px;
font-weight: 200;
}
#video input:active,
#video select:active,
#video input .active,
#video select .active {
background: #fff;
color: #272b30;
outline: none;
}
#video input:focus,
#video select:focus {
outline: none;
}
#video input.active,
#video select.active {
border-color: #DAE035;
color: #DAE035;
}
#video button,
#video select {
padding: 9px 16px 8px;
}
#path_bar {
padding: 5px;
height: 50px;
}
#path_bar input {
float: left;
}
#path_bar button {
float: left;
margin-left: 5px;
}
#path_bar select {
line-height: 41px;
height: 37px;
margin-right: 5px;
float: right;
box-sizing: content-box;
padding: 0 0 0 8px;
}
#filmout_monitor {
display: none;
border: 2px solid white;
box-sizing: border-box;
height: 360px;
margin: 0 auto;
position: relative;
}
#filmout_monitor.on {
display: block;
}
#filmout_preview_wrap {
background: #000;
width: 100%;
height: 160px;
height: 360px;
}
#filmout {
position: absolute;
background-repeat: no-repeat;
background-size: contain;
background-position: center;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: block;
opacity: 0;
}
#filmout.on {
opacity: 1;
}
#filmout_position_wrap {
padding-top: 5px;
height: 50px;
}
#filmout_position_wrap input {
margin-right: 5px;
margin-left: 5px;
width: 308px !important;
box-sizing: border-box;
}
#filmout_position_wrap button,
#filmout_position_wrap input {
float: left;
}
#filmout_position_wrap > div {
width: 425px;
margin: 0 auto;
}
#filmout_functions {
padding-top: 5px;
}
#filmout_functions > div {
width: 425px;
margin: 0 auto;
}
#filmout_stats_video,
#filmout_stats_monitor {
width: 150px;
position: absolute;
padding: 10px 5px;
text-align: center;
}
#filmout_stats_video h3,
#filmout_stats_monitor h3 {
font-size: 20px;
margin: 16px 0 3px;
text-align: center;
}
#filmout_stats_video {
left: 5px;
}
#filmout_stats_monitor {
right: 5px;
}
.hide {
display: none;
}
.show {
display: block;
}
#screens {
overflow-x: hidden;
@ -733,29 +1000,71 @@ button:focus {
}
#counters .cam,
#counters_2 .cam,
#counters_3 .cam,
#move_to .cam,
#move_to_2 .cam,
#counters .cam2,
#counters_2 .cam2,
#counters_3 .cam2,
#move_to .cam2,
#move_to_2 .cam2,
#counters .proj,
#counters_2 .proj,
#move_to .proj {
#counters_3 .proj,
#move_to .proj,
#move_to_2 .proj,
#counters .proj2,
#counters_2 .proj2,
#counters_3 .proj2,
#move_to .proj2,
#move_to_2 .proj2 {
width: 50%;
padding-bottom: 10px;
}
#counters .cam label,
#counters_2 .cam label,
#counters_3 .cam label,
#move_to .cam label,
#move_to_2 .cam label,
#counters .cam2 label,
#counters_2 .cam2 label,
#counters_3 .cam2 label,
#move_to .cam2 label,
#move_to_2 .cam2 label,
#counters .proj label,
#counters_2 .proj label,
#move_to .proj label {
#counters_3 .proj label,
#move_to .proj label,
#move_to_2 .proj label,
#counters .proj2 label,
#counters_2 .proj2 label,
#counters_3 .proj2 label,
#move_to .proj2 label,
#move_to_2 .proj2 label {
text-align: center;
font-size: 24px;
display: block;
}
#counters .cam input,
#counters_2 .cam input,
#counters_3 .cam input,
#move_to .cam input,
#move_to_2 .cam input,
#counters .cam2 input,
#counters_2 .cam2 input,
#counters_3 .cam2 input,
#move_to .cam2 input,
#move_to_2 .cam2 input,
#counters .proj input,
#counters_2 .proj input,
#move_to .proj input {
#counters_3 .proj input,
#move_to .proj input,
#move_to_2 .proj input,
#counters .proj2 input,
#counters_2 .proj2 input,
#counters_3 .proj2 input,
#move_to .proj2 input,
#move_to_2 .proj2 input {
background: rgba(255, 255, 255, 0.05);
color: #fff;
padding: 6px 12px;
@ -767,44 +1076,147 @@ button:focus {
}
#counters .cam input.changed,
#counters_2 .cam input.changed,
#counters_3 .cam input.changed,
#move_to .cam input.changed,
#move_to_2 .cam input.changed,
#counters .cam2 input.changed,
#counters_2 .cam2 input.changed,
#counters_3 .cam2 input.changed,
#move_to .cam2 input.changed,
#move_to_2 .cam2 input.changed,
#counters .proj input.changed,
#counters_2 .proj input.changed,
#move_to .proj input.changed {
#counters_3 .proj input.changed,
#move_to .proj input.changed,
#move_to_2 .proj input.changed,
#counters .proj2 input.changed,
#counters_2 .proj2 input.changed,
#counters_3 .proj2 input.changed,
#move_to .proj2 input.changed,
#move_to_2 .proj2 input.changed {
color: #DAE035;
}
#counters .cam,
#counters_2 .cam,
#move_to .cam {
#counters_3 .cam,
#move_to .cam,
#move_to_2 .cam,
#counters .cam2,
#counters_2 .cam2,
#counters_3 .cam2,
#move_to .cam2,
#move_to_2 .cam2 {
float: left;
}
#counters .proj,
#counters_2 .proj,
#move_to .proj {
#counters_3 .proj,
#move_to .proj,
#move_to_2 .proj,
#counters .proj2,
#counters_2 .proj2,
#counters_3 .proj2,
#move_to .proj2,
#move_to_2 .proj2 {
float: right;
}
#move_to {
#counters.projectors .proj,
#counters.projectors .proj2 {
width: 25%;
}
#counters.projectors .proj label,
#counters.projectors .proj2 label {
line-height: 34px;
font-size: 18px;
}
#counters.projectors .proj input,
#counters.projectors .proj2 input {
width: 90%;
}
#counters.cameras .cam,
#counters.cameras .cam2 {
width: 25%;
}
#counters.cameras .cam label,
#counters.cameras .cam2 label {
line-height: 34px;
font-size: 18px;
}
#counters.cameras .cam input,
#counters.cameras .cam2 input {
width: 90%;
}
#move_to,
#move_to_2 {
margin-top: 20px;
}
#move_to .cam > div,
#move_to .proj > div {
#move_to_2 .cam > div,
#move_to .cam2 > div,
#move_to_2 .cam2 > div,
#move_to .proj > div,
#move_to_2 .proj > div,
#move_to .proj2 > div,
#move_to_2 .proj2 > div {
width: 294px;
margin: 0 auto;
}
#move_to .cam label,
#move_to .proj label {
#move_to_2 .cam label,
#move_to .cam2 label,
#move_to_2 .cam2 label,
#move_to .proj label,
#move_to_2 .proj label,
#move_to .proj2 label,
#move_to_2 .proj2 label {
font-size: 18px;
}
#move_to .cam input,
#move_to .proj input {
#move_to_2 .cam input,
#move_to .cam2 input,
#move_to_2 .cam2 input,
#move_to .proj input,
#move_to_2 .proj input,
#move_to .proj2 input,
#move_to_2 .proj2 input {
display: inline-block;
width: 206px;
}
#move_to .cam button,
#move_to .proj button {
#move_to_2 .cam button,
#move_to .cam2 button,
#move_to_2 .cam2 button,
#move_to .proj button,
#move_to_2 .proj button,
#move_to .proj2 button,
#move_to_2 .proj2 button {
padding: 7px 16px;
float: right;
}
#move_to > .proj2,
#move_to_2 > .proj2 {
float: right;
}
.cam2,
.proj2,
.black {
display: none;
}
.cam2 > *,
.proj2 > *,
.black > * {
visibility: hidden;
}
.cam2.on,
.proj2.on,
.black.on {
display: block;
}
.cam2.on > *,
.proj2.on > *,
.black.on > * {
visibility: visible;
}
#overlay {
position: fixed;
top: 0;
@ -829,6 +1241,21 @@ button:focus {
color: #fff;
text-shadow: 1px 1px 2px #000;
}
#spinnerCancel {
display: none;
position: absolute;
z-index: 2000000000;
left: 50%;
top: 50%;
text-align: center;
margin-left: -40%;
margin-top: 120px;
width: 80%;
}
#spinnerCancel .btn {
margin: 0 auto;
background: rgba(80, 80, 80, 0.4);
}
.cp-app {
position: relative !important;
border-radius: 0px !important;

View File

@ -1,107 +1,197 @@
{
"version" : "2.0.0",
"ext_port" : 1111,
"profiles" : {
"mcopy" : {
"label" : "Default mcopy profile",
"cam" : {
"time" : 850,
"delay" : 50,
"momentary" : 0
},
"proj" : {
"time" : 1400,
"delay" : 50,
"momentary" : 0
},
"black" : {
"before" : 0,
"after" : 0
}
},
"jk103" : {
"label" : "JK103",
"cam" : {
"time" : 600,
"delay" : 50,
"momentary" : 240
},
"proj" : {
"time" : 950,
"delay" : 50,
"momentary" : 240
},
"black" : {
"before" : 0,
"after" : 0
}
},
"jk_original" : {
"label" : "JK45 profile",
"cam" : {
"time" : 750,
"delay" : 50,
"momentary" : 300
},
"proj" : {
"time" : 1300,
"delay" : 50,
"momentary" : 300
},
"black" : {
"before" : 250,
"after" : 250
}
},
"intval3" : {
"label" : "INTVAL3",
"cam" : {
"time" : 630,
"delay" : 50,
"momentary" : 0
}
}
},
"arduino" : {
"baud" : 57600,
"board" : "uno",
"serialDelay" : 20,
"sequenceDelay" : 100,
"cam" : {
"time" : 850,
"delay" : 50,
"momentary" : 300
},
"proj" : {
"time" : 1300,
"delay" : 50,
"momentary" : 300
},
"black" : {
"before" : 250,
"after" : 250
},
"cmd" : {
"debug" : "d",
"connect": "i",
"light" : "l",
"camera" : "c",
"projector" : "p",
"black" : "b",
"cam_forward" : "e",
"cam_backward" : "f",
"proj_forward" : "g",
"proj_backward" : "h",
"proj_identifier" : "j",
"cam_identifier" : "k",
"mcopy_identifier" : "m",
"cam_timed" : "n",
"proj_identifier" : "j",
"cam_identifier" : "k",
"light_identifier" : "o",
"proj_light_identifier" : "q",
"proj_cam_light_identifier" : "r",
"proj_cam_identifier" : "s"
}
}
}
"version": "1.8.104",
"ext_port": 1111,
"profiles": {
"mcopy": {
"label": "Default mcopy profile",
"cam": {
"time": 850,
"delay": 50,
"momentary": 0
},
"proj": {
"time": 1400,
"delay": 50,
"momentary": 0
},
"black": {
"before": 100,
"after": 100
},
"light": false
},
"jk103": {
"label": "JK103",
"cam": {
"time": 600,
"delay": 50,
"momentary": 240
},
"proj": {
"time": 950,
"delay": 50,
"momentary": 240
},
"black": {
"before": 0,
"after": 0
},
"light": false
},
"jk_original": {
"label": "JK45 profile",
"cam": {
"time": 750,
"delay": 50,
"momentary": 300
},
"proj": {
"time": 1300,
"delay": 50,
"momentary": 300
},
"black": {
"before": 250,
"after": 250
},
"light": false
},
"intval3": {
"label": "INTVAL3",
"cam": {
"time": 630,
"delay": 50,
"momentary": 0
},
"light": false
},
"jk_mono": {
"label": "MONO's JK",
"cam": {
"time": 750,
"delay": 50,
"momentary": 300
},
"proj": {
"time": 1300,
"delay": 50,
"momentary": 300
},
"light": false,
"projector_second": true
},
"oxberry": {
"label": "Oxberry",
"cam": {
"time": 550,
"delay": 50,
"momentary": 130
},
"proj": {
"time": 1340,
"delay": 50,
"momentary": 300
},
"light": false
},
"norris": {
"label": "Norris",
"cam": {
"time": 650,
"delay": 50,
"momentary": 130
},
"light": false
}
},
"cmd": {
"camera_forward": "CF",
"camera_backward": "CB",
"projector_forward": "PF",
"projector_backward": "PB",
"black_forward": "BF",
"black_backward": "BB",
"camera_second_forward": "C2F",
"camera_second_backward": "C2B",
"cameras_forward": "CCF",
"cameras_backward": "CCB",
"camera_forward_camera_second_backward": "CFCB",
"camera_backward_camera_second_forward": "CBCF",
"projector_second_forward": "P2F",
"projector_second_backward": "P2B",
"projectors_forward": "PPF",
"projectors_backward": "PPB",
"projector_forward_projector_second_backward": "PFPB",
"projector_backward_projector_second_forward": "PBPF",
"pause": "PA",
"alert": "AL"
},
"arduino": {
"baud": 57600,
"board": "uno",
"serialDelay": 20,
"sequenceDelay": 100,
"cam": {
"time": 850,
"delay": 50,
"momentary": 300
},
"proj": {
"time": 1300,
"delay": 50,
"momentary": 300
},
"black": {
"before": 250,
"after": 250
},
"cmd": {
"debug": "d",
"connect": "i",
"light": "l",
"camera": "c",
"projector": "p",
"black": "b",
"camera_forward": "e",
"camera_backward": "f",
"projector_forward": "g",
"projector_backward": "h",
"projector_identifier": "j",
"camera_identifier": "k",
"mcopy_identifier": "m",
"camera_timed": "n",
"light_identifier": "o",
"projector_light_identifier": "q",
"projector_camera_light_identifier": "r",
"projector_camera_identifier": "s",
"projector_second_identifier": "t",
"projectors_identifier": "d",
"projector_second_forward": "u",
"projector_second_backward": "v",
"projector_second": "w",
"projectors": "x",
"camera_second_identifier": "y",
"cameras_identifier": "a",
"camera_second_forward": "1",
"camera_second_backward": "2",
"camera_second": "3",
"cameras": "4",
"camera_projectors_identifier": "5",
"cameras_projector_identifier": "6",
"cameras_projectors_identifier": "7",
"capper_identifier": "C",
"camera_capper_identifier": "8",
"camera_capper_projector_identifier": "9",
"camera_capper_projectors_identifier": "0",
"capper_on": "A",
"capper_off": "B",
"takeup_forward": "D",
"takeup_backward": "F",
"error": "E",
"camera_exposure": "G",
"state": "H",
"home": "I",
"offset": "O"
}
}
}

View File

@ -13,6 +13,16 @@
body.meter {
background: rgb(117, 117, 117);
}
body.meter #img,
body.meter #can {
display: none;
}
body.image #can{
display: none;
}
body.image #img {
display: block;
}
#img {
position: absolute;
/*background-image: url(".../img/background.jpg");*/
@ -30,8 +40,9 @@
background: #fff;
display: none;
position: fixed;
left: 0;
top: 0;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
}
#can.show{
display: block;
@ -45,61 +56,158 @@
</canvas>
<script>
'use strict';
const { remote, ipcRenderer } = require('electron')
async function setImage (src) {
return new Promise(async (resolve, reject) => {
//let img = new Image()
let img = document.getElementById('img')
let body = document.querySelector('body')
if (body.classList.contains('meter')) {
body.classList.remove('meter')
}
img.style.backgroundImage = `url('${src}')`;
//img.onload = () => {
//document.body.appendChild(img)
//return resolve(img)
//}
//img.onerror = reject
//img.src = src
const { ipcRenderer } = require('electron')
const remote = require('@electron/remote')
let imgTmp;
function delay (ms) {
return new Promise((resolve) => {
return setTimeout(resolve, ms)
})
}
async function setMeter () {
let body = document.querySelector('body')
if (!body.classList.contains('meter')) {
body.classList.add('meter')
}
async function setImage (src) {
return new Promise(async (resolve, reject) => {
imgTmp = new Image()
let img = document.getElementById('img')
let body = document.querySelector('body')
body.className = ''
body.classList.add('image')
imgTmp.onload = function () {
img.style.backgroundImage = `url('${src}')`
return resolve(src)
}
imgTmp.src = src
})
}
async function setGrid () {
function setBlank () {
let img = document.getElementById('img')
img.style.background = ''
img.style.backgroundUrl = ''
img.style.backgroundColor = 'black'
}
async function onMeter () {
console.log('meter')
const body = document.querySelector('body')
body.className = ''
body.classList.add('meter')
}
async function onFocus () {
console.log('focus')
const can = document.getElementById('can')
const ctx = can.getContext('2d')
const dpr = window.devicePixelRatio || 1
const body = document.querySelector('body')
let ctx;
body.className = ''
if (!can.classList.contains('show')) {
can.classList.add('show')
}
can.width = window.innerWidth
can.height = window.innerHeight
can.width = window.innerWidth * dpr
can.height = window.innerHeight * dpr
can.style.width = `${window.innerWidth}px`
can.style.height = `${window.innerHeight}px`
ctx = can.getContext('2d')
ctx.scale(dpr, dpr)
try{
await drawGrid(can, ctx)
await drawFocus(can, ctx)
} catch (err) {
alert(JSON.stringify(err))
}
}
async function drawGrid (can, ctx) {
async function drawFocus (can, ctx) {
const count = 20
const half = Math.round(count / 2)
const w = can.width
const h = can.height
const dpr = window.devicePixelRatio || 1
const w = can.width / dpr
const h = can.height / dpr
const longest = w >= h ? w * 1.5 : h * 1.5
const opp = Math.tan(360 / (count * 32)) * longest / 10
//console.log(`l: ${longest}`)
//console.log(`${360 / (count * 8)}deg`)
//console.log(`o: ${opp}`)
for (let i = 0; i < count; i++) {
ctx.beginPath()
ctx.moveTo(w / 2, h / 2)
ctx.lineTo((w / 2) + opp, longest)
ctx.lineTo((w / 2) - opp, longest)
ctx.fill()
ctx.translate(w / 2, h / 2);
ctx.rotate((360 / count) * Math.PI / 180)
ctx.translate(- w / 2, -h / 2)
}
}
async function onField (evt, arg) {
console.log('field guide')
const can = document.getElementById('can')
const dpr = window.devicePixelRatio || 1
const screen = window.outerWidth / window.outerHeight
const body = document.querySelector('body')
let ctx
body.className = ''
if (!can.classList.contains('show')) {
can.classList.add('show')
}
if (arg.ratio) {
if (arg.ratio < screen) {
can.width = (window.innerHeight * arg.ratio) * dpr
can.height = window.innerHeight * dpr
} else {
can.width = window.innerWidth * dpr
can.height = (window.innerWidth / arg.ratio) * dpr
}
} else {
can.width = window.innerWidth * dpr
can.height = window.innerHeight * dpr
}
if (arg.ratio) {
if (arg.ratio < screen) {
can.style.width = `${window.innerHeight * arg.ratio}px`
can.style.height = `${window.innerHeight}px`
} else {
can.style.width = `${window.innerWidth}px`
can.style.height = `${window.innerWidth / arg.ratio}px`
}
} else {
can.style.width = `${window.innerWidth}px`
can.style.height = `${window.innerHeight}px`
}
ctx = can.getContext('2d')
ctx.scale(dpr, dpr)
try{
await drawField(can, ctx)
} catch (err) {
alert(JSON.stringify(err))
}
}
// draw a field guide
async function drawField (can, ctx) {
const count = 20
const half = Math.round(count / 2)
const dpr = window.devicePixelRatio || 1
const w = can.width / dpr
const h = can.height / dpr
const wsec = w / count
const hsec= h / count
const hsec = h / count
const spacer = 12
const fontSize = 18
ctx.lineWidth = 2
ctx.moveTo(w / 2, 0)
ctx.lineTo(w / 2, h)
ctx.stroke()
ctx.moveTo(0, h / 2)
ctx.lineTo(w, h / 2)
ctx.stroke()
for (let i = 0; i < count; i++) {
ctx.moveTo(wsec * i, hsec * i)
ctx.lineTo(wsec * i, h - (hsec * i))
@ -108,40 +216,45 @@
ctx.lineTo(w - (wsec * i), hsec * i)
ctx.stroke()
}
ctx.font = '30px Arial'
ctx.lineWidth = 1
ctx.font = `${fontSize}px Arial`
for (let i = 0; i < half; i++) {
ctx.fillText(`${(half - i)}`, (wsec * i) + 15, (h / 2) - 15)
ctx.fillText(`${(half - i)}`, (w - (wsec * i)) - 25, (h / 2) - 15)
ctx.fillText(`${(half - i)}`, (w / 2) + 15, (hsec * i) + 25 )
ctx.fillText(`${(half - i)}`, (w / 2) + 15, (h - (hsec * i)) - 15)
//left count
ctx.fillText(`${(half - i)}`, (wsec * i) + spacer, (h / 2) - spacer)
//right count
ctx.fillText(`${(half - i)}`, (w - (wsec * i)) - (spacer * 2), (h / 2) + (spacer * 2))
//up count
ctx.fillText(`${(half - i)}`, (w / 2) + spacer, (hsec * i) + spacer + (fontSize / 2) )
//down count
ctx.fillText(`${(half - i)}`, (w / 2) - (spacer * 2), (h - (hsec * i)) - spacer)
}
}
async function onDigital (event, arg) {
console.log('called')
if (arg.src) {
if (arg.exposure) {
setBlank()
await delay(10)
}
try {
await setImage(arg.src)
await setImage(arg.src)
} catch (err) {
console.error(err)
}
} else if (arg.meter) {
try {
await setMeter()
} catch (err) {
console.error(err)
}
} else if (arg.grid) {
try {
await setGrid()
} catch (err) {
console.error(err)
if (arg.exposure) {
await delay(arg.exposure)
setBlank()
}
ipcRenderer.send('display_load', { src : arg.src })
}
return event.returnValue = true
}
async function onEscape (evt) {
let isEscape = false
let win
evt = evt || window.event
if ('key' in evt) {
@ -149,12 +262,16 @@
} else {
isEscape = (evt.keyCode == 27)
}
if (isEscape) {
win = remote.getCurrentWindow()
win.close()
}
}
ipcRenderer.on('display', onDigital)
ipcRenderer.on('field', onField)
ipcRenderer.on('meter', onMeter)
ipcRenderer.on('focus', onFocus)
document.onkeydown = onEscape
</script>
</body>

12
app/entitlements.plist Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.debugger</key>
<true/>
</dict>
</plist>

View File

@ -18,17 +18,17 @@ var scripts = [
'./src/index.js'
];
gulp.task('js', function () {
gulp.task('js', () => {
'use strict';
return gulp.src(scripts)
.pipe(concat('app.js'))
.pipe(gulp.dest('./js/'));
});
gulp.task('less', function () {
gulp.task('less', () => {
return gulp.src('./less/app.less')
.pipe(less())
.pipe(gulp.dest('./css'));
});
gulp.task('default', ['js', 'less']);
gulp.task('default', gulp.parallel('js', 'less'));

View File

@ -18,37 +18,61 @@
<div id="counters">
<div class="cam">
<label>CAMERA</label>
<input type="number" id="seq_cam_count" class="count" value="00000" onchange="gui.counterFormat(this, mcopy.state.camera.pos);" onblur="gui.updateCam(this);" />
<input type="number" id="seq_cam_count" class="count" value="00000" onchange="gui.counterFormat(this, cam.pos);" onblur="gui.updateCam(this);" />
</div>
<div class="cam2">
<label>CAMERA</label>
<input type="number" id="seq_cam_2_count" class="count" value="00000" onchange="gui.counterFormat(this, cam.second.pos);" onblur="gui.updateCam2(this);" />
</div>
<div class="proj2">
<label>PROJECTOR 2</label>
<input type="number" id="seq_proj_2_count" class="count" value="00000" onchange="gui.counterFormat(this, proj.second.pos);" onblur="gui.updateProj2(this);" />
</div>
<div class="proj">
<label>PROJECTOR</label>
<input type="number" id="seq_proj_count" class="count" value="00000" onchange="gui.counterFormat(this, mcopy.state.projector.pos);" onblur="gui.updateProj(this);" />
<input type="number" id="seq_proj_count" class="count" value="00000" onchange="gui.counterFormat(this, proj.pos);" onblur="gui.updateProj(this);" />
</div>
</div>
<div id="seq_scroll">
<div id="sequence">
<div id="cam_forward" class="row" y="0"></div>
<div id="proj_forward" class="row" y="1"></div>
<div id="cam_backward" class="row spacer" y="0"></div>
<div id="proj_backward" class="row" y="1"></div>
<div id="camera_forward" class="row" y="0"></div>
<div id="camera_second_forward" class="row cam2" y="2"></div>
<div id="projector_forward" class="row" y="1"></div>
<div id="projector_second_forward" class="row proj2" y="3"></div>
<div id="camera_backward" class="row spacer" y="0"></div>
<div id="camera_second_backward" class="row cam2" y="2"></div>
<div id="projector_backward" class="row" y="1"></div>
<div id="projector_second_backward" class="row proj2" y="3"></div>
<div id="black" class="row black"></div>
<div id="light_set" class="row spacer"></div>
<div id="numbers" class="row"></div>
</div>
<div id="seq_labels">
<div><span>CAM </span><i class="fa fa-plus"></i></div>
<div><span>PRO </span><i class="fa fa-plus"></i></div>
<div class="cam2"><span>CAM2 </span><i class="fa fa-plus"></i></div>
<div><span>PROJ </span><i class="fa fa-plus"></i></div>
<div class="proj2"><span>PROJ2 </span><i class="fa fa-plus"></i></div>
<div class="spacer"><span>CAM </span><i class="fa fa-minus"></i></div>
<div><span>PRO </span><i class="fa fa-minus"></i></div>
<div class="cam2"><span>CAM2 </span><i class="fa fa-minus"></i></div>
<div><span>PROJ </span><i class="fa fa-minus"></i></div>
<div class="proj2"><span>PROJ2 </span><i class="fa fa-minus"></i></div>
<div class="black"><span>BLANK </span><i class="fa fa-times"></i></div>
<div class="spacer"><span>LIGHT</span></div>
</div>
</div>
<div id="actions">
<button id="seq_run" onclick="seq.init();">RUN</button>
<button id="seq_stop" onclick="seq.stop(true);">STOP</button>
<button id="seq_clear" onclick="gui.grid.clear();">CLEAR</button>
<button id="seq_plus24" onclick="gui.grid.plus_24();">+ 24</button>
<button id="seq_run" onclick="seq.start();">START</button>
<button id="seq_pause" onclick="seq.pause();">STOP</button>
<button id="seq_stop" onclick="seq.stop();">STOP</button>
<button id="seq_clear" onclick="grid.clear();">CLEAR</button>
<button id="seq_plus24" onclick="grid.plus_24();">+ 24</button>
<button id="seq_mscript" onclick="mse.mscript.fromSequence();">TO SCRIPT</button>
<input id="seq_scroll_state" type="number" min="0" value="00000" />
</div>
@ -58,11 +82,17 @@
<div class="cam_end">Camera end: <span>00000</span></div>
<div class="proj_end">Projector end: <span>00000</span></div>
</div>
<div id="seq_loop">
<div id="seq_loop_wrap">
<h3>LOOPS</h3>
<input type="number" min="1" id="seq_loop" value="00001" onchange="this.value = gui.fmtZero(this.value, 6); gui.grid.loopChange(this);"/>
<input type="number" min="1" id="seq_loop" value="00001" onchange="this.value = gui.fmtZero(this.value, 6); seq.setLoops(parseInt(this.value));"/>
<div id="loop_current"></div>
</div>
<div id="seq_progress">
<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;">
<span class="sr-only">0% Complete</span>
</div>
</div>
</div>
<div id="script" class="screen">
<textarea id="editor"></textarea>
@ -76,73 +106,87 @@
</footer>
</div>
<div id="controls" class="screen">
<div id="counters_2">
<div id="counters_2" class="clearfix">
<div class="cam">
<label>CAMERA</label>
<input type="number" id="seq_cam_count_2" class="count" value="00000" onchange="gui.counterFormat(this, mcopy.state.camera.pos);" onblur="gui.updateCam(this);" />
<input type="number" id="seq_cam_count_2" class="count" value="00000" onchange="gui.counterFormat(this, cam.pos);" onblur="gui.updateCam(this);" />
</div>
<div class="proj">
<label>PROJECTOR</label>
<input type="number" id="seq_proj_count_2" class="count" value="00000" onchange="gui.counterFormat(this, mcopy.state.projector.pos);" onblur="gui.updateProj(this);" />
<input type="number" id="seq_proj_count_2" class="count" value="00000" onchange="gui.counterFormat(this, proj.pos);" onblur="gui.updateProj(this);" />
</div>
</div>
<div id="move_to">
<div id="move_to" class="clearfix">
<div class="cam">
<!--<label>MOVE TO</label>-->
<div>
<input type="number" id="move_cam_to" class="count" value="00000" onchange="gui.counterFormat(this, this.value);" />
<button id="move_cam_to_go" onclick="return cmd.cam_to();">GO TO</button>
<button id="move_cam_to_go" onclick="return cmd.camera_to();">GO TO</button>
</div>
</div>
<div class="proj">
<!--<label>MOVE TO</label>-->
<div>
<input type="number" id="move_proj_to" class="count" value="00000" onchange="gui.counterFormat(this, this.value);"/>
<button id="move_proj_to_go" onclick="return cmd.proj_to();">GO TO</button>
<button id="move_proj_to_go" onclick="return cmd.projector_to();">GO TO</button>
</div>
</div>
</div>
<div id="buttons" class="clearfix">
<div>
<div>
<button id="cmd_cam_forward" onclick="cmd.cam_forward(light.color);" class="cmd fwd">
<button id="cmd_cam_forward" onclick="cmd.camera_forward(light.color);" class="cmd fwd">
<i class="fa fa-video-camera"></i>
CAMERA +1
<i class="fa fa-step-forward"></i>
</button>
</div>
<div>
<button id="cmd_cam_backward" onclick="cmd.cam_backward(light.color);" class="cmd bwd">
<button id="cmd_cam_backward" onclick="cmd.camera_backward(light.color);" class="cmd bwd">
<i class="fa fa-video-camera"></i>
CAMERA -1
<i class="fa fa-step-backward"></i>
</button>
</div>
<div>
<div class="hide">
<button id="cmd_black_forward" onclick="cmd.black_forward();" class="cmd fwd">
<i class="fa fa-times-circle"></i>
BLANK +1
<i class="fa fa-step-forward"></i>
</button>
</div>
<div>
<div class="hide">
<button id="cmd_black_backward" onclick="cmd.black_backward();" class="cmd bwd">
<i class="fa fa-times-circle"></i>
BLANK -1
<i class="fa fa-step-backward"></i>
</button>
</div>
<div class="hide">
<button id="cmd_capper_on" onclick="cmd.capper_on();" class="cmd capper">
<i class="fa fa-times-circle"></i>
CAPPER ON
<i class="fa fa-eye"></i>
</button>
</div>
<div class="hide">
<button id="cmd_capper_off" onclick="cmd.capper_off();" class="cmd capper active">
<i class="fa fa-eye"></i>
CAPPER OFF
<i class="fa fa-eye"></i>
</button>
</div>
</div>
<div>
<div>
<button id="cmd_proj_forward" onclick="cmd.proj_forward();" class="cmd fwd">
<button id="cmd_proj_forward" onclick="cmd.projector_forward();" class="cmd fwd">
<i class="fa fa-film"></i>
PROJECTOR +1
<i class="fa fa-step-forward"></i>
</button>
</div>
<div>
<button id="cmd_proj_backward" onclick="cmd.proj_backward();" class="cmd bwd">
<button id="cmd_proj_backward" onclick="cmd.projector_backward();" class="cmd bwd">
<i class="fa fa-film"></i>
PROJECTOR -1
<i class="fa fa-step-backward"></i>
@ -150,9 +194,80 @@
</div>
</div>
</div>
<footer>
<div id="log"></div>
</footer>
<div id="counters_3" class="clearfix">
<div class="cam2">
<label>CAMERA 2</label>
<input type="number" id="seq_cam_2_count_2" class="count" value="00000" onchange="gui.counterFormat(this, cam.second.pos);" onblur="gui.updateCam2(this);" />
</div>
<div class="proj2">
<label>PROJECTOR 2</label>
<input type="number" id="seq_proj_2_count_2" class="count" value="00000" onchange="gui.counterFormat(this, proj.second.pos);" onblur="gui.updateProj2(this);" />
</div>
</div>
<div id="move_to_2" class="clearfix">
<div class="cam2">
<!--<label>MOVE TO</label>-->
<div>
<input type="number" id="move_cam_to_2" class="count" value="00000" onchange="gui.counterFormat(this, this.value);" />
<button id="move_cam_to_go_2" onclick="return cmd.camera_second_to();">GO TO</button>
</div>
</div>
<div class="proj2">
<!--<label>MOVE TO</label>-->
<div>
<input type="number" id="move_proj_to_2" class="count" value="00000" onchange="gui.counterFormat(this, this.value);"/>
<button id="move_proj_to_go_2" onclick="return cmd.projector_second_to();">GO TO</button>
</div>
</div>
</div>
<div id="buttons_2" class="clearfix">
<div class="cam2">
<div>
<button id="cmd_cam2_forward" onclick="cmd.camera_second_forward(light.color);" class="cmd fwd">
<i class="fa fa-video-camera"></i>
CAMERA 2 +1
<i class="fa fa-step-forward"></i>
</button>
</div>
<div>
<button id="cmd_cam2_backward" onclick="cmd.camera_second_backward(light.color);" class="cmd bwd">
<i class="fa fa-video-camera"></i>
CAMERA 2 -1
<i class="fa fa-step-backward"></i>
</button>
</div>
<div>
<button id="cmd_black2_forward" onclick="cmd.black2_forward();" class="cmd fwd">
<i class="fa fa-times-circle"></i>
BLANK +1
<i class="fa fa-step-forward"></i>
</button>
</div>
<div>
<button id="cmd_black2_backward" onclick="cmd.black2_backward();" class="cmd bwd">
<i class="fa fa-times-circle"></i>
BLANK -1
<i class="fa fa-step-backward"></i>
</button>
</div>
</div>
<div class="proj2">
<div>
<button id="cmd_proj2_forward" onclick="cmd.projector_second_forward();" class="cmd fwd">
<i class="fa fa-film"></i>
PROJECTOR 2 +1
<i class="fa fa-step-forward"></i>
</button>
</div>
<div>
<button id="cmd_proj2_backward" onclick="cmd.projector_second_backward();" class="cmd bwd">
<i class="fa fa-film"></i>
PROJECTOR 2 -1
<i class="fa fa-step-backward"></i>
</button>
</div>
</div>
</div>
</div>
<div id="light" class="screen">
<div id="colors-tabs"></div>
@ -245,8 +360,54 @@
</div>
</footer>
</div>
<div id="settings" class="screen">
<div id="video" class="screen">
<div>
<div>
<div id="path_bar">
<input id="filmout_file" type="text" onclick="filmout.selectFile();" readonly />
<button onclick="$('#projector_type_digital').click();">USE FILE</button>
<select id="filmout_displays"></select>
</div>
<div id="filmout_preview_wrap">
<div id="filmout_monitor">
<div id="filmout"></div>
</div>
</div>
<div id="filmout_stats">
<div id="filmout_stats_video">
<h3>File</h3>
<div id="filmout_stats_video_name"></div>
<div id="filmout_stats_video_size"></div>
<div id="filmout_stats_video_frames"></div>
</div>
<div id="filmout_stats_monitor">
<h3>Monitor</h3>
<div id="filmout_stats_monitor_size"></div>
<div id="filmout_stats_monitor_aspect"></div>
<div id="filmout_stats_monitor_scale"></div>
</div>
</div>
<div id="filmout_position_wrap">
<div>
<button id="filmout_rewind" title="Rewind 1 Frame" onclick="filmout.rewind();"><</button>
<input id="filmout_position" class="count" type="number" value="00000" onchange="gui.counterFormat(this, this.value);" />
<button id="filmout_advance" title="Advance 1 Frame" onclick="filmout.advance();">></button>
</div>
</div>
<div id="filmout_functions">
<div>
<button id="filmout_preview" onclick="filmout.preview();">PREVIEW</button>
<button id="filmout_meter" onclick="filmout.meter();">METER</button>
<button id="filmout_focus" onclick="filmout.focus();">FOCUS</button>
<button id="filmout_field" onclick="filmout.field();">FIELD GUIDE</button>
</div>
</div>
</div>
</div>
</div>
<div id="settings" class="screen">
<div class="left">
<div>
<h4>Devices</h4>
<select id="devices">
@ -262,8 +423,8 @@
<input type="radio" id="projector_type_arduino" name="projector_type" value="arduino" checked="checked" />
</div>
<div class="spacer">
<input type="text" id="digital" name="digital" placeholder="Digital file" onclick="devices.digitalSelect();" data-file="" readonly />
<input type="radio" id="projector_type" name="projector_type" value="video" onclick="devices.digital();" />
<input type="text" id="digital" name="digital" placeholder="Digital file" onclick="filmout.selectFile();" data-file="" readonly />
<input type="radio" id="projector_type_digital" name="projector_type" value="video" onclick="filmout.useFile();" />
</div>
<div>
<h4>Camera</h4>
@ -276,6 +437,13 @@
<input type="text" id="intval" name="intval" placeholder="INTVAL3 URL"/>
<input type="radio" id="camera_type_intval" name="camera_type" value="intval" onclick="devices.intval();" />
</div>
<div class="spacer">
<input type="text" id="processing" name="processing" placeholder="PROCESSING URL" />
<input type="radio" id="camera_type_processing" name="camera_type" value="processing" onclick="devices.processing();" />
</div>
<div>
<div id="version"></div>
</div>
<div>
<h4>Light</h4>
<select id="light_device">
@ -289,15 +457,32 @@
</select>
</div>
</div>
<div class="right">
<div class="spacer"></div>
<div class="proj_time">
<h4>Projector Time (ms)</h4>
<input type="number" readonly id="proj_time" value="0" />
<button id="submit_proj_time" class="hide"></button>
</div>
<div class="cam_time">
<h4>Camera Time (ms)</h4>
<input type="number" readonly id="cam_time" value="0" />
<button id="submit_cam_time" class="hide" onclick="cam.exposure($('#cam_time').val());"></button>
</div>
</div>
</div>
</div>
<div id="overlay" onclick="gui.overlay(false);gui.spinner(false);"></div>
<div id="spinner">
<div id="spinnerMsg"></div>
<div id="spinnerCancel">
<div class="btn" style="margin:auto;" onclick="seq.cancel();">Cancel</div>
</div>
<div id="spinnerProgress" class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;">
<span class="sr-only">0% Complete</span>
</div>
</div>
</div>
<script src="./js/app.js"></script>

View File

@ -2472,77 +2472,64 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
},k.push(["lab",J])}).call(this);
//fgnass.github.com/spin.js#v2.0.1
!function(a,b){"object"==typeof exports?module.exports=b():"function"==typeof define&&define.amd?define(b):a.Spinner=b()}(this,function(){"use strict";function a(a,b){var c,d=document.createElement(a||"div");for(c in b)d[c]=b[c];return d}function b(a){for(var b=1,c=arguments.length;c>b;b++)a.appendChild(arguments[b]);return a}function c(a,b,c,d){var e=["opacity",b,~~(100*a),c,d].join("-"),f=.01+c/d*100,g=Math.max(1-(1-a)/b*(100-f),a),h=j.substring(0,j.indexOf("Animation")).toLowerCase(),i=h&&"-"+h+"-"||"";return l[e]||(m.insertRule("@"+i+"keyframes "+e+"{0%{opacity:"+g+"}"+f+"%{opacity:"+a+"}"+(f+.01)+"%{opacity:1}"+(f+b)%100+"%{opacity:"+a+"}100%{opacity:"+g+"}}",m.cssRules.length),l[e]=1),e}function d(a,b){var c,d,e=a.style;for(b=b.charAt(0).toUpperCase()+b.slice(1),d=0;d<k.length;d++)if(c=k[d]+b,void 0!==e[c])return c;return void 0!==e[b]?b:void 0}function e(a,b){for(var c in b)a.style[d(a,c)||c]=b[c];return a}function f(a){for(var b=1;b<arguments.length;b++){var c=arguments[b];for(var d in c)void 0===a[d]&&(a[d]=c[d])}return a}function g(a,b){return"string"==typeof a?a:a[b%a.length]}function h(a){this.opts=f(a||{},h.defaults,n)}function i(){function c(b,c){return a("<"+b+' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">',c)}m.addRule(".spin-vml","behavior:url(#default#VML)"),h.prototype.lines=function(a,d){function f(){return e(c("group",{coordsize:k+" "+k,coordorigin:-j+" "+-j}),{width:k,height:k})}function h(a,h,i){b(m,b(e(f(),{rotation:360/d.lines*a+"deg",left:~~h}),b(e(c("roundrect",{arcsize:d.corners}),{width:j,height:d.width,left:d.radius,top:-d.width>>1,filter:i}),c("fill",{color:g(d.color,a),opacity:d.opacity}),c("stroke",{opacity:0}))))}var i,j=d.length+d.width,k=2*j,l=2*-(d.width+d.length)+"px",m=e(f(),{position:"absolute",top:l,left:l});if(d.shadow)for(i=1;i<=d.lines;i++)h(i,-2,"progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)");for(i=1;i<=d.lines;i++)h(i);return b(a,m)},h.prototype.opacity=function(a,b,c,d){var e=a.firstChild;d=d.shadow&&d.lines||0,e&&b+d<e.childNodes.length&&(e=e.childNodes[b+d],e=e&&e.firstChild,e=e&&e.firstChild,e&&(e.opacity=c))}}var j,k=["webkit","Moz","ms","O"],l={},m=function(){var c=a("style",{type:"text/css"});return b(document.getElementsByTagName("head")[0],c),c.sheet||c.styleSheet}(),n={lines:12,length:7,width:5,radius:10,rotate:0,corners:1,color:"#000",direction:1,speed:1,trail:100,opacity:.25,fps:20,zIndex:2e9,className:"spinner",top:"50%",left:"50%",position:"absolute"};h.defaults={},f(h.prototype,{spin:function(b){this.stop();{var c=this,d=c.opts,f=c.el=e(a(0,{className:d.className}),{position:d.position,width:0,zIndex:d.zIndex});d.radius+d.length+d.width}if(e(f,{left:d.left,top:d.top}),b&&b.insertBefore(f,b.firstChild||null),f.setAttribute("role","progressbar"),c.lines(f,c.opts),!j){var g,h=0,i=(d.lines-1)*(1-d.direction)/2,k=d.fps,l=k/d.speed,m=(1-d.opacity)/(l*d.trail/100),n=l/d.lines;!function o(){h++;for(var a=0;a<d.lines;a++)g=Math.max(1-(h+(d.lines-a)*n)%l*m,d.opacity),c.opacity(f,a*d.direction+i,g,d);c.timeout=c.el&&setTimeout(o,~~(1e3/k))}()}return c},stop:function(){var a=this.el;return a&&(clearTimeout(this.timeout),a.parentNode&&a.parentNode.removeChild(a),this.el=void 0),this},lines:function(d,f){function h(b,c){return e(a(),{position:"absolute",width:f.length+f.width+"px",height:f.width+"px",background:b,boxShadow:c,transformOrigin:"left",transform:"rotate("+~~(360/f.lines*k+f.rotate)+"deg) translate("+f.radius+"px,0)",borderRadius:(f.corners*f.width>>1)+"px"})}for(var i,k=0,l=(f.lines-1)*(1-f.direction)/2;k<f.lines;k++)i=e(a(),{position:"absolute",top:1+~(f.width/2)+"px",transform:f.hwaccel?"translate3d(0,0,0)":"",opacity:f.opacity,animation:j&&c(f.opacity,f.trail,l+k*f.direction,f.lines)+" "+1/f.speed+"s linear infinite"}),f.shadow&&b(i,e(h("#000","0 0 4px #000"),{top:"2px"})),b(d,b(i,h(g(f.color,k),"0 0 1px rgba(0,0,0,.1)")));return d},opacity:function(a,b,c){b<a.childNodes.length&&(a.childNodes[b].style.opacity=c)}});var o=e(a("group"),{behavior:"url(#default#VML)"});return!d(o,"transform")&&o.adj?i():j=d(o,"animation"),h});
const mcopy = {};
mcopy.cfg = require('./data/cfg.json');
const { remote, ipcRenderer } = require('electron');
const dialog = require('electron').remote.dialog;
const remote = require('@electron/remote');
const { ipcRenderer } = require('electron');
const { dialog } = remote;
const notifier = require('node-notifier');
const fs = require('fs');
const uuid = require('uuid');
const uuid = require('uuid').v4;
const moment = require('moment');
const path = require('path');
const humanizeDuration = require('humanize-duration');
const PACKAGE = require('./package.json');
const cfg = require('./data/cfg.json');
const gui = require('./lib/ui');
const grid = require('./lib/ui/grid.js');
const light = require('./lib/ui/light.js');
const proj = require('./lib/ui/proj.js');
const cam = require('./lib/ui/cam.js');
const nav = require('./lib/ui/nav.js');
const seq = require('./lib/ui/seq.js');
const cmd = require('./lib/ui/cmd.js');
const log = require('./lib/ui/log.js');
const devices = require('./lib/ui/devices.js');
const filmout = require('./lib/ui/filmout.js');
const mse = require('./lib/ui/mscript.js');
const capper = require('./lib/ui/capper.js');
const timing = require('./lib/ui/timing.js');
const Mscript = require('./lib/mscript');
const { delay } = require('./lib/delay');
const alertObj = require('./lib/ui/alert.js');
let log;
/******
State shared by ALL interfaces
*******/
mcopy.state = {
version : '2.0.0', //use for file compatibility check
camera : {
pos : 0,
direction: true
},
projector : {
pos : 0,
direction: true
},
sequence : {
size : 24,
arr : ['CF', 'PF'],
light : ['255,255,255', ''],
cmd : {
camera: mcopy.cfg.arduino.cmd.camera,
projector: mcopy.cfg.arduino.cmd.projector,
cam_direction: mcopy.cfg.arduino.cmd.cam_direction,
cam_direction: mcopy.cfg.arduino.cmd.proj_direction
},
pads: {
cam_forward: 'CF',
proj_forward : 'PF',
black_forward : 'BF',
cam_backward: 'CB',
proj_backward : 'PB',
black_backward : 'BB',
light_set : 'L'
}
}
version : PACKAGE.version //use for file compatibility check
};
//
function init () {
async function init () {
'use strict';
log = await require('log')({})
nav.init();
gui.grid.init();
gui.init();
grid.init();
mse.mscript.init();
mse.console.init();
log.init();
devices.init();
filmout.init();
light.init();
proj.init();
cam.init();
seq.init();
capper.init();
alertObj.init();
timing.init();
};

View File

@ -8,11 +8,13 @@
@import "./scroll.less";
@import "./settings.less";
@import "./mscript.less";
@import "./filmout.less";
#log{
position: fixed;
width: 100%;
height: @FOOTER_H;
.hide {
display: none;
}
.show {
display: block;
}
#screens{
@ -77,9 +79,13 @@
#counters,
#counters_2,
#move_to{
#counters_3,
#move_to,
#move_to_2{
.cam,
.proj{
.cam2,
.proj,
.proj2{
width: 50%;
padding-bottom: 10px;
label{
@ -101,18 +107,52 @@
}
}
}
.cam{
.cam,
.cam2{
float: left;
}
.proj{
.proj,
.proj2{
float: right;
}
}
#move_to{
#counters{
&.projectors{
.proj,
.proj2{
width: 25%;
label{
line-height: 34px;
font-size: 18px;
}
input{
width: 90%;
}
}
}
&.cameras{
.cam,
.cam2{
width: 25%;
label{
line-height: 34px;
font-size: 18px;
}
input{
width: 90%;
}
}
}
}
#move_to,
#move_to_2{
margin-top: 20px;
.cam,
.proj{
.cam2,
.proj,
.proj2{
> div {
width: 294px;
margin: 0 auto;
@ -129,6 +169,25 @@
float: right;
}
}
> .proj2{
float: right;
}
}
.cam2,
.proj2,
.black{
display : none;
> * {
visibility: hidden;
}
&.on {
display: block;
> * {
visibility: visible;
}
}
}
#overlay{
@ -158,6 +217,22 @@
text-shadow: 1px 1px 2px #000;
}
#spinnerCancel{
display:none;
position: absolute;
z-index: 2000000000;
left: 50%;
top: 50%;
text-align: center;
margin-left: -40%;
margin-top: 120px;
width: 80%;
.btn{
margin: 0 auto;
background: rgba(80,80,80, 0.4);
}
}
.cp-app{
position: relative !important;
border-radius: 0px !important;

View File

@ -1,8 +1,12 @@
#buttons{
#buttons,
#buttons_2{
> div{
width: 50%;
float: left;
}
.proj2 {
float: right !important;
}
}
.cmd{
@ -38,6 +42,10 @@
background: @BACKWARD;
border-color: @BACKWARD;
}
&.capper{
background: white;
color: @BG;
}
i{
color: @BG;
}

117
app/less/filmout.less Normal file
View File

@ -0,0 +1,117 @@
#video{
input,select{
.button();
display: inline-block;
padding: 6px 12px;
font-size: 21px;
min-width: 300px;
&.active{
border-color: @SELECTED;
color: @SELECTED;
}
}
button, select {
padding: 9px 16px 8px;
}
}
#path_bar{
padding: 5px;
height: 50px;
input{
float: left;
}
button{
float: left;
margin-left: 5px;
}
select{
line-height: 41px;
height: 37px;
margin-right: 5px;
float: right;
box-sizing: content-box;
padding: 0 0 0 8px;
}
}
#filmout_file {
}
#filmout_monitor{
display: none;
border: 2px solid white;
box-sizing: border-box;
height: 360px;
margin: 0 auto;
position: relative;
&.on{
display: block;
}
}
#filmout_preview_wrap {
background: #000;
width: 100%;
height: 360px;
}
#filmout {
position: absolute;
background-repeat:no-repeat;
background-size: contain;
background-position: center;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: block;
opacity: 0;
&.on {
opacity: 1.0;
}
}
#filmout_position_wrap{
padding-top: 5px;
height: 50px;
input{
margin-right: 5px;
margin-left: 5px;
width: 308px !important;
box-sizing: border-box;
}
button, input{
float: left;
}
> div{
width: 425px;
margin: 0 auto;
}
}
#filmout_functions{
padding-top: 5px;
> div{
width: 425px;
margin: 0 auto;
}
}
#filmout_stats_video,
#filmout_stats_monitor{
width: 150px;
position: absolute;
//background: grey;
padding: 10px 5px;
text-align: center;
h3{
font-size: 20px;
margin: 16px 0 3px;
text-align: center;
}
}
#filmout_stats_video{
left: 5px;
}
#filmout_stats_monitor{
right: 5px;
}

View File

@ -28,6 +28,7 @@
float: right;
width: 90px;
margin-right: 60px;
height: 32px;
}
}
#seq_stats{
@ -45,7 +46,7 @@
.timing{
}
}
#seq_loop{
#seq_loop_wrap{
width: 40%;
float: left;
padding: 0 0 0 56px;
@ -64,43 +65,75 @@
}
}
#sequencer{
}
#sequence{
width: 970px;
padding-bottom: 21px;
padding-left: 70px;
#cam_forward,
#proj_forward,
padding-left: 92px;
#camera_forward,
#camera_second_forward,
#projector_forward,
#projector_second_forward,
#black_forward{
clear: both;
input[type=checkbox]{
border: 2px solid @FORWARD;
&:checked{
background: @FORWARD;
//background: radial-gradient(circle at 25px 25px, #00C4A0, #343434);
}
}
>div{
color: @FORWARD;
}
}
#cam_backward,
#proj_backward,
#camera_backward,
#camera_second_backward,
#projector_backward,
#projector_second_backward,
#black_backward{
clear: both;
input[type=checkbox]{
border: 2px solid @BACKWARD;
&:checked{
background: @BACKWARD;
//background: radial-gradient(circle at 25px 25px, #AB1A25, #343434);
}
}
>div{
color: @BACKWARD;
}
}
#camera_second_forward,
#projector_second_forward {
input[type=checkbox]{
border: 2px solid @FORWARD + @SECOND;
&:checked{
background: @FORWARD + @SECOND;
}
}
>div{
color: @FORWARD + @SECOND;
}
}
#camera_second_backward,
#projector_second_backward{
input[type=checkbox]{
border: 2px solid @BACKWARD + @SECOND;
&:checked{
background: @BACKWARD + @SECOND;
}
}
>div{
color: @BACKWARD + @SECOND;
}
}
#black{
input[type=checkbox]{
&:checked{
background: white;
}
}
}
input[type=checkbox]{
-webkit-appearance: none;
-moz-appearance: none;
@ -116,6 +149,10 @@
display: inline-block;
box-sizing: border-box;
cursor: pointer;
&.disabled{
cursor: not-allowed;
border-color: rgb(100, 100, 100);
}
}
.L{
display: inline-block;
@ -164,10 +201,10 @@
.monospace();
background-color: #272b30;
position: absolute;
top: 115px;
top: 113px;
padding-top: 2px;
padding-bottom: 15px;
width: 54px;
width: 75px;
div{
height: 43px;
line-height: 35px;
@ -177,11 +214,33 @@
display: inline-block;
margin-right: 5px;
}
i.fa{
right: 3px;
position: absolute;
margin-top: 10px;
}
}
#loop_current{
margin-top: 54px;
width: 121px;
font-family: 'Menlo', monospace;
font-size: 22px;
margin-top: 13px;
margin-right: 50px;
width: 93px;
text-align: center;
position: relative;
float: right;
color: @SELECTED;
}
}
#seq_pause{
display: none;
}
#seq_progress{
width: 100%;
height: 15px;
position: fixed;
left: 0;
bottom: 0;
}

View File

@ -1,25 +1,61 @@
#settings{
h4{
margin-bottom: 1px;
}
> div{
width: 300px;
margin: 0 auto;
&.left{
float: left;
padding-left: 30px;
}
&.right{
float: right;
padding-right: 30px;
input[type=number] {
min-width: 200px;
width: 200px;
}
input[readonly]{
cursor: not-allowed;
}
.spacer{
height: 62px;
}
.proj_time{
height: 111px;
}
.cam_time{
height: 111px;
}
& > div {
width: 270px;
}
}
}
> div > div{
width: 360px;
}
input[type=text], select{
input[type=text],
input[type=number],
select{
.button();
display: inline-block;
padding: 6px 12px;
font-size: 21px;
min-width: 300px;
max-width: 300px;
&.active{
border-color: @SELECTED;
color: @SELECTED;
}
}
input[type=text]{
width: 200px;
}
button{
margin-top: -1px;
float: right;
margin-top: 0px;
float: right;
padding: 8px 16px 9px;
}
input[type=radio]{
float: right;
@ -28,4 +64,15 @@
.spacer{
margin-top: 10px;
}
#version{
position: absolute;
right: 20px;
bottom: 10px;
z-index: 1000;
height: 14px;
width: auto;
font-size: 14px;
line-height: 14px;
color: #999;
}
}

View File

@ -5,6 +5,7 @@
@FORWARD: #00C4A0;
@BACKWARD: #AB1A25;
@SELECTED: #DAE035;
@SECOND : rgb(20, 20, 20);
@SEQ: #3C3636;
@SCRIPT: rgb(39, 40, 34);

1
app/lib/alert/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export {};

58
app/lib/alert/index.js Normal file
View File

@ -0,0 +1,58 @@
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
/* class representing alert functionality */
class Alert {
constructor(ui) {
this.id = 'alert';
this.cb = null;
this.ui = ui;
this.init();
}
/**
*
**/
async init() {
const Log = require('log');
this.log = await Log({ label: this.id });
this.ipc = require('electron').ipcMain;
this.listen();
}
/**
*
**/
listen() {
this.ipc.on(this.id, this.listener.bind(this));
}
/**
*
**/
async listener(event, arg) {
if (this.cb !== null) {
try {
await this.cb(arg.state, arg.id);
}
catch (err) {
this.log.error(err);
}
}
event.returnValue = true;
}
/**
*
**/
async start(cmd) {
const start = +new Date();
const msg = (cmd + '').replace('ALERT', '').replace('Alert', '').replace('alert', '').trim();
this.ui.send(this.id, { msg });
return new Promise(function (resolve, reject) {
this.cb = function () {
const ms = (+new Date()) - start;
return resolve(ms);
};
}.bind(this));
}
}
module.exports = function (ui) {
return new Alert(ui);
};
//# sourceMappingURL=index.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/alert/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAIb,4CAA4C;AAE5C,MAAM,KAAK;IAOV,YAAc,EAAQ;QAJd,OAAE,GAAY,OAAO,CAAA;QACrB,OAAE,GAAc,IAAI,CAAA;QAI3B,IAAI,CAAC,EAAE,GAAG,EAAE,CAAA;QACZ,IAAI,CAAC,IAAI,EAAE,CAAA;IACZ,CAAC;IAED;;QAEI;IACI,KAAK,CAAC,IAAI;QACjB,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;QAC1B,IAAI,CAAC,GAAG,GAAG,MAAM,GAAG,CAAC,EAAE,KAAK,EAAG,IAAI,CAAC,EAAE,EAAE,CAAC,CAAA;QACzC,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,OAAO,CAAA;QACtC,IAAI,CAAC,MAAM,EAAE,CAAA;IACd,CAAC;IAED;;QAEI;IACI,MAAM;QACb,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IAC/C,CAAC;IAED;;QAEI;IACI,KAAK,CAAC,QAAQ,CAAE,KAAW,EAAE,GAAS;QAC7C,IAAI,IAAI,CAAC,EAAE,KAAK,IAAI,EAAE;YACrB,IAAI;gBACH,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC,CAAA;aAChC;YAAC,OAAO,GAAG,EAAE;gBACb,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;aACnB;SACD;QACD,KAAK,CAAC,WAAW,GAAG,IAAI,CAAA;IACzB,CAAC;IAED;;QAEI;IACG,KAAK,CAAC,KAAK,CAAE,GAAY;QAC/B,MAAM,KAAK,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAY,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;QACrG,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAA;QAC9B,OAAO,IAAI,OAAO,CAAC,UAAU,OAAkB,EAAE,MAAiB;YACjE,IAAI,CAAC,EAAE,GAAG;gBACT,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,GAAG,KAAK,CAAC;gBACjC,OAAO,OAAO,CAAC,EAAE,CAAC,CAAC;YACpB,CAAC,CAAA;QACF,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACf,CAAC;CACD;AAED,MAAM,CAAC,OAAO,GAAG,UAAU,EAAQ;IAClC,OAAO,IAAI,KAAK,CAAC,EAAE,CAAC,CAAC;AACtB,CAAC,CAAA"}

71
app/lib/arduino/Readme.md Normal file
View File

@ -0,0 +1,71 @@
<a name="Arduino"></a>
## Arduino
Class representing the arduino communication features
**Kind**: global class
* [Arduino](#Arduino)
* [.enumerate()](#Arduino+enumerate) ⇒ <code>Promise</code>
* [.sendAsync(device, cmd)](#Arduino+sendAsync) ⇒ <code>Promise</code>
* [.writeAsync(device, str)](#Arduino+writeAsync) ⇒ <code>Promise</code>
* [.openArduino(device)](#Arduino+openArduino) ⇒ <code>Promise</code>
* [.closeArduino(device)](#Arduino+closeArduino) ⇒ <code>Promise</code>
<a name="Arduino+enumerate"></a>
### arduino.enumerate() ⇒ <code>Promise</code>
Enumerate all connected devices that might be Arduinos
**Kind**: instance method of [<code>Arduino</code>](#Arduino)
**Returns**: <code>Promise</code> - Resolves after enumerating
<a name="Arduino+sendAsync"></a>
### arduino.sendAsync(device, cmd) ⇒ <code>Promise</code>
Send a command to an Arduino using async/await
**Kind**: instance method of [<code>Arduino</code>](#Arduino)
**Returns**: <code>Promise</code> - Resolves after sending
| Param | Type | Description |
| --- | --- | --- |
| device | <code>string</code> | Arduino identifier |
| cmd | <code>string</code> | Single character command to send |
<a name="Arduino+writeAsync"></a>
### arduino.writeAsync(device, str) ⇒ <code>Promise</code>
Send a string to an Arduino using async/await
**Kind**: instance method of [<code>Arduino</code>](#Arduino)
**Returns**: <code>Promise</code> - Resolves after sending
| Param | Type | Description |
| --- | --- | --- |
| device | <code>string</code> | Arduino identifier |
| str | <code>string</code> | String to send |
<a name="Arduino+openArduino"></a>
### arduino.openArduino(device) ⇒ <code>Promise</code>
Connect to an Arduino using async/await
**Kind**: instance method of [<code>Arduino</code>](#Arduino)
**Returns**: <code>Promise</code> - Resolves after opening
| Param | Type | Description |
| --- | --- | --- |
| device | <code>string</code> | Arduino identifier |
<a name="Arduino+closeArduino"></a>
### arduino.closeArduino(device) ⇒ <code>Promise</code>
Close a connection to an Arduino using async/await
**Kind**: instance method of [<code>Arduino</code>](#Arduino)
**Returns**: <code>Promise</code> - Resolves after closing
| Param | Type | Description |
| --- | --- | --- |
| device | <code>string</code> | Arduino identifier |

1
app/lib/arduino/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export {};

View File

@ -1,327 +1,601 @@
'use strict'
const SerialPort = require('serialport')
const Readline = SerialPort.parsers.Readline
const exec = require('child_process').exec
const parser = new Readline('')
const newlineRe = new RegExp('\n', 'g')
const returnRe = new RegExp('\r', 'g')
let eventEmitter
const mcopy = {}
async function delay (ms) {
return new Promise(resolve => {
return setTimeout(resolve, ms)
})
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
/**
* 2023-07-16 Clarification
*
* Previous versions of this script intermingled and even
* swapped the usage of the terms 'serial' and 'device'.
* From here on out, the terms will be used as such:
*
* serial - a hardware address of a serial port
* device - common name of a type of mcopy device (eg. camera,
* projector, light) that is aliased to a serial port
*
**/
//import Log = require('log');
const delay_1 = require("delay");
const { SerialPort } = require('serialport');
const { ReadlineParser } = require('@serialport/parser-readline');
const exec = require('child_process').exec;
const parser = new ReadlineParser({ delimiter: '\r\n' });
const newlineRe = new RegExp('\n', 'g');
const returnRe = new RegExp('\r', 'g');
let eventEmitter;
let cfg;
let arduino;
const KNOWN = [
'/dev/tty.usbmodem1a161',
'/dev/tty.usbserial-A800f8dk',
'/dev/tty.usbserial-A900cebm',
'/dev/tty.usbmodem1a131',
'/dev/tty.usbserial-a900f6de',
'/dev/tty.usbmodem1a141',
'/dev/ttyACM0',
'COM3'
];
/**
* Class representing the arduino communication features
**/
class Arduino {
constructor(errorState) {
this.path = {};
this.known = KNOWN;
this.alias = {};
this.serial = {};
this.hasState = {};
this.baud = 57600;
this.queue = {};
this.timer = 0;
this.locks = {};
this.stateStr = {};
this.errorState = errorState;
this.init();
}
async init() {
const Log = require('log');
this.log = await Log({ label: 'arduino' });
this.keys = Object.keys(cfg.arduino.cmd);
this.values = this.keys.map(key => cfg.arduino.cmd[key]);
}
/**
* Enumerate all connected devices that might be Arduinos
*
* @async
* @returns {Promise} Resolves after enumerating
**/
async enumerate() {
let ports;
let matches = [];
try {
ports = await SerialPort.list();
}
catch (err) {
throw err;
}
this.log.info('Available ports:');
this.log.info(ports.map((port) => { return port.path; }).join(','));
ports.forEach((port) => {
if (this.known.indexOf(port.path) !== -1) {
matches.push(port.path);
}
else if ((port.manufacturer + '').toLowerCase().indexOf('arduino') !== -1) {
matches.push(port.path);
}
else if ((port.path + '').toLowerCase().indexOf('usbserial') !== -1) {
matches.push(port.path);
}
else if ((port.path + '').toLowerCase().indexOf('usbmodem') !== -1) {
matches.push(port.path);
}
else if ((port.path + '').toLowerCase().indexOf('ttyusb') !== -1) {
matches.push(port.path);
}
});
if (matches.length === 0) {
throw new Error('No USB devices found');
}
else if (matches.length > 0) {
return matches;
}
}
/**
* Send a command to an Arduino using async/await
*
* @param {string} device The Arduino device identifier
* @param {string} cmd Single character command to send
*
* @async
* @returns {Promise} Resolves after sending
**/
async sendAsync(device, cmd) {
return new Promise((resolve, reject) => {
this.log.info(`sendAsync ${cmd} -> ${device}`);
this.queue[cmd] = (ms) => {
return resolve(ms);
};
this.log.info(`Device: ${device}`);
return this.serial[this.alias[device]].write(cmd, (err, results) => {
if (err) {
//this.log.error(err)
return reject(err);
}
});
});
}
/**
* Sends a command to the specified Arduino and waits for a response.
* Handles the communication lock to prevent sending multiple commands simultaneously.
* Emits an 'arduino_send' event after successfully sending the command.
*
* @async
* @param {string} device - The Arduino device identifier.
* @param {string} cmd - The command to be sent to the Arduino.
* @returns {Promise<boolean|string>} Returns 'false' if the communication is locked, otherwise returns the response from the device.
* @throws {Error} Throws an error if the sendAsync method encounters an error.
**/
async send(device, cmd) {
const serial = this.alias[device];
let ms;
this.log.info(`send ${cmd} -> ${device}`);
if (this.isLocked(serial)) {
this.log.warn(`send Serial ${serial} is locked`);
return null;
}
this.timer = new Date().getTime();
this.lock(serial);
await (0, delay_1.delay)(cfg.arduino.serialDelay);
try {
ms = await this.sendAsync(device, cmd);
}
catch (e) {
return this.log.error(e);
}
this.unlock(serial);
await eventEmitter.emit('arduino_send', cmd);
return ms;
}
/**
* Sends a string to the specified Arduino.
* Handles different types of devices, including fake devices for testing purposes.
* Waits for a specified delay before sending the string.
*
* @async
* @param {string} device - The Arduino device identifier.
* @param {string} str - The string to be sent to the Arduino.
* @returns {Promise<boolean|string>} Returns 'true' if the string is sent successfully, otherwise returns an error message.
* @throws {Error} Throws an error if the writeAsync method encounters an error.
**/
async sendString(device, str) {
let writeSuccess;
await (0, delay_1.delay)(cfg.arduino.serialDelay);
if (typeof this.serial[this.alias[device]].fake !== 'undefined'
&& this.serial[this.alias[device]].fake) {
return this.serial[this.alias[device]].string(str);
}
else {
this.log.info(`sendString ${str} -> ${device}`);
try {
writeSuccess = await this.writeAsync(device, str);
}
catch (e) {
return this.log.error(e);
}
this.unlock(this.alias[device]);
return writeSuccess;
}
}
/**
*
**/
async stateAsync(device, confirm = false) {
const cmd = cfg.arduino.cmd.state;
const serial = confirm ? this.alias['connect'] : this.alias[device];
return new Promise((resolve, reject) => {
this.queue[cmd] = (state) => {
this.stateStr[device] = state;
if (confirm) {
this.hasState[device] = true;
this.log.info(`Device ${device} supports state [${state}]`);
}
return resolve(state);
};
if (confirm) {
setTimeout(function () {
if (typeof this.queue[cmd] !== 'undefined') {
delete this.queue[cmd];
this.hasState[device] = false;
this.log.info(`Device ${device} does not support state`);
return resolve(null);
}
}.bind(this), 1000);
}
this.log.info(`stateAsync ${cmd} -> ${device}`);
return this.serial[serial].write(cmd, (err, results) => {
if (err) {
//this.log.error(err)
return reject(err);
}
});
});
}
/**
*
**/
async state(device, confirm = false) {
const serial = confirm ? this.alias['connect'] : this.alias[device];
let results;
if (this.isLocked(serial)) {
this.log.warn(`state Serial ${serial} is locked`);
return null;
}
this.timer = new Date().getTime();
this.lock(serial);
await (0, delay_1.delay)(cfg.arduino.serialDelay);
try {
results = await this.stateAsync(device, confirm);
}
catch (e) {
return this.log.error(e);
}
this.unlock(serial);
await eventEmitter.emit('arduino_state', cfg.arduino.cmd.state);
return results;
}
/**
* Send a string to an Arduino using async/await
*
* @param {string} device Arduino identifier
* @param {string} str String to send
*
* @returns {Promise} Resolves after sending
**/
async writeAsync(device, str) {
return new Promise((resolve, reject) => {
this.serial[this.alias[device]].write(str, function (err, results) {
if (err) {
return reject(err);
}
return resolve(results);
});
});
}
/**
* Handles the end of communication with the Arduino.
* Calculates the time taken for the communication, executes the callback,
* and emits an 'arduino_end' event. Handles errors and stray data received.
*
* @param {string} serial - The serial address of the Arduino device.
* @param {string} data - The data received from the Arduino.
* @returns {any} The time taken for the communication in milliseconds.
**/
end(serial, data) {
const end = new Date().getTime();
const ms = end - this.timer;
let complete;
//this.log.info(`end ${serial} -> ${data}`)
if (this.queue[data] !== undefined) {
this.unlock(serial);
complete = this.queue[data](ms); //execute callback
eventEmitter.emit('arduino_end', data);
delete this.queue[data];
}
else if (data[0] === cfg.arduino.cmd.state) {
//this.log.info(`end serial -> ${serial}`)
this.unlock(serial);
complete = this.queue[cfg.arduino.cmd.state](data);
eventEmitter.emit('arduino_end', data);
delete this.queue[cfg.arduino.cmd.state];
return data;
}
else if (data[0] === cfg.arduino.cmd.error) {
this.log.error(`Received error from device ${serial}`);
this.unlock(serial);
this.error(serial, data);
//error state
//stop sequence
//throw error in ui
}
else {
this.log.info('Received stray "' + data + '"'); //silent to user
}
return ms;
}
error(serial, data) {
this.log.error("ERROR", data);
}
/**
* Associates an alias with an Arduinos serial address.
* Used to map multi-purpose devices onto the same serial connection.
*
* @param {string} device - The serial number of the target Arduino.
* @param {string} serial - The alias to be associated with the target device.
**/
aliasSerial(device, serial) {
//this.log.info(`Making "${serial}" an alias of ${device}`)
this.alias[device] = serial;
}
/**
* Connects to an Arduino using its serial number.
* Sets up the SerialPort instance and path for the device, and handles data communication.
* Handles opening the connection and emitting 'arduino_end' or 'confirmEnd' events upon receiving data.
*
* @async
* @param {string} device - The device identifier (common name).
* @param {string} serial - The serial address of the target Arduino (e.g., COM port on Windows).
* @param {function} confirm - A callback function to be executed upon receiving confirmation data.
* @returns {Promise<string>} Resolves with the device path if the connection is successful.
* @throws {Error} Rejects with an error message if the connection fails.
**/
async connect(device, serial, confirm) {
//this.log.info(`connect device ${device}`)
//this.log.info(`connect serial ${serial}`)
return new Promise(async (resolve, reject) => {
let connectSuccess;
this.path[device] = serial;
this.aliasSerial(device, serial);
this.serial[serial] = new SerialPort({
path: serial,
autoOpen: false,
baudRate: cfg.arduino.baud,
parser
});
this.unlock(serial);
try {
connectSuccess = await this.openArduino(device);
}
catch (e) {
this.log.error(`Failed to open ${device} @ ${serial}: ` + e);
return reject(e);
}
this.log.info(`Opened connection with ${this.path[device]} as ${device}`);
if (!confirm) {
this.serial[this.alias[device]].on('data', async (data) => {
let d = data.toString('utf8');
d = d.replace(newlineRe, '').replace(returnRe, '');
return this.end(serial, d);
});
}
else {
this.serial[this.alias[device]].on('data', async (data) => {
let d = data.toString('utf8');
d = d.replace(newlineRe, '').replace(returnRe, '');
return await this.confirmEnd(d);
});
}
return resolve(this.path[serial]);
});
}
/**
* Handles the confirmation data received from an Arduino.
* Executes the confirmation callback function if the received data is present in the list of expected values.
*
* @param {string} data - The data received from the Arduino.
**/
confirmEnd(data) {
if (this.values.indexOf(data) !== -1 && typeof this.confirmExec === 'function') {
this.confirmExec(null, data);
this.confirmExec = {};
this.unlock(this.alias['connect']);
}
else if (data[0] === cfg.arduino.cmd.state) {
this.queue[cfg.arduino.cmd.state](data);
delete this.queue[cfg.arduino.cmd.state];
this.unlock(this.alias['connect']);
}
}
/**
* Verifies the connection to an Arduino by sending a connect command.
* The confirmation callback checks if the received data matches the expected connect command.
*
* @async
* @returns {Promise<boolean>} Resolves with 'true' if the connection is verified successfully.
* @throws {Error} Rejects with an error message if the connection verification fails.
**/
async verify() {
return new Promise(async (resolve, reject) => {
const device = 'connect';
let writeSuccess;
this.confirmExec = function (err, data) {
if (data === cfg.arduino.cmd.connect) {
return resolve(true);
}
else {
return reject('Wrong data returned');
}
};
await (0, delay_1.delay)(cfg.arduino.serialDelay);
try {
writeSuccess = await this.sendAsync(device, cfg.arduino.cmd.connect);
}
catch (e) {
return reject(e);
}
return resolve(writeSuccess);
});
}
/**
* Distinguishes the type of Arduino connected.
* Sends a command to the device to identify its type and resolves the promise with the received type.
*
* @async
* @returns {Promise<string>} Resolves with the type of the connected Arduino-based device.
* @throws {Error} Rejects with an error message if the distinguish operation fails.
**/
async distinguish() {
return new Promise(async (resolve, reject) => {
const device = 'connect';
let writeSuccess;
let type;
this.confirmExec = function (err, data) {
if (data === cfg.arduino.cmd.projector_identifier) {
type = 'projector';
}
else if (data === cfg.arduino.cmd.camera_identifier) {
type = 'camera';
}
else if (data === cfg.arduino.cmd.light_identifier) {
type = 'light';
}
else if (data === cfg.arduino.cmd.projector_light_identifier) {
type = 'projector,light';
}
else if (data === cfg.arduino.cmd.projector_camera_light_identifier) {
type = 'projector,camera,light';
}
else if (data === cfg.arduino.cmd.projector_camera_identifier) {
type = 'projector,camera';
}
else if (data === cfg.arduino.cmd.projector_second_identifier) {
type = 'projector_second';
}
else if (data === cfg.arduino.cmd.projectors_identifier) {
type = 'projector,projector_second';
}
else if (data === cfg.arduino.cmd.camera_second_identifier) {
type = 'camera_second';
}
else if (data === cfg.arduino.cmd.cameras_identifier) {
type = 'camera,camera_second';
}
else if (data === cfg.arduino.cmd.camera_projectors_identifier) {
type = 'camera,projector,projector_second';
}
else if (data === cfg.arduino.cmd.cameras_projector_identifier) {
type = 'camera,camera_second,projector';
}
else if (data === cfg.arduino.cmd.cameras_projectors_identifier) {
type = 'camera,camera_second,projector,projector_second';
}
else if (data === cfg.arduino.cmd.capper_identifier) {
type = 'capper';
}
else if (data === cfg.arduino.cmd.camera_capper_identifier) {
type = 'camera,capper';
}
else if (data === cfg.arduino.cmd.camera_capper_projector_identifier) {
type = 'camera,capper,projector';
}
else if (data === cfg.arduino.cmd.camera_capper_projectors_identifier) {
type = 'camera,capper,projector,projector_second';
}
return resolve(type);
};
await (0, delay_1.delay)(cfg.arduino.serialDelay);
try {
writeSuccess = await this.sendAsync(device, cfg.arduino.cmd.mcopy_identifier);
this.log.info(writeSuccess);
}
catch (e) {
return reject(e);
}
});
}
/**
* Closes the connection to an Arduino.
*
* @async
* @returns {Promise<boolean>} Resolves with 'true' if the connection is closed successfully.
* @throws {Error} Throws an error if the closeArduino method encounters an error.
**/
async close() {
const device = 'connect';
let closeSuccess;
try {
closeSuccess = await this.closeArduino(device);
}
catch (e) {
throw e;
}
return closeSuccess;
}
/**
* Establishes a fake connection to an Arduino for testing purposes.
* Creates a fake SerialPort instance with custom write and string methods.
*
* @async
* @param {string} serial - The device identifier of the fake Arduino.
* @returns {Promise<boolean>} Resolves with 'true' if the fake connection is established successfully.
**/
async fakeConnect(device) {
const serial = '/dev/fake';
this.aliasSerial(device, serial);
this.serial[serial] = {
write: async function (cmd, cb) {
const t = {
c: cfg.arduino.cam.time + cfg.arduino.cam.delay,
p: cfg.arduino.proj.time + cfg.arduino.proj.delay,
A: 180,
B: 180
};
let timeout = t[cmd];
if (typeof timeout === 'undefined')
timeout = 10;
arduino.timer = +new Date();
await (0, delay_1.delay)(timeout);
arduino.end(serial, cmd);
return cb();
},
string: async function (str) {
//do nothing
return true;
},
fake: true
};
//this.log.info('Connected to fake arduino! Not real! Does not exist!')
return true;
}
/**
* Connect to an Arduino using async/await
*
* @param {string} device Arduino identifier
*
* @returns {Promise} Resolves after opening
**/
async openArduino(device) {
return new Promise((resolve, reject) => {
return this.serial[this.alias[device]].open((err) => {
if (err) {
return reject(err);
}
return resolve(true);
});
});
}
/**
* Close a connection to an Arduino using async/await
*
* @param {string} device Arduino identifier
*
* @returns {Promise} Resolves after closing
**/
async closeArduino(device) {
return new Promise((resolve, reject) => {
return this.serial[this.alias[device]].close((err) => {
if (err) {
return reject(err);
}
return resolve(true);
});
});
}
lock(serial) {
//this.log.info(`Locked serial ${serial}`)
this.locks[serial] = true;
}
unlock(serial) {
//this.log.info(`Unlocked serial ${serial}`)
this.locks[serial] = false;
}
isLocked(serial) {
return typeof this.locks[serial] !== 'undefined' && this.locks[serial] === true;
}
}
async function send (device, cmd) {
return new Promise ((resolve, reject) => {
mcopy.arduino.queue[cmd] = (ms) => {
return resolve(ms)
}
return mcopy.arduino.serial[device].write(cmd, (err, results) => {
if (err) {
//console.error(err)
return reject(err)
}
//
})
})
}
async function write (device, str) {
return new Promise ((resolve, reject) => {
mcopy.arduino.serial[device].write(str, function (err, results) {
if (err) {
return reject(err)
}
//console.log('sent: ' + str)
return resolve(results)
})
})
}
async function open (device) {
return new Promise((resolve, reject) => {
return mcopy.arduino.serial[device].open(error => {
if (error) {
return reject(error)
}
return resolve(true)
})
})
}
async function close (device) {
return new Promise((resolve, reject) => {
return mcopy.arduino.serial[device].close((err) => {
if (err) {
return reject(err)
}
return resolve(true)
})
})
}
/******
Arduino handlers
*******/
mcopy.arduino = {
path : {},
known: [
'/dev/tty.usbmodem1a161',
'/dev/tty.usbserial-A800f8dk',
'/dev/tty.usbserial-A900cebm',
'/dev/tty.usbmodem1a131',
'/dev/tty.usbserial-a900f6de',
'/dev/tty.usbmodem1a141',
'/dev/ttyACM0',
'COM3'
],
alias : {
},
serial : {
connect : {},
projector : {},
camera : {},
light : {}
},
baud : 57600,
queue : {},
timer : 0,
lock : false
}
mcopy.arduino.enumerate = async function () {
return new Promise( (resolve, reject) => {
return SerialPort.list((err, ports) => {
let matches = []
if (err) {
return reject(err)
}
ports.forEach(port => {
if (mcopy.arduino.known.indexOf(port.comName) !== -1) {
matches.push(port.comName)
} else if ((port.manufacturer + '').toLowerCase().indexOf('arduino') !== -1) {
matches.push(port.comName)
}
})
if (matches.length === 0) {
return reject('No USB devices found');
} else if (matches.length > 0) {
return resolve(matches)
}
})
})
}
//commands which respond to a sent char
mcopy.arduino.send = async function (serial, cmd, res) {
const device = mcopy.arduino.alias[serial]
let results
if (mcopy.arduino.lock) {
return false
}
mcopy.arduino.lock = true
await delay(mcopy.cfg.arduino.serialDelay)
try {
results = await send(device, cmd)
} catch (e) {
return console.error(e)
}
mcopy.arduino.lock = false
mcopy.arduino.timer = new Date().getTime()
return await eventEmitter.emit('arduino_send', cmd)
}
//send strings, after char triggers firmware to accept
mcopy.arduino.string = async function (serial, str) {
const device = mcopy.arduino.alias[serial]
let writeSuccess
await delay(mcopy.cfg.arduino.serialDelay)
if (typeof mcopy.arduino.serial[device].fake !== 'undefined'
&& mcopy.arduino.serial[device].fake) {
return mcopy.arduino.serial[device].string(str)
} else {
try {
writeSuccess = await write(device, str)
} catch (e) {
return console.error(e)
}
return writeSuccess
}
}
//respond with same char over serial when done
mcopy.arduino.end = async function (data) {
const end = new Date().getTime()
const ms = end - mcopy.arduino.timer
let complete
if (mcopy.arduino.queue[data] !== undefined) {
mcopy.arduino.lock = false;
//console.log('Command ' + data + ' took ' + ms + 'ms');
complete = mcopy.arduino.queue[data](ms) //execute callback
eventEmitter.emit('arduino_end', data)
delete mcopy.arduino.queue[data]
} else {
//console.log('Received stray "' + data + '"'); //silent to user
}
return complete
};
mcopy.arduino.alias = function (serial, device) {
console.log(`Making "${serial}" an alias of ${device}`)
mcopy.arduino.alias[serial] = device
}
mcopy.arduino.connect = async function (serial, device, confirm) {
return new Promise(async (resolve, reject) => {
let connectSuccess
mcopy.arduino.path[serial] = device;
mcopy.arduino.alias[serial] = device;
mcopy.arduino.serial[device] = new SerialPort(mcopy.arduino.path[serial], {
autoOpen : false,
baudRate: mcopy.cfg.arduino.baud,
parser: parser
})
try {
connectSuccess = await open(device)
} catch (e) {
console.error('failed to open: ' + e)
return reject(e)
}
console.log(`Opened connection with ${mcopy.arduino.path[serial]} as ${serial}`);
if (!confirm) {
mcopy.arduino.serial[device].on('data', async (data) => {
let d = data.toString('utf8')
d = d.replace(newlineRe, '').replace(returnRe, '')
return await mcopy.arduino.end(d)
})
} else {
mcopy.arduino.serial[device].on('data', async (data) => {
let d = data.toString('utf8')
d = d.replace(newlineRe, '').replace(returnRe, '')
return await mcopy.arduino.confirmEnd(d)
})
}
return resolve(mcopy.arduino.path[serial])
})
}
mcopy.arduino.confirmExec = {};
mcopy.arduino.confirmEnd = function (data) {
//console.dir(data)
if (data === mcopy.cfg.arduino.cmd.connect
|| data === mcopy.cfg.arduino.cmd.proj_identifier
|| data === mcopy.cfg.arduino.cmd.cam_identifier
|| data === mcopy.cfg.arduino.cmd.light_identifier
|| data === mcopy.cfg.arduino.cmd.proj_light_identifier
|| data === mcopy.cfg.arduino.cmd.proj_cam_light_identifier
|| data === mcopy.cfg.arduino.cmd.proj_cam_identifier ) {
mcopy.arduino.confirmExec(null, data);
mcopy.arduino.confirmExec = {};
}
}
mcopy.arduino.verify = async function () {
return new Promise(async (resolve, reject) => {
const device = mcopy.arduino.alias['connect']
let writeSuccess
mcopy.arduino.confirmExec = function (err, data) {
if (data === mcopy.cfg.arduino.cmd.connect) {
return resolve(true)
} else {
return reject('Wrong data returned')
}
}
await delay(mcopy.cfg.arduino.serialDelay)
try {
writeSuccess = await send(device, mcopy.cfg.arduino.cmd.connect)
} catch (e) {
return reject(e)
}
return resolve(writeSuccess)
})
}
mcopy.arduino.distinguish = async function () {
return new Promise(async (resolve, reject) => {
const device = mcopy.arduino.alias['connect']
let writeSuccess
let type
mcopy.arduino.confirmExec = function (err, data) {
if (data === mcopy.cfg.arduino.cmd.proj_identifier) {
type = 'projector'
} else if (data === mcopy.cfg.arduino.cmd.cam_identifier) {
type = 'camera'
} else if (data === mcopy.cfg.arduino.cmd.light_identifier) {
type = 'light'
} else if (data === mcopy.cfg.arduino.cmd.proj_light_identifier) {
type = 'projector,light'
} else if (data === mcopy.cfg.arduino.cmd.proj_cam_light_identifier) {
type = 'projector,camera,light'
} else if (data === mcopy.cfg.arduino.cmd.proj_cam_identifier) {
type = 'projector,camera'
}
return resolve(type)
}
await delay(mcopy.cfg.arduino.serialDelay)
try {
writeSuccess = await send(device, mcopy.cfg.arduino.cmd.mcopy_identifier)
} catch (e) {
console.error(e)
return reject(e)
}
})
}
mcopy.arduino.close = async function (callback) {
const device = mcopy.arduino.alias['connect']
let closeSuccess
try {
closeSuccess = await close(device)
} catch (e) {
return console.error(e)
}
return closeSuccess
};
mcopy.arduino.fakeConnect = async function (serial) {
//console.log('Connecting to fake arduino...');
const device = '/dev/fake'
mcopy.arduino.alias[serial] = device
mcopy.arduino.serial[device] = {
write : function (cmd, cb) {
const t = {
c : mcopy.cfg.arduino.cam.time + mcopy.cfg.arduino.cam.delay,
p : mcopy.cfg.arduino.proj.time + mcopy.cfg.arduino.proj.delay
}
let timeout = t[cmd]
let end
if (typeof timeout === 'undefined') timeout = 10
mcopy.arduino.timer = +new Date()
setTimeout(() => {
mcopy.arduino.end(cmd)
return cb()
}, timeout)
},
string : async function (str) {
//do nothing
return true
},
fake : true
};
//console.log('Connected to fake arduino! Not real! Doesn\'t exist!');
return true
}
if (typeof module !== 'undefined' && module.parent) {
module.exports = function (cfg, ee) {
eventEmitter = ee
mcopy.cfg = cfg
return mcopy.arduino
}
}
module.exports = function (c, ee, errorState) {
eventEmitter = ee;
cfg = c;
arduino = new Arduino(errorState);
return arduino;
};
}
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

49
app/lib/cam/Readme.md Normal file
View File

@ -0,0 +1,49 @@
<a name="Camera"></a>
## Camera
class representing camera functions
**Kind**: global class
* [Camera](#Camera)
* [.init()](#Camera+init)
* [.listen()](#Camera+listen)
* [.set()](#Camera+set)
* [.move()](#Camera+move)
* [.exposure()](#Camera+exposure)
* [.connectIntval()](#Camera+connectIntval)
* [.listener()](#Camera+listener)
* [.end()](#Camera+end)
<a name="Camera+init"></a>
### camera.init()
**Kind**: instance method of [<code>Camera</code>](#Camera)
<a name="Camera+listen"></a>
### camera.listen()
**Kind**: instance method of [<code>Camera</code>](#Camera)
<a name="Camera+set"></a>
### camera.set()
**Kind**: instance method of [<code>Camera</code>](#Camera)
<a name="Camera+move"></a>
### camera.move()
**Kind**: instance method of [<code>Camera</code>](#Camera)
<a name="Camera+exposure"></a>
### camera.exposure()
**Kind**: instance method of [<code>Camera</code>](#Camera)
<a name="Camera+connectIntval"></a>
### camera.connectIntval()
**Kind**: instance method of [<code>Camera</code>](#Camera)
<a name="Camera+listener"></a>
### camera.listener()
**Kind**: instance method of [<code>Camera</code>](#Camera)
<a name="Camera+end"></a>
### camera.end()
**Kind**: instance method of [<code>Camera</code>](#Camera)

1
app/lib/cam/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export {};

342
app/lib/cam/index.js Normal file
View File

@ -0,0 +1,342 @@
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
const intval_1 = require("intval");
const processing_1 = require("processing");
const delay_1 = require("delay");
/** class representing camera functions **/
class Camera {
/**
*
**/
constructor(arduino, cfg, ui, filmout, second = false) {
this.state = {
pos: 0,
dir: true,
capepr: false
};
this.arduino = null;
this.intval = null;
this.processing = null;
this.id = 'camera';
this.arduino = arduino;
this.cfg = cfg;
this.ui = ui;
this.filmout = filmout;
if (second)
this.id += '_second';
this.init();
}
/**
*
**/
async init() {
const Log = require('log');
this.log = await Log({ label: this.id });
this.ipc = require('electron').ipcMain;
this.listen();
}
/**
*
**/
listen() {
this.ipc.on(this.id, this.listener.bind(this));
this.ipc.on('intval', this.connectIntval.bind(this));
this.ipc.on('processing', this.connectProcessing.bind(this));
}
/**
*
**/
async set(dir, id) {
let cmd;
let ms;
if (dir) {
cmd = this.cfg.arduino.cmd[`${this.id}_forward`];
}
else {
cmd = this.cfg.arduino.cmd[`${this.id}_backward`];
}
this.state.dir = dir;
if (this.processing) {
try {
ms = await this.processing.setDir(dir);
}
catch (err) {
this.log.error(err);
}
}
else if (this.intval) {
try {
ms = await this.intval.setDir(dir);
}
catch (err) {
this.log.error(err);
}
}
else {
try {
ms = await this.arduino.send(this.id, cmd);
}
catch (err) {
this.log.error(err);
}
}
return await this.end(cmd, id, ms);
}
/**
*
**/
async cap(state, id) {
let cmd;
let ms;
if (state) {
cmd = this.cfg.arduino.cmd[`${this.id}_forward`];
}
else {
cmd = this.cfg.arduino.cmd[`${this.id}_backward`];
}
this.state.capper = state;
try {
ms = await this.arduino.send(this.id, cmd);
}
catch (err) {
this.log.error(err);
}
return await this.end(cmd, id, ms);
}
/**
*
**/
async move(frame, id) {
const cmd = this.cfg.arduino.cmd[this.id];
let ms;
if (this.filmout.state.enabled) {
await this.filmout.start();
}
if (this.processing) {
try {
ms = await this.processing.move();
}
catch (err) {
this.log.error(err);
}
}
else if (this.intval) {
try {
ms = await this.intval.move();
}
catch (err) {
this.log.error(err);
}
}
else {
try {
ms = await this.arduino.send(this.id, cmd);
}
catch (err) {
this.log.error(err);
}
}
if (this.filmout.state.enabled) {
//await delay(100 * 1000);
await this.filmout.end();
}
//this.log.info('Camera move time', { ms });
return this.end(cmd, id, ms);
}
async both(frame, id) {
const cmd = this.cfg.arduino.cmd[id];
let ms;
try {
ms = await this.arduino.send(this.id, cmd);
}
catch (err) {
this.log.error(`Error moving ${this.id}`, err);
}
//this.log.info('Cameras move time', { ms });
return await this.end(cmd, id, ms);
}
/**
*
**/
async exposure(exposure, id) {
const cmd = this.cfg.arduino.cmd.camera_exposure;
const str = `${exposure}`;
const started = +new Date();
let ms;
let confirmState;
let parts;
let confirmExposure;
if (this.intval) {
return this.intval.setExposure(this.id, exposure, (ms) => {
this.ui.send('timing', { c: 'c', ms: exposure });
return this.end(cmd, id, ms);
});
}
else if (this.arduino.hasState[this.id]) {
try {
ms = this.arduino.send(this.id, cmd);
}
catch (err) {
this.log.error('Error sending camera exposure command', err);
}
await (0, delay_1.delay)(1);
try {
ms = await this.arduino.sendString(this.id, str);
}
catch (err) {
this.log.error('Error sending camera exposure string', err);
}
await ms;
await (0, delay_1.delay)(1);
try {
confirmState = await this.arduino.state(this.id, false);
}
catch (err) {
this.log.error(`Error confirming set state`, err);
}
parts = this.arduino.stateStr[this.id].split('G');
if (parts.length > 1) {
parts = parts[1].split('H');
confirmExposure = parseInt(parts[0]);
if (!isNaN(confirmExposure)) {
this.log.info(`Exposure successfully set to ${confirmExposure}ms`);
this.ui.send('timing', { c: 'c', ms: exposure });
}
}
ms = (+new Date()) - started;
return await this.end(cmd, id, ms);
}
return 0;
}
/**
*
**/
async connectIntval(event, arg) {
return new Promise((resolve, reject) => {
if (arg.connect) {
this.intval = new intval_1.Intval(arg.url);
this.processing = null;
this.intval.connect((err, ms, state) => {
if (err) {
this.ui.send('intval', { connected: false });
this.log.info(`Cannot connect to ${arg.url}`, 'INTVAL');
this.intval = null;
}
else {
this.ui.send('intval', { connected: true, url: arg.url, state: state });
this.log.info(`Connected to INTVAL3 @ ${arg.url}`, 'INTVAL');
}
return resolve(true);
});
}
else if (arg.disconnect) {
this.intval = null;
return resolve(false);
}
});
}
/**
*
**/
async connectProcessing(event, arg) {
return new Promise((resolve, reject) => {
this.processing = new processing_1.Processing(arg.url);
this.intval = null;
this.ui.send('processing', { connected: true, url: arg.url });
return resolve(true);
});
}
/**
*
**/
async listener(event, arg) {
if (typeof arg.dir !== 'undefined') {
try {
await this.set(arg.dir, arg.id);
}
catch (err) {
this.log.error(err);
}
}
else if (typeof arg.frame !== 'undefined') {
try {
await this.move(arg.frame, arg.id);
}
catch (err) {
this.log.error(err);
}
}
else if (typeof arg.val !== 'undefined') {
this.state.pos = arg.val;
}
else if (typeof arg.capper !== 'undefined') {
try {
await this.cap(arg.capper, arg.id);
}
catch (err) {
this.log.error(err);
}
}
else if (typeof arg.exposure !== 'undefined') {
try {
await this.exposure(arg.exposure, arg.id);
}
catch (err) {
this.log.error(err);
}
}
event.returnValue = true;
}
/**
*
**/
async end(cmd, id, ms) {
let message = '';
if (cmd === this.cfg.arduino.cmd.camera_forward) {
message = 'Camera set to FORWARD';
}
else if (cmd === this.cfg.arduino.cmd.camera_backward) {
message = 'Camera set to BACKWARD';
}
else if (cmd === this.cfg.arduino.cmd.camera_second_forward) {
message = 'Camera second set to FORWARD';
}
else if (cmd === this.cfg.arduino.cmd.camera_second_backward) {
message = 'Camera second set to BACKWARD';
}
else if (cmd === this.cfg.arduino.cmd.camera) {
message = 'Camera ';
if (this.state.dir) {
message += 'ADVANCED';
}
else {
message += 'REWOUND';
}
message += ' 1 frame';
}
else if (cmd === this.cfg.arduino.cmd.camera_second) {
message = 'Camera second ';
if (this.state.dir) {
message += 'ADVANCED';
}
else {
message += 'REWOUND';
}
message += ' 1 frame';
}
else if (cmd === this.cfg.arduino.cmd.camerass) {
message += 'Cameras both MOVED 1 frame each';
}
else if (cmd === this.cfg.arduino.camera_exposure) {
message += 'Camera set exposure';
}
message += ` ${ms}ms`;
this.log.info(message);
this.ui.send(this.id, { cmd: cmd, id: id, ms: ms });
return ms;
}
}
module.exports = function (arduino, cfg, ui, filmout, second) {
return new Camera(arduino, cfg, ui, filmout, second);
};
//# sourceMappingURL=index.js.map

1
app/lib/cam/index.js.map Normal file

File diff suppressed because one or more lines are too long

11
app/lib/cam/package.json Normal file
View File

@ -0,0 +1,11 @@
{
"name": "cam",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

1
app/lib/capper/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export {};

89
app/lib/capper/index.js Normal file
View File

@ -0,0 +1,89 @@
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
/** class representing capper functions **/
class Capper {
/**
*
**/
constructor(arduino, cfg, ui, filmout) {
this.state = {
capper: false
};
this.arduino = null;
this.id = 'capper';
this.arduino = arduino;
this.cfg = cfg;
this.ui = ui;
this.filmout = filmout;
this.init();
}
/**
*
**/
async init() {
const Log = require('log');
this.log = await Log({ label: this.id });
this.ipc = require('electron').ipcMain;
this.listen();
}
/**
*
**/
listen() {
this.ipc.on(this.id, this.listener.bind(this));
}
/**
*
**/
async capper(state, id) {
let cmd;
let ms;
if (state) {
cmd = this.cfg.arduino.cmd[`${this.id}_on`];
}
else {
cmd = this.cfg.arduino.cmd[`${this.id}_off`];
}
this.state.capper = state;
try {
ms = await this.arduino.send(this.id, cmd);
}
catch (err) {
this.log.error(err);
}
return await this.end(cmd, id, ms);
}
/**
*
**/
async listener(event, arg) {
if (typeof arg.state !== 'undefined') {
try {
await this.capper(arg.state, arg.id);
}
catch (err) {
this.log.error(err);
}
}
event.returnValue = true;
}
/**
*
**/
async end(cmd, id, ms) {
let message = '';
if (cmd === this.cfg.arduino.cmd.capper_on) {
message = 'Capper set to ON';
}
else if (cmd === this.cfg.arduino.cmd.capper_off) {
message = 'Capper set to OFF';
}
message += ` ${ms}ms`;
this.log.info(message);
this.ui.send(this.id, { cmd: cmd, id: id, ms: ms });
}
}
module.exports = function (arduino, cfg, ui, filmout) {
return new Capper(arduino, cfg, ui, filmout);
};
//# sourceMappingURL=index.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/capper/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAMb,2CAA2C;AAE3C,MAAM,MAAM;IAWX;;QAEI;IACJ,YAAa,OAAiB,EAAE,GAAS,EAAE,EAAQ,EAAE,OAAa;QAb1D,UAAK,GAAS;YACrB,MAAM,EAAG,KAAK;SACd,CAAC;QACM,YAAO,GAAa,IAAI,CAAC;QAMzB,OAAE,GAAY,QAAQ,CAAC;QAK9B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,IAAI,EAAE,CAAC;IACb,CAAC;IAED;;QAEI;IACI,KAAK,CAAC,IAAI;QACjB,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QAC3B,IAAI,CAAC,GAAG,GAAG,MAAM,GAAG,CAAC,EAAE,KAAK,EAAG,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1C,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC;QACvC,IAAI,CAAC,MAAM,EAAE,CAAC;IACf,CAAC;IAED;;QAEI;IACI,MAAM;QACb,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAChD,CAAC;IAED;;QAEI;IACI,KAAK,CAAC,MAAM,CAAE,KAAe,EAAE,EAAW;QACjD,IAAI,GAAY,CAAC;QACjB,IAAI,EAAW,CAAC;QAEhB,IAAI,KAAK,EAAE;YACV,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;SAC5C;aAAM;YACN,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;SAC7C;QAED,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC;QAE1B,IAAI;YACH,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;SAC3C;QAAC,OAAO,GAAG,EAAE;YACb,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;SACpB;QAED,OAAO,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IACpC,CAAC;IAED;;QAEI;IACI,KAAK,CAAC,QAAQ,CAAE,KAAW,EAAE,GAAS;QAC7C,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,WAAW,EAAE;YACrC,IAAI;gBACH,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC,CAAA;aACpC;YAAC,OAAO,GAAG,EAAE;gBACb,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;aACnB;SACD;QACD,KAAK,CAAC,WAAW,GAAG,IAAI,CAAA;IACzB,CAAC;IAED;;QAEI;IACI,KAAK,CAAC,GAAG,CAAE,GAAY,EAAE,EAAW,EAAE,EAAW;QACxD,IAAI,OAAO,GAAG,EAAE,CAAC;QAEjB,IAAI,GAAG,KAAK,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE;YAC3C,OAAO,GAAG,kBAAkB,CAAC;SAC7B;aAAM,IAAI,GAAG,KAAK,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE;YACnD,OAAO,GAAG,mBAAmB,CAAC;SAC9B;QAED,OAAO,IAAI,IAAI,EAAE,IAAI,CAAA;QAErB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvB,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAG,EAAE,EAAE,EAAE,EAAE,EAAE,EAAC,CAAC,CAAC;IACpD,CAAC;CACD;AAED,MAAM,CAAC,OAAO,GAAG,UAAU,OAAiB,EAAE,GAAS,EAAE,EAAQ,EAAE,OAAY;IAC9E,OAAO,IAAI,MAAM,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;AAC9C,CAAC,CAAA"}

View File

View File

@ -8,8 +8,8 @@ const parser = new Readline('');
const newlineRe = new RegExp('\n', 'g');
const returnRe = new RegExp('\r', 'g');
const exec = require('exec');
const delay = require('delay');
const { exec } = require('exec');
const { delay } = require('delay');
let system = {};
let INTVAL;

287
app/lib/client/index.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

0
app/lib/cmd/Readme.md Normal file
View File

1
app/lib/cmd/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export {};

644
app/lib/cmd/index.js Normal file
View File

@ -0,0 +1,644 @@
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
const uuid_1 = require("uuid");
const delay_1 = require("delay");
class Commands {
/**
* @constructor
* Assign all connected devices and mock devices as private classes.
*
* @param {object} cfg Configuration object
* @param {object} proj Projector 1
* @param {object} cam Camera 1
* @param {object} light Light source
* @param {object} alert Alert object
* @param {object} cam2 (optional) Camera 2
* @param {object} proj2 (optional) Projector 2
* @param {object} capper Capper object
*
**/
constructor(cfg, proj, cam, light, alert, cam2 = null, proj2 = null, capper = null) {
this.cfg = cfg;
this.proj = proj;
this.cam = cam;
this.light = light;
this.alertObj = alert;
if (cam2 !== null)
this.cam2 = cam2;
if (proj2 !== null)
this.proj2 = proj2;
if (capper !== null)
this.capper = capper;
this.ipc = require('electron').ipcMain;
}
/**
* Move the projector one frame forward
*
* @returns {integer} Length of action in ms
**/
async projector_forward() {
let ms;
try {
if (!this.proj.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.proj.set(true);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
ms = await this.proj.move();
}
catch (err) {
throw err;
}
return ms;
}
/**
* Move the projector one frame backward
*
* @returns {integer} Length of action in ms
**/
async projector_backward() {
let ms;
try {
if (this.proj.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.proj.set(false);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
ms = await this.proj.move();
}
catch (err) {
throw err;
}
return ms;
}
/**
* Move the camera one frame forward
*
* @param {object} cmd Full cmd object
*
* @returns {integer} Length of action in ms
**/
async camera_forward() {
const id = (0, uuid_1.v4)();
const off = [0, 0, 0];
let rgb = [255, 255, 255];
let ms;
try {
if (!this.cam.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.cam.set(true);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.light.set(rgb, id);
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
ms = await this.cam.move();
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.light.set(off, id);
}
catch (err) {
throw err;
}
return ms;
}
/**
* Move the camera one frame forward with light off
*
* @returns {integer} Length of action in ms
**/
async black_forward() {
const id = (0, uuid_1.v4)();
const off = [0, 0, 0];
let ms = 0;
try {
if (!this.cam.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.cam.set(true);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
if (this.capper) {
ms += await this.capper.capper(true, id);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.light.set(off, id); //make sure set to off
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
ms += await this.cam.move();
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.light.set(off, id);
if (this.capper) {
ms += await this.capper.capper(false, id);
}
}
catch (err) {
throw err;
}
return ms;
}
/**
* Move the camera one frame backward
*
* @param {object} cmd Full cmd object
*
* @returns {integer} Length of action in ms
**/
async camera_backward() {
const id = (0, uuid_1.v4)();
const off = [0, 0, 0];
let rgb = [255, 255, 255];
let ms;
try {
if (this.cam.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.cam.set(false);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.light.set(rgb, id);
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
ms = await this.cam.move();
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.light.set(off, id);
}
catch (err) {
throw err;
}
return ms;
}
/**
* Move the camera one frame forward, light set to black or off
*
* @returns {integer} Length of action in ms
**/
async black_backward() {
const id = (0, uuid_1.v4)();
const off = [0, 0, 0];
let ms = 0;
try {
if (this.cam.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.cam.set(false);
}
if (this.capper) {
ms += await this.capper.capper(true, id);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.light.set(off, id); //make sure set to off
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
ms += await this.cam.move();
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.light.set(off, id);
if (this.capper) {
ms += await this.capper.capper(false, id);
}
}
catch (err) {
throw err;
}
return ms;
}
/**
* Move the second camera one frame forward
*
* @param {object} cmd Full cmd object
*
* @returns {integer} Length of action in ms
**/
async camera_second_forward() {
const id = (0, uuid_1.v4)();
const off = [0, 0, 0];
let rgb = [255, 255, 255];
let ms;
try {
if (!this.cam2.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.cam2.set(true);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.light.set(rgb, id);
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
ms = await this.cam2.move();
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.light.set(off, id);
}
catch (err) {
throw err;
}
return ms;
}
/**
* Move the second camera one frame backward
*
* @param {object} cmd Full cmd object
*
* @returns {integer} Length of action in ms
**/
async camera_second_backward() {
const id = (0, uuid_1.v4)();
const off = [0, 0, 0];
let rgb = [255, 255, 255];
let ms;
try {
if (this.cam2.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.cam2.set(false);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.light.set(rgb, id);
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
ms = await this.cam2.move();
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.light.set(off, id);
}
catch (err) {
throw err;
}
return ms;
}
/**
* Move the both cameras one frame forward
*
* @param {object} cmd Full cmd object
*
* @returns {integer} Length of action in ms
**/
async cameras_forward() {
const id = (0, uuid_1.v4)();
const off = [0, 0, 0];
let rgb = [255, 255, 255];
let both;
let ms;
try {
if (!this.cam.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.cam.set(true);
}
if (!this.cam2.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.cam2.set(true);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.light.set(rgb, id);
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
if (this.cam && this.cam2 && this.cam.arduino.alias.camera === this.cam.arduino.alias.camera_second) {
ms = await this.cam.both();
}
else {
this.cam.move();
this.cam2.move();
both = [await this.cam.move, await this.cam2.move];
ms = Math.max(...both);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.light.set(off, id);
}
catch (err) {
throw err;
}
return ms;
}
/**
* Move the both cameras one frame backward
*
* @param {object} cmd Full cmd object
*
* @returns {integer} Length of action in ms
**/
async cameras_backward() {
const id = (0, uuid_1.v4)();
const off = [0, 0, 0];
let rgb = [255, 255, 255];
let both;
let ms;
try {
if (this.cam.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.cam.set(false);
}
if (this.cam2.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.cam2.set(false);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.light.set(rgb, id);
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
if (this.cam && this.cam2 && this.cam.arduino.alias.camera === this.cam.arduino.alias.camera_second) {
ms = await this.cam.both();
}
else {
this.cam.move();
this.cam2.move();
both = [await this.cam.move, await this.cam2.move];
ms = Math.max(...both);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.light.set(off, id);
}
catch (err) {
throw err;
}
return ms;
}
/**
* Move first camera one frame forward and rewind secondary camera one frame backward
*
* @param {object} cmd Full cmd object
*
* @returns {integer} Length of action in ms
**/
async camera_forward_camera_second_backward() {
const id = (0, uuid_1.v4)();
const off = [0, 0, 0];
let rgb = [255, 255, 255];
let both;
let ms;
try {
if (!this.cam.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.cam.set(true);
}
if (this.cam2.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.cam2.set(false);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.light.set(rgb, id);
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
if (this.cam && this.cam2 && this.cam.arduino.alias.camera === this.cam.arduino.alias.camera_second) {
ms = await this.cam.both();
}
else {
this.cam.move();
this.cam2.move();
both = [await this.cam.move, await this.cam2.move];
ms = Math.max(...both);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.light.set(off, id);
}
catch (err) {
throw err;
}
return ms;
}
/**
* Rewind first camera one frame backward and move secondary camera one frame forward
*
* @param {object} cmd Full cmd object
*
* @returns {integer} Length of action in ms
**/
async camera_backward_camera_second_forward() {
const id = (0, uuid_1.v4)();
const off = [0, 0, 0];
let rgb = [255, 255, 255];
let both;
let ms;
try {
if (this.cam.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.cam.set(false);
}
if (!this.cam2.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.cam2.set(true);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.light.set(rgb, id);
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
if (this.cam && this.cam2 && this.cam.arduino.alias.camera === this.cam.arduino.alias.camera_second) {
ms = await this.cam.both();
}
else {
this.cam.move();
this.cam.move();
both = [await this.cam.move, await this.proj2.move];
ms = Math.max(...both);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.light.set(off, id);
}
catch (err) {
throw err;
}
return ms;
}
/**
* Move the secondary projector forward one frame
*
* @returns {integer} Length of action in ms
**/
async projector_second_forward() {
let ms;
try {
if (!this.proj2.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.proj2.set(true);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
ms = await this.proj2.move();
}
catch (err) {
throw err;
}
return ms;
}
/**
* Rewind the secondary projector backward one frame
*
* @returns {integer} Length of action in ms
**/
async projector_second_backward() {
let ms;
try {
if (this.proj2.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.proj2.set(false);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
ms = await this.proj2.move();
}
catch (err) {
throw err;
}
return ms;
}
/**
* Move the both projectors forward one frame
*
* @returns {integer} Length of action in ms
**/
async projectors_forward() {
let both;
let ms;
try {
if (!this.proj.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.proj.set(true);
}
if (!this.proj2.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.proj2.set(true);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
if (this.proj && this.proj2 && this.proj.arduino.alias.projector === this.proj.arduino.alias.projector_second) {
ms = await this.proj.both();
}
else {
this.proj.move();
this.proj2.move();
both = [await this.proj.move, await this.proj2.move];
ms = Math.max(...both);
}
}
catch (err) {
throw err;
}
return ms;
}
/**
* Rewind both projectors backwards one frame
*
* @returns {integer} Length of action in ms
**/
async projectors_backward() {
let both;
let ms;
try {
if (this.proj.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.proj.set(false);
}
if (this.proj2.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.proj2.set(false);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
//run one projector without await?
if (this.proj && this.proj2 && this.proj.arduino.alias.projector === this.proj.arduino.alias.projector_second) {
ms = await this.proj.both();
}
else {
this.proj.move();
this.proj2.move();
both = [await this.proj.move, await this.proj2.move];
ms = Math.max(...both);
}
}
catch (err) {
throw err;
}
return ms;
}
/**
* Move the primary projector forward one frame and rewind the secondary projector
* one frame backwards.
*
* @returns {integer} Length of action in ms
**/
async projector_forward_projector_second_backward() {
let both;
let ms;
try {
if (!this.proj.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.proj.set(true);
}
if (this.proj2.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.proj2.set(false);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
//run one projector without await?
if (this.proj && this.proj2 && this.proj.arduino.alias.projector === this.proj.arduino.alias.projector_second) {
ms = await this.proj.both();
}
else {
this.proj.move();
this.proj2.move();
both = [await this.proj.move, await this.proj2.move];
ms = Math.max(...both);
}
}
catch (err) {
throw err;
}
return ms;
}
/**
* Rewind the primary projector backwards one frame and move the secondary
* projector forward one frame.
*
* @returns {integer} Length of action in ms
**/
async projector_backward_projector_second_forward() {
let both;
let ms;
try {
if (this.proj.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.proj.set(false);
}
if (!this.proj2.state.dir) {
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
await this.proj2.set(true);
}
await (0, delay_1.delay)(this.cfg.arduino.serialDelay);
//run one projector without await?
if (this.proj && this.proj2 && this.proj.arduino.alias.projector === this.proj.arduino.alias.projector_second) {
ms = await this.proj.both();
}
else {
this.proj.move();
this.proj2.move();
both = [await this.proj.move, await this.proj2.move];
ms = Math.max(...both);
}
}
catch (err) {
throw err;
}
return ms;
}
/**
* Throws an alert to pause a sequence
*
* @returns {integer} Length of action in ms
**/
async alert(cmd) {
let ms;
try {
ms = await this.alertObj.start(cmd.light); //change this meta
}
catch (err) {
throw err;
}
return ms;
}
/**
* Pauses a sequence for a length of time
*
* @returns {integer} Length of action in ms
**/
async pause(cmd) {
let ms;
try {
ms = await (0, delay_1.delay)(cmd.light * 1000); //delay is in seconds
}
catch (err) {
throw err;
}
return ms;
}
async camera_exposure(cmd) {
let ms;
try {
ms = await this.cam.exposure(cmd.light);
}
catch (err) {
throw err;
}
return ms;
}
}
module.exports = function (cfg, proj, cam, light, alert, cam2, proj2, capper) {
return new Commands(cfg, proj, cam, light, alert, cam2, proj2, capper);
};
//# sourceMappingURL=index.js.map

1
app/lib/cmd/index.js.map Normal file

File diff suppressed because one or more lines are too long

11
app/lib/cmd/package.json Normal file
View File

@ -0,0 +1,11 @@
{
"name": "cmd",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

View File

12
app/lib/delay/Readme.md Normal file
View File

@ -0,0 +1,12 @@
<a name="delay"></a>
## delay(ms) ⇒ <code>Promise</code>
Delay in an async/await function
**Kind**: global function
**Returns**: <code>Promise</code> - Promise to resolve after timeout
| Param | Type | Description |
| --- | --- | --- |
| ms | <code>integer</code> | Milliseconds to delay for |

8
app/lib/delay/index.d.ts vendored Normal file
View File

@ -0,0 +1,8 @@
/**
* Delay in an async/await function
*
* @param {integer} ms Milliseconds to delay for
*
* @returns {Promise} Promise to resolve after timeout
**/
export declare function delay(ms: number): Promise<unknown>;

View File

@ -1,9 +1,18 @@
'use strict';
function delay (ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
Object.defineProperty(exports, "__esModule", { value: true });
exports.delay = void 0;
/**
* Delay in an async/await function
*
* @param {integer} ms Milliseconds to delay for
*
* @returns {Promise} Promise to resolve after timeout
**/
function delay(ms) {
return new Promise((resolve) => {
return setTimeout(resolve, ms);
});
}
module.exports = delay;
exports.delay = delay;
module.exports = { delay };
//# sourceMappingURL=index.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/delay/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;AAEb;;;;;;IAMI;AAEJ,SAAgB,KAAK,CAAE,EAAW;IACjC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAa,EAAE,EAAE;QACpC,OAAO,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;AACJ,CAAC;AAJD,sBAIC;AAED,MAAM,CAAC,OAAO,GAAG,EAAE,KAAK,EAAE,CAAC"}

74
app/lib/devices/Readme.md Normal file
View File

@ -0,0 +1,74 @@
<a name="Devices"></a>
## Devices
class representing the device discovery features
**Kind**: global class
* [Devices](#Devices)
* [.init()](#Devices+init)
* [.listen()](#Devices+listen)
* [.listener()](#Devices+listener)
* [.enumerate()](#Devices+enumerate)
* [.favor()](#Devices+favor)
* [.distinguish()](#Devices+distinguish)
* [.fakeProjector()](#Devices+fakeProjector)
* [.fakeCamera()](#Devices+fakeCamera)
* [.fakeLight()](#Devices+fakeLight)
* [.connectDevice()](#Devices+connectDevice)
* [.all()](#Devices+all)
* [.remember()](#Devices+remember)
* [.ready()](#Devices+ready)
<a name="Devices+init"></a>
### devices.init()
**Kind**: instance method of [<code>Devices</code>](#Devices)
<a name="Devices+listen"></a>
### devices.listen()
**Kind**: instance method of [<code>Devices</code>](#Devices)
<a name="Devices+listener"></a>
### devices.listener()
**Kind**: instance method of [<code>Devices</code>](#Devices)
<a name="Devices+enumerate"></a>
### devices.enumerate()
**Kind**: instance method of [<code>Devices</code>](#Devices)
<a name="Devices+favor"></a>
### devices.favor()
**Kind**: instance method of [<code>Devices</code>](#Devices)
<a name="Devices+distinguish"></a>
### devices.distinguish()
**Kind**: instance method of [<code>Devices</code>](#Devices)
<a name="Devices+fakeProjector"></a>
### devices.fakeProjector()
**Kind**: instance method of [<code>Devices</code>](#Devices)
<a name="Devices+fakeCamera"></a>
### devices.fakeCamera()
**Kind**: instance method of [<code>Devices</code>](#Devices)
<a name="Devices+fakeLight"></a>
### devices.fakeLight()
**Kind**: instance method of [<code>Devices</code>](#Devices)
<a name="Devices+connectDevice"></a>
### devices.connectDevice()
**Kind**: instance method of [<code>Devices</code>](#Devices)
<a name="Devices+all"></a>
### devices.all()
**Kind**: instance method of [<code>Devices</code>](#Devices)
<a name="Devices+remember"></a>
### devices.remember()
**Kind**: instance method of [<code>Devices</code>](#Devices)
<a name="Devices+ready"></a>
### devices.ready()
**Kind**: instance method of [<code>Devices</code>](#Devices)

1
app/lib/devices/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export {};

585
app/lib/devices/index.js Normal file
View File

@ -0,0 +1,585 @@
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
const delay_1 = require("delay");
const Log = require("log");
/**
* class representing the device discovery features
*
*
**/
class Devices {
/**
* Constructor assigns arduino, settings, UI browser window and cam objects
* locally to this class for reference.
**/
constructor(arduino, settings, mainWindow, cam) {
this.connected = {};
this.arduino = arduino;
this.settings = settings;
this.mainWindow = mainWindow;
this.ui = this.mainWindow.webContents;
this.cam = cam;
this.init();
}
/**
* Initialize the log for "devices". Establish an ipc connection to the UI.
* Start listening on that ipc connection.
**/
async init() {
this.log = await Log({ label: 'devices' });
this.ipc = require('electron').ipcMain;
this.listen();
}
/**
* Listen to the "profile" channel for messages from the UI.
**/
listen() {
this.ipc.handle('profile', this.listener.bind(this));
}
/**
* The "profile" channel callback. If a profile is changed, set it in the
* local settings object.
**/
async listener(event, arg) {
if (typeof arg.profile !== 'undefined') {
this.log.info(`Saving profile ${arg.profile}`, 'SETTINGS', false, false);
this.settings.update('profile', arg.profile);
await this.settings.save();
}
if (typeof arg.timing !== 'undefined') {
this.log.info(`Saving timing info`, 'SETTINGS', false, false);
this.settings.update('timing', arg.timing);
await this.settings.save();
}
return true;
}
/**
*
**/
async enumerate() {
let serials;
try {
serials = await this.arduino.enumerate();
}
catch (err) {
this.log.warn(err, 'SERIAL', false, true);
await (0, delay_1.delay)(1000);
return this.all([]);
}
this.log.info(`Found ${serials.length} USB devices`, 'SERIAL', true, true);
serials = this.favor(serials);
return await this.all(serials);
}
/**
*
**/
favor(serials) {
const past = this.settings.state.devices.filter((device) => {
if (device.serial) {
return device;
}
}).map((device) => {
return device.serial;
});
if (past.length === 0) {
return serials;
}
serials.sort((a, b) => {
if (past.indexOf(a) !== -1 && past.indexOf(b) === -1) {
return 1;
}
else if (past.indexOf(a) === -1 && past.indexOf(b) !== -1) {
return -1;
}
return 0;
});
return serials;
}
/**
*
**/
async distinguish(serial) {
let connectSuccess;
let verifySuccess;
let device;
//this.log.info(`distinguish() ${serial}`)
try {
connectSuccess = await this.arduino.connect('connect', serial, true);
}
catch (err) {
this.log.error('Error connecting', err);
return null;
}
await (0, delay_1.delay)(2000);
try {
verifySuccess = await this.arduino.verify();
}
catch (err) {
this.log.error('Error verifying device', err);
return null;
}
this.log.info(`Verified ${serial} as mcopy device`, 'SERIAL', true, true);
await (0, delay_1.delay)(1000);
try {
device = await this.arduino.distinguish();
}
catch (err) {
this.log.error('Error distinguishing device', err);
return null;
}
this.remember(device, serial, 'arduino');
this.log.info(`Determined ${device} to be ${device}`, 'SERIAL', true, true);
await (0, delay_1.delay)(100);
try {
await this.arduino.state(device, true);
}
catch (err) {
this.log.error('Error checking state capability', err);
}
return device;
}
/**
*
**/
async fakeProjector() {
this.connected.projector = '/dev/fake';
try {
await this.arduino.fakeConnect('projector');
}
catch (err) {
this.log.error(`Error connecting to fake PROjECTOR device`, 'SERIAL', true, true);
this.log.error(err);
return false;
}
this.log.info('Connected to fake PROJECTOR device', 'SERIAL', true, true);
return true;
}
/**
*
**/
async fakeCamera() {
this.connected.camera = '/dev/fake';
try {
await this.arduino.fakeConnect('camera');
}
catch (err) {
this.log.error(`Error connecting to fake CAMERA device`, 'SERIAL', true, true);
this.log.error(err);
return false;
}
this.log.info('Connected to fake CAMERA device', 'SERIAL', true, true);
return true;
}
/**
*
**/
async fakeLight() {
this.connected.light = '/dev/fake';
try {
await this.arduino.fakeConnect('light');
}
catch (err) {
this.log.error(`Error connecting to fake LIGHT device`, 'SERIAL', true, true);
this.log.error(err);
return false;
}
this.log.info('Connected to fake LIGHT device', 'SERIAL', true, true);
return true;
}
/**
*
**/
async fakeCapper() {
this.connected.capper = '/dev/fake';
try {
await this.arduino.fakeConnect('capper');
}
catch (err) {
this.log.error(`Error connecting to fake CAPPER device`, 'SERIAL', true, true);
this.log.error(err);
return false;
}
this.log.info('Connected to fake CAPPER device', 'SERIAL', true, true);
return true;
}
/**
*
**/
async connectDevice(device, serial) {
let closeSuccess;
let connectSuccess;
try {
closeSuccess = await this.arduino.close();
}
catch (err) {
this.log.error('Error closing arduino connection', err);
return false;
}
if (device === 'projector') {
this.connected.projector = serial;
try {
connectSuccess = await this.arduino.connect('projector', serial, false);
}
catch (err) {
this.log.error('Error connecting to projector', err);
return false;
}
this.log.info(`Connected to ${device} as PROJECTOR`, 'SERIAL', true, true);
}
else if (device === 'camera') {
this.connected.camera = serial;
try {
connectSuccess = await this.arduino.connect('camera', serial, false);
}
catch (err) {
this.log.error('Error connecting to camera', err);
return false;
}
this.log.info(`Connected to ${device} as CAMERA`, 'SERIAL', true, true);
}
else if (device === 'light') {
this.connected.light = serial;
try {
connectSuccess = await this.arduino.connect('light', serial, false);
}
catch (err) {
this.log.error('Error connecting to light', err);
return false;
}
this.log.info(`Connected to ${device} as LIGHT`, 'SERIAL', true, true);
}
else if (device === 'projector,light') {
this.connected.projector = serial;
this.connected.light = serial;
this.arduino.aliasSerial('light', serial);
try {
connectSuccess = await this.arduino.connect('projector', serial, false);
}
catch (err) {
this.log.error('Error connecting to projector and light', err);
return false;
}
this.log.info(`Connected to ${device} as PROJECTOR + LIGHT`, 'SERIAL', true, true);
}
else if (device === 'projector,camera,light') {
this.connected.projector = serial;
this.connected.camera = serial;
this.connected.light = serial;
this.arduino.aliasSerial('camera', serial);
this.arduino.aliasSerial('light', serial);
try {
connectSuccess = await this.arduino.connect('projector', serial, false);
}
catch (err) {
this.log.error('Error connecting to projector, camera and light', err);
return false;
}
this.log.info(`Connected to ${device} as PROJECTOR + CAMERA + LIGHT`, 'SERIAL', true, true);
}
else if (device === 'projector,camera') {
this.connected.projector = serial;
this.connected.camera = serial;
this.arduino.aliasSerial('camera', serial);
try {
connectSuccess = await this.arduino.connect('projector', serial, false);
}
catch (err) {
this.log.error('Error connecting to projector and camera', err);
return false;
}
this.log.info(`Connected to ${device} as PROJECTOR + CAMERA`, 'SERIAL', true, true);
}
else if (device === 'projector_second') {
this.connected.projector_second = serial;
try {
connectSuccess = await this.arduino.connect('projector_second', serial, false);
}
catch (err) {
this.log.error('Error connecting to secondary projector', err);
return false;
}
this.log.info(`Connected to ${device} as PROJECTOR_SECOND`, 'SERIAL', true, true);
}
else if (device === 'projector,projector_second') {
this.connected.projector = serial;
this.connected.projector_second = serial;
this.arduino.aliasSerial('projector_second', serial);
try {
connectSuccess = await this.arduino.connect('projector', serial, false);
}
catch (err) {
this.log.error('Error connecting to projector and secondary projector', err);
return false;
}
}
else if (device === 'camera_second') {
this.connected.camera_second = serial;
try {
connectSuccess = await this.arduino.connect('camera_second', serial, false);
}
catch (err) {
this.log.error(err);
return false;
}
}
else if (device === 'camera,camera_second') {
this.connected.camera = serial;
this.connected.camera_second = serial;
this.arduino.aliasSerial('camera_second', serial);
try {
connectSuccess = await this.arduino.connect('camera', serial, false);
}
catch (err) {
this.log.error('Error connecting to camera, camera_secondary and projector', err);
return false;
}
}
else if (device === 'camera,projector,projector_second') {
this.connected.camera = serial;
this.connected.projector = serial;
this.connected.projector_second = serial;
this.arduino.aliasSerial('projector', serial);
this.arduino.aliasSerial('projector_second', serial);
try {
connectSuccess = await this.arduino.connect('camera', serial, false);
}
catch (err) {
this.log.error('Error connecting to camera, projector and projector_second', err);
return false;
}
}
else if (device === 'camera,camera_second,projector') {
this.connected.camera = serial;
this.connected.camera_second = serial;
this.connected.projector = serial;
this.arduino.aliasSerial('camera_second', serial);
this.arduino.aliasSerial('projector', serial);
try {
connectSuccess = await this.arduino.connect('camera', serial, false);
}
catch (err) {
this.log.error('Error connecting to camera, camera_second and projector', err);
return false;
}
}
else if (device === 'camera,camera_second,projector,projector_second') {
this.connected.camera = serial;
this.connected.camera_second = serial;
this.connected.projector = serial;
this.connected.projector_second = serial;
this.arduino.aliasSerial('camera_second', serial);
this.arduino.aliasSerial('projector', serial);
this.arduino.aliasSerial('projector_second', serial);
try {
connectSuccess = await this.arduino.connect('camera', serial, false);
}
catch (err) {
this.log.error('Error connecting to camera, camera_second, projector and projector_second', err);
return false;
}
}
else if (device === 'capper') {
this.connected.capper = serial;
try {
connectSuccess = await this.arduino.connect('capper', serial, false);
}
catch (err) {
this.log.error('Error connecting capper', err);
return false;
}
}
else if (device === 'camera,capper') {
this.connected.camera = serial;
this.connected.capper = serial;
this.arduino.aliasSerial('capper', serial);
try {
connectSuccess = await this.arduino.connect('camera', serial, false);
}
catch (err) {
this.log.error('Error connecting to camera and capper', err);
return false;
}
}
else if (device === 'camera,capper,projector') {
this.connected.camera = serial;
this.connected.capper = serial;
this.connected.projector = serial;
this.arduino.aliasSerial('capper', serial);
this.arduino.aliasSerial('projector', serial);
try {
connectSuccess = await this.arduino.connect('camera', serial, false);
}
catch (err) {
this.log.error('Error connecting to camera, capper and projector', err);
return false;
}
}
else if (device === 'camera,capper,projector,projector_second') {
this.connected.camera = serial;
this.connected.capper = serial;
this.connected.projector = serial;
this.connected.projector_second = serial;
this.arduino.aliasSerial('capper', serial);
this.arduino.aliasSerial('projector', serial);
this.arduino.aliasSerial('projector_second', serial);
try {
connectSuccess = await this.arduino.connect('camera', serial, false);
}
catch (err) {
this.log.error('Error connecting to camera, capper, projector and projector_second', err);
return false;
}
}
return connectSuccess;
}
/**
*
**/
//Cases for 1 or 2 arduinos connected
async all(serials) {
let c = {};
let p = {};
let l = {};
let device;
let d;
let cs = {};
let ps = {};
let capper = {};
let checklist = [];
let exposure;
let parts;
this.connected = {
projector: false,
camera: false,
light: false,
projector_second: false,
capper: false
};
for (let serial of serials) {
try {
device = await this.distinguish(serial);
}
catch (err) {
this.log.error('Error distinguishing device', err);
throw err;
}
try {
await this.connectDevice(device, serial);
}
catch (err) {
this.log.error('Error connecting to device', err);
throw err;
}
}
//done checking devices
if (!this.connected.projector) {
await this.fakeProjector();
}
else if (this.arduino.hasState['projector']) {
p.state = true;
}
p.arduino = this.connected.projector;
if (!this.connected.camera) {
await this.fakeCamera();
}
else if (this.arduino.hasState['camera']) {
if (device.indexOf('camera') !== -1) {
parts = this.arduino.stateStr[device].split('G');
if (parts.length > 1) {
parts = parts[1].split('H');
exposure = parseInt(parts[0]);
if (!isNaN(exposure)) {
this.log.info(`Timing for [${device}] = ${exposure}`);
this.ui.send('timing', { c: 'c', ms: exposure });
}
}
}
c.state = true;
c.exposure = true;
}
c.arduino = this.connected.camera;
if (!this.connected.light) {
await this.fakeLight();
}
l.arduino = this.connected.light;
if (this.connected.camera_second) {
cs.arduino = this.connected.camera_second;
}
if (this.connected.projector_second) {
ps.arduino = this.connected.projector_second;
}
if (this.connected.capper) {
capper.arduino = this.connected.capper;
}
if (this.settings.state.camera && this.settings.state.camera.intval) {
c.intval = this.settings.state.camera.intval;
}
return this.ready(p, c, l, cs, ps, capper);
}
/**
*
**/
remember(device, serial, type) {
let deviceEntry;
const match = this.settings.state.devices.filter((dev) => {
if (typeof dev.device !== 'undefined' && dev.device === device &&
typeof dev.serial !== 'undefined' && dev.serial === serial) {
return dev;
}
});
if (match.length === 0) {
deviceEntry = {
device,
type,
serial
};
this.settings.state.devices.push(deviceEntry);
this.settings.update('devices', this.settings.state.devices);
this.settings.save();
}
}
/**
*
**/
ready(projector, camera, light, camera_second, projector_second, capper) {
let args = {
camera,
projector,
light,
profile: this.settings.state.profile
};
if (this.settings.state.timing) {
args.timing = this.settings.state.timing;
}
if (projector_second && projector_second.arduino) {
args.projector_second = projector_second;
this.settings.update('projector_second', projector_second);
this.mainWindow.setSize(800, 800);
}
if (camera_second && camera_second.arduino) {
args.camera_second = camera_second;
this.settings.update('camera_second', camera_second);
if (projector_second && projector_second.arduino) {
this.mainWindow.setSize(900, 800);
}
else {
this.mainWindow.setSize(800, 800);
}
}
if (capper && capper.arduino) {
args.capper = capper;
this.mainWindow.setSize(800, 800);
this.settings.update('capper', capper);
}
this.settings.update('camera', camera);
this.settings.update('projector', projector);
this.settings.update('light', light);
this.settings.save();
this.ui.send('ready', args);
return true;
}
}
module.exports = function (arduino, settings, mainWindow, cam) {
return new Devices(arduino, settings, mainWindow, cam);
};
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,11 @@
{
"name": "devices",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

View File

1
app/lib/display/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export {};

View File

@ -1,127 +1,198 @@
'use strict';
const path = require('path');
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @module display
* Provides features for displaying a full screen display of images for the digital module.
**/
const path_1 = require("path");
const url_1 = require("url");
const delay_1 = require("delay");
const Log = require("log");
const { BrowserWindow } = require('electron');
const exec = require('exec');
const spawn = require('spawn');
const delay = require('delay');
let wv;
let cp;
let system = {};
let digitalWindow;
let TMPDIR;
class WebView {
constructor() {
}
async open () {
digitalWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: true,
allowRunningInsecureContent: false,
'unsafe-eval' : false
},
width: 800,
height: 600,
minWidth : 800,
minHeight : 600//,
//icon: path.join(__dirname, '../../assets/icons/icon.png')
});
digitalWindow.loadURL('file://' + __dirname + '../../../display.html');
if (process.argv.indexOf('-d') !== -1 || process.argv.indexOf('--dev') !== -1) {
digitalWindow.webContents.openDevTools();
}
digitalWindow.on('closed', () => {
digitalWindow = null
});
}
async fullScreen () {
return digitalWindow.setFullScreen(true);
}
async setImage (src) {
return digitalWindow.webContents.send('display', { src });
}
async setMeter () {
return digitalWindow.webContents.send('display', { meter : true });
}
async setGrid () {
return digitalWindow.webContents.send('display', { grid : true });
}
async close () {
if (digitalWindow) {
digitalWindow.close();
}
return true
}
async move () {
}
constructor(platform, display) {
this.opened = false;
this.showing = false;
this.loadWait = {};
const prefs = {
webPreferences: {
nodeIntegration: true,
allowRunningInsecureContent: false,
enableRemoteModule: true,
contextIsolation: false
},
width: 800,
height: 600,
minWidth: 800,
minHeight: 600 //,
//icon: path.join(__dirname, '../../assets/icons/icon.png')
};
const pagePath = (0, path_1.normalize)((0, path_1.join)(__dirname, '../../display.html'));
const pageUrl = (0, url_1.format)({
pathname: pagePath,
protocol: 'file:'
});
this.init();
if (!display.primary) {
prefs.x = display.x + 50;
prefs.y = display.y + 50;
}
this.digitalWindow = new BrowserWindow(prefs);
require('@electron/remote/main').enable(this.digitalWindow.webContents);
this.digitalWindow.loadURL(pageUrl);
if (process.argv.indexOf('-d') !== -1 || process.argv.indexOf('--dev') !== -1) {
this.digitalWindow.webContents.openDevTools();
}
this.digitalWindow.on('closed', () => {
this.digitalWindow = null;
this.close();
});
//this.digitalWindow.hide();
this.platform = platform;
this.display = display;
this.ipc = require('electron').ipcMain;
this.ipc.on('display_load', this.onLoad.bind(this));
}
async init() {
this.log = await Log({ label: 'devices' });
}
async open() {
this.digitalWindow.show();
this.showing = true;
this.opened = true;
await this.digitalWindow.setFullScreen(true);
await (0, delay_1.delay)(300);
if (this.platform === 'osx') {
await (0, delay_1.delay)(300); //give macs an extra 300ms to open fullscreen
}
}
async show(src) {
const normalSrc = (0, path_1.normalize)((0, path_1.join)(src));
if (!this.digitalWindow) {
this.log.warn(`Cannot show "${src}" because window does not exist`);
return false;
}
try {
this.digitalWindow.webContents.send('display', { src: normalSrc });
}
catch (err) {
this.log.error(err);
}
this.showing = true;
return new Promise(function (resolve) {
this.loadWait[src] = resolve;
}.bind(this));
}
onLoad(evt, arg) {
if (this.loadWait[arg.src]) {
this.loadWait[arg.src]();
delete this.loadWait[arg.src];
}
}
async focus() {
if (!this.digitalWindow) {
this.log.warn(`Cannot show focus screen because window does not exist`);
return false;
}
await (0, delay_1.delay)(500);
try {
this.digitalWindow.webContents.send('focus', { focus: true });
}
catch (err) {
this.log.error(err);
}
}
async field(ratio) {
if (!this.digitalWindow) {
this.log.warn(`Cannot show field guide because window does not exist`);
return false;
}
await (0, delay_1.delay)(500);
try {
this.digitalWindow.webContents.send('field', { field: true, ratio });
}
catch (err) {
this.log.error(err);
}
}
async meter() {
if (!this.digitalWindow) {
this.log.warn(`Cannot show meter screen because window does not exist`);
return false;
}
await (0, delay_1.delay)(500);
try {
this.digitalWindow.webContents.send('meter', { meter: true });
}
catch (err) {
this.log.error(err);
}
}
hide() {
if (this.digitalWindow) {
this.digitalWindow.hide();
}
this.showing = false;
return true;
}
close() {
this.hide();
if (this.digitalWindow) {
this.digitalWindow.close();
this.digitalWindow = null;
}
this.opened = false;
this.showing = false;
return true;
}
}
function padded_frame (i) {
let len = (i + '').length;
let str = i + '';
for (let x = 0; x < 5 - len; x++) {
str = '0' + str;
}
return str;
class Display {
constructor(sys) {
this.platform = sys.platform;
this.displays = sys.displays;
this.tmpdir = (0, path_1.join)(sys.tmp, 'mcopy_digital');
this.display = this.displays.find((display) => {
if (display.primary)
return true;
});
}
async open() {
if (this.wv && this.wv.display && this.wv.display.id !== this.display.id) {
this.wv.close();
}
if (!this.wv || !this.wv.opened) {
this.wv = new WebView(this.platform, this.display);
await this.wv.open();
}
}
async show(src) {
await this.wv.show(src);
}
async showPath(pathStr) {
return await this.wv.show(pathStr);
}
hide() {
}
async close() {
return await this.wv.close();
}
async focus() {
return await this.wv.focus();
}
async field(ratio) {
return await this.wv.field(ratio);
}
async meter() {
return await this.wv.meter();
}
change(id) {
this.display = this.displays.find((display) => {
if (display.id == id)
return true;
});
}
}
async function display_eog (src) {
//timeout 3 eog --fullscreen ${src}
cp = spawn('eog', ['--fullscreen', src]);
}
async function display_wv (src) {
await wv.open();
await wv.fullScreen();
await delay(200);
await wv.setImage(src);
}
async function end () {
if (system.platform !== 'nix') {
await wv.close();
} else {
if (cp) cp.kill()
}
}
async function start (frame) {
let padded = padded_frame(frame);
let ext = 'tif';
let tmppath;
if (system.platform !== 'nix') {
ext = 'png';
}
tmppath = path.join(TMPDIR, `export-${padded}.${ext}`);
if (system.platform !== 'nix') {
display_wv(tmppath);
} else {
display_eog(tmppath);
}
}
module.exports = function (sys) {
system = sys;
TMPDIR = path.join(system.tmp, 'mcopy_digital');
if (system.platform !== 'nix') {
wv = new WebView();
} else {
//child process
}
return {
start,
end
}
}
return new Display(sys);
};
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

1
app/lib/exec/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export declare const execRaw: any;

View File

@ -1,7 +1,7 @@
'use strict'
const execRaw = require('child_process').exec
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.execRaw = void 0;
exports.execRaw = require('child_process').exec;
/**
* Promisified child_process.exec
*
@ -14,26 +14,26 @@ const execRaw = require('child_process').exec
* @returns {Promise<{ stdout: string, stderr: stderr }>}
*/
async function exec(...args) {
let cmd = args[0]
let argz = null
let opts = null
if (typeof args[1] === 'object' && Array.isArray(args[1])) {
argz = args[1]
}
if (argz === null && typeof args[1] === 'object') {
opts = args[1]
} else if (typeof args[2] === 'object') {
opts = args[2]
}
if (opts === null) {
opts = { maxBuffer : 1024 * 1024 }
}
let cmd = args[0];
let argz = null;
let opts = null;
if (typeof args[1] === 'object' && Array.isArray(args[1])) {
argz = args[1];
}
if (argz === null && typeof args[1] === 'object') {
opts = args[1];
}
else if (typeof args[2] === 'object') {
opts = args[2];
}
if (opts === null) {
opts = { maxBuffer: 1024 * 1024 };
}
return new Promise((resolve, reject) => {
const child = execRaw(cmd, opts,
(err, stdout, stderr) => err ? reject(err) : resolve({
stdout: stdout,
stderr: stderr
}));
const child = (0, exports.execRaw)(cmd, opts, (err, stdout, stderr) => err ? reject(err) : resolve({
stdout,
stderr
}));
if (opts.stdout) {
child.stdout.pipe(opts.stdout);
}
@ -42,5 +42,5 @@ async function exec(...args) {
}
});
}
module.exports = exec
module.exports.exec = exec;
//# sourceMappingURL=index.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/exec/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAA;;;AAEC,QAAA,OAAO,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC,IAAI,CAAA;AAEpD;;;;;;;;;;GAUG;AACH,KAAK,UAAU,IAAI,CAAC,GAAG,IAAe;IACrC,IAAI,GAAG,GAAY,IAAI,CAAC,CAAC,CAAC,CAAA;IAC1B,IAAI,IAAI,GAAY,IAAI,CAAA;IACxB,IAAI,IAAI,GAAS,IAAI,CAAA;IAErB,IAAI,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE;QAC1D,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;KACd;IACD,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE;QACjD,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;KACd;SAAM,IAAI,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE;QACvC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;KACd;IACD,IAAI,IAAI,KAAK,IAAI,EAAE;QAClB,IAAI,GAAG,EAAE,SAAS,EAAG,IAAI,GAAG,IAAI,EAAE,CAAA;KAClC;IACE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACtC,MAAM,KAAK,GAAG,IAAA,eAAO,EAAC,GAAG,EAAE,IAAI,EACjC,CAAC,GAAW,EAAE,MAAe,EAAE,MAAc,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YAC7E,MAAM;YACN,MAAM;SACN,CAAC,CAAC,CAAC;QACC,IAAI,IAAI,CAAC,MAAM,EAAE;YACb,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;SAClC;QACD,IAAI,IAAI,CAAC,MAAM,EAAE;YACb,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;SAClC;IACL,CAAC,CAAC,CAAC;AACP,CAAC;AAED,MAAM,CAAC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAA"}

13
app/lib/exit/Readme.md Normal file
View File

@ -0,0 +1,13 @@
<a name="exit"></a>
## exit(msg, code)
Exit process with either a 0 code or other
specified failure code. Print message to console first.
**Kind**: global function
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| msg | <code>string</code> | | Reason for exit |
| code | <code>integer</code> | <code>0</code> | process exit code, default 0 |

8
app/lib/exit/index.d.ts vendored Normal file
View File

@ -0,0 +1,8 @@
/**
* Exit process with either a 0 code or other
* specified failure code. Print message to console first.
*
* @param {string} msg Reason for exit
* @param {integer} code process exit code, default 0
**/
declare function exit(msg: string, code?: number): void;

View File

@ -1,13 +1,20 @@
'use strict';
function exit (msg, code = 0) {
if (code === 0) {
console.log(msg);
process.exit();
} else {
console.error(msg);
process.exit(code);
}
/**
* Exit process with either a 0 code or other
* specified failure code. Print message to console first.
*
* @param {string} msg Reason for exit
* @param {integer} code process exit code, default 0
**/
function exit(msg, code = 0) {
if (code === 0) {
console.log(msg);
process.exit();
}
else {
console.error(msg);
process.exit(code);
}
}
module.exports = exit;
module.exports.exit = exit;
//# sourceMappingURL=index.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/exit/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb;;;;;;IAMI;AAEJ,SAAS,IAAI,CAAE,GAAY,EAAE,OAAgB,CAAC;IAC7C,IAAI,IAAI,KAAK,CAAC,EAAE;QACf,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjB,OAAO,CAAC,IAAI,EAAE,CAAC;KACf;SAAM;QACN,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;KACnB;AACF,CAAC;AAED,MAAM,CAAC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC"}

0
app/lib/ffmpeg/Readme.md Normal file
View File

1
app/lib/ffmpeg/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export {};

View File

@ -1,158 +1,356 @@
'use strict';
const uuid = require('uuid').v4;
const path = require('path');
const fs = require('fs-extra');
const exec = require('exec');
//const spawn = require('spawn');
const exit = require('exit');
let system = {};
let TMPDIR;
function padded_frame (i) {
let len = (i + '').length;
let str = i + '';
for (let x = 0; x < 5 - len; x++) {
str = '0' + str;
}
return str;
Object.defineProperty(exports, "__esModule", { value: true });
/** @module ffmpeg **/
const path_1 = require("path");
const fs_extra_1 = require("fs-extra");
const exec_1 = require("exec");
const child_process_1 = require("child_process");
async function spawnAsync(bin, args) {
return new Promise((resolve, reject) => {
const child = (0, child_process_1.spawn)(bin, args);
let stdout = '';
let stderr = '';
child.on('exit', (code) => {
if (code === 0) {
return resolve({ stdout, stderr });
}
else {
console.error(`Process exited with code: ${code}`);
console.error(stderr);
return reject(stderr);
}
});
child.stdout.on('data', (data) => {
stdout += data;
});
child.stderr.on('data', (data) => {
stderr += data;
});
return child;
});
}
async function frame (video, frame, obj) {
let padded = padded_frame(frame);
let ext = 'tif';
let tmpoutput;
let cmd;
let output;
if (system.platform !== 'nix') {
ext = 'png';
}
tmpoutput = path.join(TMPDIR, `export-${padded}.${ext}`)
cmd = `ffmpeg -i "${video}" -vf select='gte(n\\,${frame})' -vframes 1 -compression_algo raw -pix_fmt rgb24 "${tmpoutput}"`
//ffmpeg -i "${video}" -ss 00:00:07.000 -vframes 1 "export-${time}.jpg"
//ffmpeg -i "${video}" -compression_algo raw -pix_fmt rgb24 "export-%05d.tiff"
//-vf "select=gte(n\,${frame})" -compression_algo raw -pix_fmt rgb24 "export-${padded}.png"
try {
console.log(cmd);
output = await exec(cmd);
} catch (err) {
console.error(err);
}
if (output) console.log(`"${output}"`);
/** @class FFMPEG **/
class FFMPEG {
/**
* @constructor
* Creates an ffmpeg class
*
* @param {object} sys System object to be used to get temp directory
**/
constructor(sys) {
this.id = 'ffmpeg';
this.onProgress = () => { };
this.bin = sys.deps.ffmpeg;
this.TMPDIR = (0, path_1.join)(sys.tmp, 'mcopy_digital');
this.init();
}
/**
* Async method to call async functions from constructor
**/
async init() {
const Log = require('log');
this.log = await Log({ label: this.id });
await this.checkDir();
}
/**
* Add padding to a number to 5 places. Return a string.
*
* @param {integer} i Integer to pad
*
* @returns {string} Padded string
**/
padded_frame(i) {
let len = (i + '').length;
let str = i + '';
for (let x = 0; x < 8 - len; x++) {
str = '0' + str;
}
return str;
}
/**
* Parse the stderr output of ffmpeg
*
* @param {string} line Stderr line
**/
parseStderr(line) {
//frame= 6416 fps= 30 q=31.0 size= 10251kB time=00:03:34.32 bitrate= 391.8kbits/s speed= 1x
let obj = {};
if (line.substring(0, 'frame='.length) === 'frame=') {
try {
obj.frame = line.split('frame=')[1].split('fps=')[0];
obj.frame = parseInt(obj.frame);
obj.fps = line.split('fps=')[1].split('q=')[0];
obj.fps = parseFloat(obj.fps);
obj.time = line.split('time=')[1].split('bitrate=')[0];
obj.speed = line.split('speed=')[1].trim().replace('x', '');
obj.speed = parseFloat(obj.speed);
obj.size = line.split('size=')[1].split('time=')[0].trim();
}
catch (err) {
console.error(err);
console.log(line);
process.exit();
}
}
else {
}
return obj;
}
/**
* Render a single frame from a video or image to a png.
*
* @param {object} state State object containing file data
* @param {object} light Object containing color information for frame
*
* @returns {string} Path of frame
**/
async frame(state, light) {
const frameNum = state.frame;
const video = state.directory ? state.files[frameNum] : state.path;
const w = state.info.width;
const h = state.info.height;
const padded = this.padded_frame(frameNum);
let ext = 'png';
let rgb = light.color;
let rgba = {};
let tmpoutput;
let cmd;
let output;
let fileExists = false;
let scale = '';
if (state.directory) {
return video;
}
if (w && h) {
scale = `,scale=trunc(ih*dar):${h}`; //:force_original_aspect_ratio=decrease,pad=${w}:${h}:(ow-iw)/2:(oh-ih)/2
}
tmpoutput = (0, path_1.join)(this.TMPDIR, `${state.hash}-export-${padded}.${ext}`);
try {
fileExists = await (0, fs_extra_1.exists)(tmpoutput);
}
catch (err) {
//
}
if (fileExists) {
this.log.info(`File ${tmpoutput} exists`);
return tmpoutput;
}
//
cmd = `${this.bin} -y -i "${video}" -vf "select='gte(n\\,${frameNum})'${scale}" -vframes 1 -compression_algo raw -pix_fmt rgb24 -crf 0 "${tmpoutput}"`;
//cmd2 = `${this.convert} "${tmpoutput}" -resize ${w}x${h} -size ${w}x${h} xc:"rgb(${rgb[0]},${rgb[1]},${rgb[2]})" +swap -compose Darken -composite "${tmpoutput}"`;
//ffmpeg -i "${video}" -ss 00:00:07.000 -vframes 1 "export-${time}.jpg"
//ffmpeg -i "${video}" -compression_algo raw -pix_fmt rgb24 "export-%05d.tiff"
//-vf "select=gte(n\,${frame})" -compression_algo raw -pix_fmt rgb24 "export-${padded}.png"
try {
this.log.info(cmd);
output = await (0, exec_1.exec)(cmd);
}
catch (err) {
this.log.error(err);
}
if (output && output.stdout)
this.log.info(`"${output.stdout.trim()}"`);
if (rgb[0] !== 255 || rgb[1] !== 255 || rgb[2] !== 255) {
rgb = rgb.map((e) => {
return parseInt(e);
});
rgba = { r: rgb[0], g: rgb[1], b: rgb[2], a: 255 };
try {
//await Frame.blend(tmpoutput, rgba, tmpoutput);
}
catch (err) {
this.log.error(err);
}
}
return tmpoutput;
}
/**
* Render all frames in a video to the temp directory.
* Not in use.
*
* @param {string} video Path to video
* @param {object} obj Not sure
*
* @returns {?}
**/
async frames(state) {
const video = state.path;
const w = state.info.width;
const h = state.info.height;
const tmppath = this.TMPDIR;
let ext = 'png';
let tmpoutput = (0, path_1.join)(tmppath, `${state.hash}-export-%08d.${ext}`);
let args;
let output;
let estimated = -1;
//cmd = `${this.bin} -y -i "${video}" -vf "${scale}" -compression_algo raw -pix_fmt rgb24 -crf 0 "${tmpoutput}"`;
args = [
'-y',
'-i', video
];
if (w && h) {
args.push('-vf');
args.push(`scale=${w}:${h}`);
}
args = args.concat([
'-compression_algo', 'raw',
'-pix_fmt', 'rgb24',
'-crf', '0',
tmpoutput
]);
//console.dir(args)
//console.dir(state)
try {
await (0, fs_extra_1.mkdir)(tmppath);
}
catch (err) {
if (err.code && err.code === 'EEXIST') {
//directory exists
}
else {
this.log.error(err);
}
}
//ffmpeg -i "${video}" -compression_algo raw -pix_fmt rgb24 "${tmpoutput}"
return new Promise((resolve, reject) => {
let stdout = '';
let stderr = '';
this.log.info(`${this.bin} ${args.join(' ')}`);
this.child = (0, child_process_1.spawn)(this.bin, args);
this.child.on('exit', (code) => {
//console.log('GOT TO EXIT');
if (code === 0) {
console.log(stderr);
console.log(stdout);
return resolve(true);
}
else {
console.error(`Process exited with code: ${code}`);
console.error(stderr);
return reject(stderr + stdout);
}
});
this.child.stdout.on('data', (data) => {
const line = data.toString();
stdout += line;
});
this.child.stderr.on('data', (data) => {
const line = data.toString();
const obj = this.parseStderr(line);
if (obj.frame && state.frames) {
obj.progress = obj.frame / state.frames;
}
if (obj.frame && obj.speed && state.frames && state.info.fps) {
//scale by speed
obj.remaining = ((state.frames - obj.frame) / state.info.fps) / obj.speed;
obj.estimated = state.info.seconds / obj.speed;
if (obj.estimated > estimated) {
estimated = obj.estimated;
}
}
if (obj.frame) {
//log.info(`${input.name} ${obj.frame}/${input.frames} ${Math.round(obj.progress * 1000) / 10}% ${Math.round(obj.remaining)} seconds remaining of ${Math.round(obj.estimated)}`);
this.onProgress(obj);
}
});
});
}
cancel() {
if (this.child) {
this.child.kill();
this.log.info(`Stopped exporting sequence with ffmpeg`);
}
}
/**
* Clears a specific frame from the tmp directory
*
* @param {integer} frame Integer of frame to clear
*
* @returns {boolean} True if successful, false if not
**/
async clear(state) {
const padded = this.padded_frame(state.frame);
let ext = 'png';
let tmppath;
let fileExists;
tmppath = (0, path_1.join)(this.TMPDIR, `${state.hash}-export-${padded}.${ext}`);
try {
fileExists = await (0, fs_extra_1.exists)(tmppath);
}
catch (err) {
this.log.error(err);
}
if (!fileExists)
return false;
try {
await (0, fs_extra_1.unlink)(tmppath);
this.log.info(`Cleared frame ${tmppath}`);
}
catch (err) {
this.log.error(err);
}
return true;
}
/**
* Deletes all frames in temp directory.
*
**/
async clearAll() {
const tmppath = this.TMPDIR;
let files;
try {
files = await (0, fs_extra_1.readdir)(tmppath);
}
catch (err) {
this.log.error(err);
}
files = files.filter((file) => {
if (file.indexOf('-export-') !== -1) {
return true;
}
return false;
});
if (files) {
files.forEach(async (file, index) => {
try {
await (0, fs_extra_1.unlink)((0, path_1.join)(tmppath, file));
}
catch (err) {
this.log.error(err);
}
});
}
}
/**
* Checks if mcopy temp directory exists. If it doesn't,
* creates it.
**/
async checkDir() {
let fileExists;
try {
fileExists = await (0, fs_extra_1.exists)(this.TMPDIR);
}
catch (err) {
this.log.error('Error checking for tmp dir', err);
}
if (!fileExists) {
try {
await (0, fs_extra_1.mkdir)(this.TMPDIR);
this.log.info(`Created tmpdir ${this.TMPDIR}`);
}
catch (err) {
this.log.error('Error creating tmp dir', err);
}
}
try {
await this.clearAll();
}
catch (err) {
this.log.error(err);
}
}
}
async function frames (video, obj) {
let tmppath = TMPDIR;
let ext = 'tif';
let tmpoutput;
if (system.platform !== 'nix') {
ext = 'png';
}
tmpoutput = path.join(tmppath, `export-%05d.${ext}`);
try {
await fs.mkdir(tmppath)
} catch (Err) {
console.error(err);
}
//ffmpeg -i "${video}" -compression_algo raw -pix_fmt rgb24 "${tmpoutput}"
}
async function clear (frame) {
let padded = padded_frame(frame);
let ext = 'tif';
let tmppath;
let tmpoutput;
let cmd;
let exists;
if (system.platform !== 'nix') {
ext = 'png';
}
tmppath = path.join(TMPDIR, `export-${padded}.${ext}`);
try {
exists = await fs.exists(tmppath);
} catch (err) {
console.error(err);
}
if (!exists) return false;
try {
await fs.unlink(tmppath);
console.log(`Cleared frame ${tmppath}`);
} catch (err) {
console.error(err);
}
return true;
}
async function clearAll () {
let tmppath = TMPDIR;
let files;
try {
files = await fs.readdir(tmppath);
} catch (err) {
console.error(err);
}
if (files) {
files.forEach(async (file, index) => {
try {
await fs.unlink(path.join(tmppath, file));
} catch (err) {
console.error(err);
}
});
}
}
async function checkDir () {
let exists;
try {
exists = await fs.exists(TMPDIR);
} catch (err) {
console.error('Error checking for tmp dir', err);
}
if (!exists) {
try {
await fs.mkdir(TMPDIR);
console.log(`Created tmpdir ${TMPDIR}`);
} catch (err) {
console.error('Error creating tmp dir', err);
}
}
try {
await clearAll();
} catch (err) {
console.error(err);
}
}
module.exports = (sys) => {
system = sys;
TMPDIR = path.join(system.tmp, 'mcopy_digital');
checkDir();
return {
frames,
frame,
clear,
clearAll
}
}
return new FFMPEG(sys);
};
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

1
app/lib/ffprobe/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export {};

View File

@ -1,104 +1,144 @@
'use strict';
const fs = require('fs-extra');
const exec = require('exec');
Object.defineProperty(exports, "__esModule", { value: true });
/** @module FFPROBE **/
const fs_extra_1 = require("fs-extra");
const path_1 = require("path");
const exec_1 = require("exec");
//const spawn = require('spawn');
//const exit = require('exit');
let system = {};
async function info (video) {
let cmd = `ffprobe -v quiet -print_format json -show_format -show_streams "${video}"`
let exists;
let raw;
let json;
let vid;
try {
exists = await fs.exists(video);
} catch (err) {
return exit(err, 5);
}
if (!exists) {
//return exit(`File ${video} does not exist`, 6);
console.error(err);
return false
}
try {
console.log(cmd);
raw = await exec(cmd);
} catch (err) {
//return exit(err, 7);
console.error(err);
return false
}
try {
json = JSON.parse(raw.stdout);
} catch (err) {
return raw.stdout;
}
if (json && json.streams) {
vid = json.streams.find(stream => {
if (stream.width && stream.height) return stream;
});
}
if (vid) {
json.width = vid.width;
json.height = vid.height;
}
return json;
class FFPROBE {
constructor(sys) {
this.bin = sys.deps.ffprobe;
}
/**
* Parse the fps entry into a float representing the fps of a video
**/
parseFps(fpsStr) {
let fps = 30.0;
let parts;
if (fpsStr.indexOf('/') !== -1) {
parts = fpsStr.split('/');
fps = parseFloat(parts[0]) / parseFloat(parts[1]);
}
else {
fps = parseFloat(fpsStr);
}
return fps;
}
/**
* Get info on a video in json format. Use for filmout.
*
* @param {string} video Path to video
*
* @returns {object} Video info in an object
**/
async info(video) {
const cmd = `${this.bin} -v quiet -print_format json -show_format -show_streams "${video}"`;
let fileExists;
let raw;
let json;
let vid; //whether video has stream with video data
try {
fileExists = await (0, fs_extra_1.exists)(video);
}
catch (err) {
return exit(err, 5);
}
if (!fileExists) {
//return exit(`File ${video} does not exist`, 6);
console.error(new Error(`File ${video} does not exist`));
return false;
}
try {
console.log(cmd);
raw = await (0, exec_1.exec)(cmd);
}
catch (err) {
//return exit(err, 7);
console.error(err);
return false;
}
try {
json = JSON.parse(raw.stdout);
}
catch (err) {
return raw.stdout;
}
if (json.format && json.format.duration) {
json.seconds = parseFloat(json.format.duration);
}
if (json && json.streams) {
vid = json.streams.find((stream) => {
if (stream.width && stream.height)
return stream;
});
}
if (vid) {
json.width = vid.width;
json.height = vid.height;
json.fps = this.parseFps(vid.r_frame_rate);
}
return json;
}
/**
* Count the number of frames in the video using one of two methods.
* The first uses -select_streams and is very fast. The second uses
* -count_frames and is VERY slow.
*
* @param {string} video Path to video
*
* @returns {integer} Number of frames in video
**/
async frames(video) {
const ext = (0, path_1.extname)(video.toLowerCase());
let cmd = `${this.bin} -v error -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 "${video}"`;
let backup_cmd = `${this.bin} -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 "${video}"`;
let gif_cmd = `identify -format "%n\n" "${video}" | head -1`;
let fileExists;
let raw;
let frames;
try {
fileExists = await (0, fs_extra_1.exists)(video);
}
catch (err) {
//return exit(err, 5);
console.error(err);
return false;
}
if (!fileExists) {
//return exit(`File ${video} does not exist`, 6);
console.error(new Error(`File ${video} does not exist`));
return false;
}
if (ext === '.mkv') {
cmd = backup_cmd;
}
else if (ext === '.gif') {
cmd = gif_cmd;
}
try {
console.log(cmd);
raw = await (0, exec_1.exec)(cmd);
}
catch (err) {
console.error(err);
return false;
}
try {
frames = parseInt(raw.stdout);
}
catch (err) {
return raw.stdout;
}
return frames;
}
}
async function frames (video) {
let cmd = `ffprobe -v error -count_frames -select_streams v:0 -show_entries stream=nb_read_frames -of default=nokey=1:noprint_wrappers=1 "${video}"`;
let exists;
let raw;
let frames;
try {
exists = await fs.exists(video);
} catch (err) {
//return exit(err, 5);
console.error(err);
return false
}
if (!exists) {
//return exit(`File ${video} does not exist`, 6);
console.error(err);
return false;
}
try {
console.log(cmd);
raw = await exec(cmd);
} catch (err) {
console.error(err);
return false;
}
try {
frames = parseInt(raw.stdout)
} catch (err) {
return raw.stdout;
}
return frames;
/*
function map (obj : any) {
console.dir(obj);
}
function map (obj) {
console.dir(obj);
}
*/
module.exports = (sys) => {
system = sys;
return {
info,
frames
}
}
return new FFPROBE(sys);
};
//# sourceMappingURL=index.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ffprobe/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,uBAAuB;AAEvB,uCAAkC;AAClC,+BAA+B;AAC/B,+BAA4B;AAC5B,iCAAiC;AACjC,+BAA+B;AAE/B,MAAM,OAAO;IAGZ,YAAa,GAAS;QACrB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC;IAC7B,CAAC;IAED;;QAEI;IACI,QAAQ,CAAE,MAAe;QAChC,IAAI,GAAG,GAAY,IAAI,CAAC;QACxB,IAAI,KAAgB,CAAC;QACrB,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE;YAC/B,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC1B,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;SAClD;aAAM;YACN,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;SACzB;QACD,OAAO,GAAG,CAAA;IACX,CAAC;IACD;;;;;;QAMI;IACG,KAAK,CAAC,IAAI,CAAE,KAAc;QAChC,MAAM,GAAG,GAAY,GAAG,IAAI,CAAC,GAAG,4DAA4D,KAAK,GAAG,CAAA;QACpG,IAAI,UAAoB,CAAC;QACzB,IAAI,GAAS,CAAC;QACd,IAAI,IAAU,CAAC;QACf,IAAI,GAAS,CAAC,CAAC,0CAA0C;QAEzD,IAAI;YACH,UAAU,GAAG,MAAM,IAAA,iBAAM,EAAC,KAAK,CAAC,CAAC;SACjC;QAAC,OAAO,GAAG,EAAE;YACb,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;SACpB;QACD,IAAI,CAAC,UAAU,EAAE;YAChB,iDAAiD;YACjD,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,KAAK,iBAAiB,CAAC,CAAC,CAAC;YACzD,OAAO,KAAK,CAAA;SACZ;QAED,IAAI;YACH,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACjB,GAAG,GAAG,MAAM,IAAA,WAAI,EAAC,GAAG,CAAC,CAAC;SACtB;QAAC,OAAO,GAAG,EAAE;YACb,sBAAsB;YACtB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACnB,OAAO,KAAK,CAAA;SACZ;QAED,IAAI;YACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;SAC9B;QAAC,OAAO,GAAG,EAAE;YACb,OAAO,GAAG,CAAC,MAAM,CAAC;SAClB;QAED,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE;YACxC,IAAI,CAAC,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;SAChD;QAED,IAAI,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE;YACzB,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAY,EAAE,EAAE;gBACxC,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM;oBAAE,OAAO,MAAM,CAAC;YAClD,CAAC,CAAC,CAAC;SACH;QAED,IAAI,GAAG,EAAE;YACR,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;YACvB,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC;YACzB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;SAC1C;QAED,OAAO,IAAI,CAAC;IACb,CAAC;IACD;;;;;;;;QAQI;IACG,KAAK,CAAC,MAAM,CAAE,KAAc;QAClC,MAAM,GAAG,GAAY,IAAA,cAAO,EAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;QAClD,IAAI,GAAG,GAAY,GAAG,IAAI,CAAC,GAAG,wGAAwG,KAAK,GAAG,CAAC;QAC/I,IAAI,UAAU,GAAY,GAAG,IAAI,CAAC,GAAG,2HAA2H,KAAK,GAAG,CAAC;QACzK,IAAI,OAAO,GAAY,4BAA4B,KAAK,aAAa,CAAA;QACrE,IAAI,UAAoB,CAAC;QACzB,IAAI,GAAS,CAAC;QACd,IAAI,MAAe,CAAC;QAEpB,IAAI;YACH,UAAU,GAAG,MAAM,IAAA,iBAAM,EAAC,KAAK,CAAC,CAAC;SACjC;QAAC,OAAO,GAAG,EAAE;YACb,sBAAsB;YACtB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACnB,OAAO,KAAK,CAAA;SACZ;QACD,IAAI,CAAC,UAAU,EAAE;YAChB,iDAAiD;YACjD,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,KAAK,iBAAiB,CAAC,CAAC,CAAC;YACzD,OAAO,KAAK,CAAC;SACb;QAED,IAAI,GAAG,KAAK,MAAM,EAAE;YACnB,GAAG,GAAG,UAAU,CAAC;SACjB;aAAM,IAAI,GAAG,KAAK,MAAM,EAAE;YAC1B,GAAG,GAAG,OAAO,CAAC;SACd;QACD,IAAI;YACH,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACjB,GAAG,GAAG,MAAM,IAAA,WAAI,EAAC,GAAG,CAAC,CAAC;SACtB;QAAC,OAAO,GAAG,EAAE;YACb,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACnB,OAAO,KAAK,CAAC;SACb;QAED,IAAI;YACH,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;SAC9B;QAAC,OAAO,GAAG,EAAE;YACb,OAAO,GAAG,CAAC,MAAM,CAAC;SAClB;QAED,OAAO,MAAM,CAAC;IACf,CAAC;CACD;AAED;;;;EAIE;AAEF,MAAM,CAAC,OAAO,GAAG,CAAC,GAAS,EAAE,EAAE;IAC9B,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC,CAAA"}

44
app/lib/filmout/Readme.md Normal file
View File

@ -0,0 +1,44 @@
<a name="Digital"></a>
## Digital
**Kind**: global class
* [Digital](#Digital)
* [.init()](#Digital+init)
* [.listen()](#Digital+listen)
* [.set()](#Digital+set)
* [.move()](#Digital+move)
* [.start()](#Digital+start)
* [.end()](#Digital+end)
* [.connectDigital()](#Digital+connectDigital)
<a name="Digital+init"></a>
### digital.init()
**Kind**: instance method of [<code>Digital</code>](#Digital)
<a name="Digital+listen"></a>
### digital.listen()
**Kind**: instance method of [<code>Digital</code>](#Digital)
<a name="Digital+set"></a>
### digital.set()
**Kind**: instance method of [<code>Digital</code>](#Digital)
<a name="Digital+move"></a>
### digital.move()
**Kind**: instance method of [<code>Digital</code>](#Digital)
<a name="Digital+start"></a>
### digital.start()
**Kind**: instance method of [<code>Digital</code>](#Digital)
<a name="Digital+end"></a>
### digital.end()
**Kind**: instance method of [<code>Digital</code>](#Digital)
<a name="Digital+connectDigital"></a>
### digital.connectDigital()
Use a file as the "digital" source on "projector"
**Kind**: instance method of [<code>Digital</code>](#Digital)

1
app/lib/filmout/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export {};

504
app/lib/filmout/index.js Normal file
View File

@ -0,0 +1,504 @@
'use strict';
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const animated_gif_detector_1 = __importDefault(require("animated-gif-detector"));
const path_1 = require("path");
const fs_extra_1 = require("fs-extra");
const delay_1 = require("delay");
const crypto_1 = require("crypto");
const frame_1 = __importDefault(require("frame"));
/**
* @module FilmOut
**/
class FilmOut {
/**
* @constructor
* Builds FilmOut class with display, ffmpeg, ffprobe, ui and light as internal properties.
*
* @param {object} display Display object for showing frames
* @param {object} ffmpeg FFMPEG wrapper
* @param {object} ffprobe FFPROBE wrapper for file info
* @param {object} ui Electron ui object
* @param {object} light Light device object
**/
constructor(display, server, ffmpeg, ffprobe, ui, light) {
this.id = 'filmout';
this.videoExtensions = ['.mpg', '.mpeg', '.mov', '.mkv', '.avi', '.mp4'];
this.stillExtensions = ['.tif', '.tiff', '.png', '.jpg', '.jpeg', '.bmp'];
this.sequenceExtensions = ['.png', '.jpg', '.jpeg'];
this.gifExtension = '.gif';
this.state = {
frame: 0,
frames: 0,
still: false,
path: null,
fileName: null,
directory: false,
info: {},
dir: true,
enabled: false,
files: []
};
this.display = display;
this.server = server;
this.ffmpeg = ffmpeg;
this.ffprobe = ffprobe;
this.ui = ui;
this.light = light;
this.init();
}
/**
* Async function for requiring log, ipcMain and bind events.
**/
async init() {
const Log = require('log');
this.log = await Log({ label: this.id });
this.ipc = require('electron').ipcMain;
this.listen();
}
/**
*
**/
listen() {
this.ipc.on(this.id, this.onConnect.bind(this));
this.ipc.on('focus', this.focus.bind(this));
this.ipc.on('field', this.field.bind(this));
this.ipc.on('meter', this.meter.bind(this));
this.ipc.on('filmout_close', this.close.bind(this));
this.ipc.on('preview', this.preview.bind(this));
this.ipc.on('preview_frame', this.previewFrame.bind(this));
this.ipc.on('display', this.onDisplay.bind(this));
this.ipc.on('pre_export', this.onPreExport.bind(this));
this.ffmpeg.onProgress = (obj) => {
this.ui.send('pre_export_progress', { progress: obj });
};
}
/**
* Create a hash of a string.
*
* @param {string} data Data to produce hash of
*/
hash(data) {
return (0, crypto_1.createHash)('sha1').update(data).digest('hex');
}
/**
* Sets filmout direction.
*
* @param {boolean} dir Direction of filmout
**/
set(dir) {
this.state.dir = dir;
}
/**
* Moves filmout a frame at a time.
*
* @returns {number} Time since start
**/
async move() {
let start = +new Date();
if (this.state.still) {
return -1;
}
if (this.state.dir) {
this.state.frame++;
}
else {
this.state.frame--;
}
if (this.state.frame < 1) {
this.state.frame = 1;
}
return (+new Date()) - start;
}
/**
* Begin the process of exporting single frames from the video for display.
**/
async start() {
let path;
try {
path = await this.ffmpeg.frame(this.state, this.light.state);
}
catch (err) {
this.log.error(err, 'FILMOUT', true, true);
throw err;
}
if (this.server.displayImage(path)) {
await (0, delay_1.delay)(20);
return;
}
await this.display.show(path);
await (0, delay_1.delay)(20);
}
/**
* Ends the filmout process and closes the display.
**/
async end() {
await (0, delay_1.delay)(20);
this.display.hide();
}
/**
* Use a video file as a film out source on "projector"
*
* @param {object} evt Original connect event
* @param {object} arg Arguments from ipc message
*
* @returns {boolean} Success state
**/
async onConnect(evt, arg) {
let frames = 0;
let isAnimated = false;
let info;
let ext;
let stats;
let frameList;
try {
stats = await (0, fs_extra_1.lstat)(arg.path);
}
catch (err) {
this.log.error(err, 'FILMOUT', true, true);
return false;
}
ext = (0, path_1.extname)(arg.fileName.toLowerCase());
if (stats.isDirectory()) {
this.state.directory = true;
this.state.still = false;
}
else if (ext === this.gifExtension) {
try {
isAnimated = await this.isGifAnimated(arg.path);
}
catch (err) {
this.log.error(err, 'FILMOUT', true, true);
await this.ui.send(this.id, { valid: false });
return false;
}
this.state.still = !isAnimated;
}
else if (this.stillExtensions.indexOf(ext) !== -1) {
this.state.still = true;
this.state.directory = false;
}
else if (this.videoExtensions.indexOf(ext) !== -1) {
this.state.still = false;
this.state.directory = false;
}
else {
this.log.error(`File is not of a valid file type`, 'FILMOUT', true, true);
return false;
}
try {
await this.ffmpeg.clearAll();
}
catch (err) {
this.log.error(err, 'FILMOUT', true, true);
throw err;
}
if (this.state.directory) {
try {
frameList = await this.dirList(arg.path);
}
catch (err) {
this.log.error(err, 'FILMOUT', true, true);
this.state.enabled = false;
await this.ui.send(this.id, { valid: false });
return false;
}
try {
info = await this.dirInfo(frameList);
}
catch (err) {
this.log.error(err, 'FILMOUT', true, true);
this.state.enabled = false;
await this.ui.send(this.id, { valid: false });
return false;
}
frames = frameList.length;
this.state.files = frameList;
}
else if (this.state.still) {
try {
info = await this.stillInfo(arg.path);
}
catch (err) {
this.log.error(err, 'FILMOUT', true, true);
this.state.enabled = false;
await this.ui.send(this.id, { valid: false });
return false;
}
frames = 1;
}
else {
try {
info = await this.ffprobe.info(arg.path);
}
catch (err) {
this.log.error(err, 'FILMOUT', true, true);
this.state.enabled = false;
await this.ui.send(this.id, { valid: false });
return false;
}
try {
frames = await this.ffprobe.frames(arg.path);
}
catch (err) {
this.log.error(err, 'FILMOUT', true, true);
this.state.enabled = false;
await this.ui.send(this.id, { valid: false });
return false;
}
}
this.state.frame = 0;
this.state.path = arg.path;
this.state.fileName = arg.fileName;
this.state.frames = frames;
this.state.info = info;
this.state.hash = this.hash(arg.path);
if (info.fps) {
this.state.fps = info.fps;
}
else {
this.state.fps = 24; //default
}
if (info.seconds) {
this.state.seconds = info.seconds;
}
else if (info.fps && frames) {
this.state.seconds = frames / info.fps;
}
else if (this.state.directory) {
this.state.seconds = frames / 24;
}
this.log.info(`Opened ${this.state.fileName}`, 'FILMOUT', true, true);
this.log.info(`Frames : ${frames}`, 'FILMOUT', true, true);
this.state.enabled = true;
await this.ui.send(this.id, { valid: true, state: JSON.stringify(this.state) });
return true;
}
/**
* Pre-export all frames from video for display.
*
* @param {object} evt IPC event
* @param {object} arg IPC args
*
* @returns {any} UI send call
*/
async onPreExport(evt, arg) {
if (!this.state.path) {
return await this.ui.send('pre_export', { complete: false, err: 'No file to pre export.' });
}
try {
await this.ffmpeg.frames(this.state);
}
catch (err) {
return await this.ui.send('pre_export', { complete: false, err });
}
return await this.ui.send('pre_export', { complete: true });
}
/**
* Return true if gif is animated, false if it is a still
*
* @param {string} pathStr Path to gif to check
*
* @returns {boolean} Whether or not gif is animated
**/
async isGifAnimated(pathStr) {
let gifBuffer;
try {
gifBuffer = await (0, fs_extra_1.readFile)(pathStr);
}
catch (err) {
this.log.error(err, 'FILMOUT', true, true);
return false;
}
return (0, animated_gif_detector_1.default)(gifBuffer);
}
/**
* Return information on a still image using the Jimp module
*
* @param {string} pathStr Path to gif to check
*
* @returns {object} Info about still from sharp
**/
async stillInfo(pathStr) {
let info;
try {
info = await frame_1.default.info(pathStr);
}
catch (err) {
this.log.error(err, 'FILMOUT', true, true);
}
return info;
}
/**
* Return information on the first still image found in a
* directory using the Jimp module.
*
* @param {array} images List of image paths
*
* @returns {object} Info about first image
**/
async dirInfo(images) {
let info;
try {
info = await this.stillInfo(images[0]);
}
catch (err) {
this.log.error(err, 'FILMOUT', true, true);
}
return info;
}
/**
* Returns a list of images within a directory, filtered
* for supported types and sorted.
*
* @param {string} pathStr Path to directory
*
* @returns {array} Array of image paths
**/
async dirList(pathStr) {
let frameList = [];
try {
frameList = await (0, fs_extra_1.readdir)(pathStr);
}
catch (err) {
this.log.error(err, 'FILMOUT', true, true);
}
frameList = frameList.filter((fileName) => {
let ext = (0, path_1.extname)(fileName);
if (this.sequenceExtensions.indexOf(ext) !== -1) {
return true;
}
return false;
});
frameList.sort();
frameList = frameList.map((fileName) => {
return (0, path_1.join)(pathStr, fileName);
});
return frameList;
}
/**
* Preview a frame from the selected video.
*
* @param {object} evt Original event
* @param {object} arg Arguments from message
**/
async previewFrame(evt, arg) {
const state = JSON.parse(JSON.stringify(this.state));
let path;
state.frame = arg.frame;
try {
path = await this.ffmpeg.frame(state, { color: [255, 255, 255] });
}
catch (err) {
this.log.error(err, 'FILMOUT', true, true);
throw err;
}
this.ui.send('preview_frame', { path, frame: arg.frame });
}
/**
* Open a single frame in a display window to preview filmout.
*
* @param {object} evt Original event
* @param {object} arg Arguments from message
**/
async preview(evt, arg) {
const state = JSON.parse(JSON.stringify(this.state));
let path;
state.frame = arg.frame;
this.log.info(`Previewing frame ${state.frame} of ${state.fileName}`);
try {
path = await this.ffmpeg.frame(state, { color: [255, 255, 255] });
}
catch (err) {
this.log.error(err, 'FILMOUT', true, true);
throw err;
}
try {
if (await this.server.displayImage(path)) {
return;
}
await this.display.open();
await this.display.show(path);
}
catch (err) {
this.log.error(err, 'FILMOUT', true, true);
}
}
/**
*
**/
async focus(evt, arg) {
this.log.info(`Showing focus screen`);
try {
if (await this.server.cmdAll('focus')) {
return;
}
await this.display.open();
await this.display.focus();
}
catch (err) {
this.log.error(err, 'FILMOUT', true, true);
}
}
/**
*
**/
async field(evt, arg) {
const ratio = arg.ratio;
this.log.info(`Showing field guide screen`);
try {
if (await this.server.cmdAll('field', { ratio })) {
return;
}
await this.display.open();
await this.display.field(ratio);
}
catch (err) {
this.log.error(err, 'FILMOUT', true, true);
}
}
/**
*
**/
async meter(evt, arg) {
this.log.info(`Showing meter screen`);
try {
if (await this.server.cmdAll('meter')) {
return;
}
await this.display.open();
await this.display.meter();
}
catch (err) {
this.log.error(err, 'FILMOUT', true, true);
}
}
/**
*
**/
async close(evt, arg) {
try {
if (await this.server.cmdAll('blank')) {
return;
}
await this.display.hide();
await this.display.close();
}
catch (err) {
this.log.error(err, 'FILMOUT', true, true);
}
}
/**
*
**/
onDisplay(evt, arg) {
this.display.change(arg.display);
this.log.info(`Changing the display to ${arg.display}`);
}
}
module.exports = (display, server, ffmpeg, ffprobe, ui, light) => {
return new FilmOut(display, server, ffmpeg, ffprobe, ui, light);
};
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,11 @@
{
"name": "digital",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

15
app/lib/frame/index.d.ts vendored Normal file
View File

@ -0,0 +1,15 @@
interface RGBA {
r: number;
g: number;
b: number;
a: number;
}
export default class Frame {
static info(imagePath: string): Promise<{
width: any;
height: any;
}>;
static solidColor(width: number, height: number, color: RGBA): Promise<unknown>;
static blend(inPath: any, color: RGBA, imagePath: string): Promise<string>;
}
export {};

70
app/lib/frame/index.js Normal file
View File

@ -0,0 +1,70 @@
'use strict';
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const jimp_1 = __importDefault(require("jimp"));
class Frame {
static async info(imagePath) {
let image;
try {
image = await jimp_1.default.read(imagePath);
}
catch (err) {
throw err;
}
return {
width: image.bitmap.width,
height: image.bitmap.height
};
}
static async solidColor(width, height, color) {
//@ts-ignore
const colorInt = jimp_1.default.rgbaToInt(color.r, color.g, color.b, color.a);
return new Promise((resolve, reject) => {
return new jimp_1.default(width, height, colorInt, (err, image) => {
if (err) {
return reject(err);
}
return resolve(image);
});
});
}
static async blend(inPath, color, imagePath) {
//cmd2 = `${this.convert} "${tmpoutput}" -resize ${w}x${h} -size ${w}x${h} xc:"rgb(${rgb[0]},${rgb[1]},${rgb[2]})" +swap -compose Darken -composite "${tmpoutput}"`;
const options = {
mode: jimp_1.default.BLEND_DARKEN,
opacitySource: 1.0,
opacityDest: 1.0
};
let width;
let height;
let bottom;
let top;
try {
top = await jimp_1.default.read(inPath);
}
catch (err) {
throw err;
}
width = top.bitmap.width;
height = top.bitmap.height;
try {
bottom = await Frame.solidColor(width, height, color);
}
catch (err) {
throw err;
}
bottom.composite(top, 0, 0, options);
try {
await bottom.writeAsync(imagePath);
}
catch (err) {
throw err;
}
return imagePath;
}
}
exports.default = Frame;
module.exports = Frame;
//# sourceMappingURL=index.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/frame/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;AAEb,gDAAwB;AASxB,MAAqB,KAAK;IACzB,MAAM,CAAC,KAAK,CAAC,IAAI,CAAE,SAAkB;QACpC,IAAI,KAAW,CAAC;QAChB,IAAI;YACH,KAAK,GAAG,MAAM,cAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;SACnC;QAAC,OAAO,GAAG,EAAE;YACb,MAAM,GAAG,CAAC;SACV;QACD,OAAO;YACN,KAAK,EAAG,KAAK,CAAC,MAAM,CAAC,KAAK;YAC1B,MAAM,EAAG,KAAK,CAAC,MAAM,CAAC,MAAM;SAC5B,CAAC;IACH,CAAC;IACD,MAAM,CAAC,KAAK,CAAC,UAAU,CAAE,KAAc,EAAE,MAAe,EAAE,KAAY;QACrE,YAAY;QACZ,MAAM,QAAQ,GAAY,cAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;QAC7E,OAAO,IAAI,OAAO,CAAC,CAAC,OAAkB,EAAE,MAAiB,EAAE,EAAE;YAC5D,OAAO,IAAI,cAAI,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;gBACrD,IAAI,GAAG,EAAE;oBACR,OAAO,MAAM,CAAC,GAAG,CAAC,CAAA;iBAClB;gBACD,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;YACzB,CAAC,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,KAAK,CAAE,MAAY,EAAE,KAAY,EAAE,SAAkB;QACjE,oKAAoK;QACpK,MAAM,OAAO,GAAS;YACrB,IAAI,EAAE,cAAI,CAAC,YAAY;YACvB,aAAa,EAAE,GAAG;YAClB,WAAW,EAAE,GAAG;SAChB,CAAC;QACF,IAAI,KAAc,CAAC;QACnB,IAAI,MAAe,CAAC;QACpB,IAAI,MAAY,CAAC;QACjB,IAAI,GAAS,CAAC;QAEd,IAAI;YACH,GAAG,GAAG,MAAM,cAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;SAC9B;QAAC,OAAO,GAAG,EAAE;YACb,MAAM,GAAG,CAAC;SACV;QAED,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC;QACzB,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC;QAE3B,IAAI;YACH,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;SACtD;QAAC,OAAO,GAAG,EAAE;YACb,MAAM,GAAG,CAAC;SACV;QAED,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;QAErC,IAAI;YACH,MAAM,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;SACnC;QAAC,OAAO,GAAG,EAAE;YACb,MAAM,GAAG,CAAC;SACV;QAED,OAAO,SAAS,CAAC;IAClB,CAAC;CACD;AA/DD,wBA+DC;AAED,MAAM,CAAC,OAAO,GAAG,KAAK,CAAA"}

View File

@ -0,0 +1,11 @@
{
"name": "frame",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

0
app/lib/intval/Readme.md Normal file
View File

9
app/lib/intval/index.d.ts vendored Normal file
View File

@ -0,0 +1,9 @@
export declare class Intval {
private _baseUrl;
private req;
constructor(url: string);
move(): Promise<unknown>;
setDir(dir: boolean): Promise<unknown>;
setExposure(exposure: number, cb: Function): Promise<unknown>;
connect(cb: Function): void;
}

View File

@ -1,71 +1,71 @@
'use strict'
const req = require('request')
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.Intval = void 0;
class Intval {
constructor (url) {
this._baseUrl = `http://${url}`
}
async move () {
return new Promise ((resolve, reject) => {
const timeStart = +new Date()
const url = `${this._baseUrl}/frame`
//console.log(url)
return req(url, (err, res, body) => {
let ms = (+new Date()) - timeStart
if (err) {
return reject(err)
}
return resolve(ms)
})
})
}
async setDir (dir) {
return new Promise ((resolve, reject) => {
const timeStart = +new Date()
const url = `${this._baseUrl}/dir?dir=${dir}`
//console.log(url)
return req(url, (err, res, body) => {
let ms = (+new Date()) - timeStart
if (err) {
return reject(err)
}
return resolve(ms)
})
})
}
async setExposure (exposure, cb) {
return new Promise ((resolve, reject) => {
const timeStart = +new Date()
const url = `${this._baseUrl}/exposure?exposure=${exposure}`
//console.log(url)
return req(url, (err, res, body) => {
let ms = (+new Date()) - timeStart
if (err) {
return reject(err)
}
return resolve(ms)
})
})
}
connect (cb) {
const timeStart = +new Date()
const url = `${this._baseUrl}/status`
const opts = {
method : 'GET',
uri : url,
timeout: 5000
}
req(opts, (err, res, body) => {
let ms = (+new Date()) - timeStart
if (err) {
//console.error(err)
return cb(err, ms)
}
cb(null, ms, body)
})
}
constructor(url) {
this._baseUrl = `http://${url}`;
this.req = require('request');
}
async move() {
return new Promise((resolve, reject) => {
const timeStart = +new Date();
const url = `${this._baseUrl}/frame`;
//console.log(url)
return this.req(url, (err, res, body) => {
let ms = (+new Date()) - timeStart;
if (err) {
return reject(err);
}
return resolve(ms);
});
});
}
async setDir(dir) {
return new Promise((resolve, reject) => {
const timeStart = +new Date();
const url = `${this._baseUrl}/dir?dir=${dir}`;
//console.log(url)
return this.req(url, (err, res, body) => {
let ms = (+new Date()) - timeStart;
if (err) {
return reject(err);
}
return resolve(ms);
});
});
}
async setExposure(exposure, cb) {
return new Promise((resolve, reject) => {
const timeStart = +new Date();
const url = `${this._baseUrl}/exposure?exposure=${exposure}`;
//console.log(url)
return this.req(url, (err, res, body) => {
let ms = (+new Date()) - timeStart;
if (err) {
return reject(err);
}
return resolve(ms);
});
});
}
connect(cb) {
const timeStart = +new Date();
const url = `${this._baseUrl}/status`;
const opts = {
method: 'GET',
uri: url,
timeout: 5000
};
this.req(opts, (err, res, body) => {
let ms = (+new Date()) - timeStart;
if (err) {
//console.error(err)
return cb(err, ms);
}
cb(null, ms, body);
});
}
}
module.exports = Intval
exports.Intval = Intval;
module.exports.Intval = Intval;
//# sourceMappingURL=index.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/intval/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAA;;;AAEZ,MAAa,MAAM;IAGlB,YAAa,GAAY;QACxB,IAAI,CAAC,QAAQ,GAAG,UAAU,GAAG,EAAE,CAAA;QAC/B,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,SAAS,CAAC,CAAA;IAC9B,CAAC;IACM,KAAK,CAAC,IAAI;QAChB,OAAO,IAAI,OAAO,CAAE,CAAC,OAAa,EAAE,MAAY,EAAE,EAAE;YACnD,MAAM,SAAS,GAAY,CAAC,IAAI,IAAI,EAAE,CAAA;YACtC,MAAM,GAAG,GAAY,GAAG,IAAI,CAAC,QAAQ,QAAQ,CAAA;YAC7C,kBAAkB;YAClB,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAW,EAAE,GAAS,EAAE,IAAa,EAAE,EAAE;gBAC9D,IAAI,EAAE,GAAY,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,GAAG,SAAS,CAAA;gBAC3C,IAAI,GAAG,EAAE;oBACR,OAAO,MAAM,CAAC,GAAG,CAAC,CAAA;iBAClB;gBACD,OAAO,OAAO,CAAC,EAAE,CAAC,CAAA;YACnB,CAAC,CAAC,CAAA;QACH,CAAC,CAAC,CAAA;IACH,CAAC;IACM,KAAK,CAAC,MAAM,CAAE,GAAa;QACjC,OAAO,IAAI,OAAO,CAAE,CAAC,OAAa,EAAE,MAAY,EAAE,EAAE;YACnD,MAAM,SAAS,GAAY,CAAC,IAAI,IAAI,EAAE,CAAA;YACtC,MAAM,GAAG,GAAY,GAAG,IAAI,CAAC,QAAQ,YAAY,GAAG,EAAE,CAAA;YACtD,kBAAkB;YAClB,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAW,EAAE,GAAS,EAAE,IAAa,EAAE,EAAE;gBAC9D,IAAI,EAAE,GAAY,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,GAAG,SAAS,CAAA;gBAC3C,IAAI,GAAG,EAAE;oBACR,OAAO,MAAM,CAAC,GAAG,CAAC,CAAA;iBAClB;gBACD,OAAO,OAAO,CAAC,EAAE,CAAC,CAAA;YACnB,CAAC,CAAC,CAAA;QACH,CAAC,CAAC,CAAA;IACH,CAAC;IACM,KAAK,CAAC,WAAW,CAAE,QAAiB,EAAE,EAAa;QACzD,OAAO,IAAI,OAAO,CAAE,CAAC,OAAa,EAAE,MAAY,EAAE,EAAE;YACnD,MAAM,SAAS,GAAY,CAAC,IAAI,IAAI,EAAE,CAAA;YACtC,MAAM,GAAG,GAAY,GAAG,IAAI,CAAC,QAAQ,sBAAsB,QAAQ,EAAE,CAAA;YACrE,kBAAkB;YAClB,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAW,EAAE,GAAS,EAAE,IAAa,EAAE,EAAE;gBAC9D,IAAI,EAAE,GAAY,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,GAAG,SAAS,CAAA;gBAC3C,IAAI,GAAG,EAAE;oBACR,OAAO,MAAM,CAAC,GAAG,CAAC,CAAA;iBAClB;gBACD,OAAO,OAAO,CAAC,EAAE,CAAC,CAAA;YACnB,CAAC,CAAC,CAAA;QACH,CAAC,CAAC,CAAA;IACH,CAAC;IACM,OAAO,CAAE,EAAa;QAC5B,MAAM,SAAS,GAAY,CAAC,IAAI,IAAI,EAAE,CAAA;QACtC,MAAM,GAAG,GAAY,GAAG,IAAI,CAAC,QAAQ,SAAS,CAAA;QAC9C,MAAM,IAAI,GAAS;YAClB,MAAM,EAAG,KAAK;YACd,GAAG,EAAG,GAAG;YACT,OAAO,EAAE,IAAI;SACb,CAAA;QAED,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,GAAW,EAAE,GAAS,EAAE,IAAa,EAAE,EAAE;YACxD,IAAI,EAAE,GAAY,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,GAAG,SAAS,CAAA;YAC3C,IAAI,GAAG,EAAE;gBACR,oBAAoB;gBACpB,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;aAClB;YACD,EAAE,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,CAAA;QACnB,CAAC,CAAC,CAAA;IACH,CAAC;CACD;AAnED,wBAmEC;AAED,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAA"}

32
app/lib/light/Readme.md Normal file
View File

@ -0,0 +1,32 @@
<a name="Light"></a>
## Light
**Kind**: global class
* [Light](#Light)
* [.init()](#Light+init)
* [.listen()](#Light+listen)
* [.listener()](#Light+listener)
* [.set()](#Light+set)
* [.end()](#Light+end)
<a name="Light+init"></a>
### light.init()
**Kind**: instance method of [<code>Light</code>](#Light)
<a name="Light+listen"></a>
### light.listen()
**Kind**: instance method of [<code>Light</code>](#Light)
<a name="Light+listener"></a>
### light.listener()
**Kind**: instance method of [<code>Light</code>](#Light)
<a name="Light+set"></a>
### light.set()
**Kind**: instance method of [<code>Light</code>](#Light)
<a name="Light+end"></a>
### light.end()
**Kind**: instance method of [<code>Light</code>](#Light)

1
app/lib/light/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export {};

97
app/lib/light/index.js Normal file
View File

@ -0,0 +1,97 @@
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
const delay_1 = require("delay");
const Log = require("log");
class Light {
/**
*
**/
constructor(arduino, cfg, ui) {
this.state = { color: [0, 0, 0] };
this.enabled = true;
this.id = 'light';
this.arduino = arduino;
this.cfg = cfg;
this.ui = ui;
this.init();
}
/**
*
**/
async init() {
this.log = await Log({ label: this.id });
this.ipc = require('electron').ipcMain;
this.listen();
}
/**
*
**/
listen() {
this.ipc.handle(this.id, this.listener.bind(this));
}
/**
*
**/
async listener(event, arg) {
if (typeof arg.rgb !== 'undefined') {
try {
await this.set(arg.rgb, arg.id, true);
}
catch (err) {
this.log.error('Error setting light', err);
}
}
else if (typeof arg.enable !== 'undefined') {
this.enabled = true;
}
else if (typeof arg.disable !== 'undefined') {
this.enabled = false;
}
return true;
}
/**
*
**/
async set(rgb, id, on = true) {
const str = rgb.join(',');
let ms;
this.state.color = rgb;
try {
ms = await this.arduino.send(this.id, this.cfg.arduino.cmd.light);
}
catch (err) {
this.log.error('Error sending light command', err);
}
await (0, delay_1.delay)(1);
try {
this.arduino.sendString(this.id, str);
}
catch (err) {
this.log.error('Error sending light string', err);
}
await (0, delay_1.delay)(1);
await ms;
return await this.end(rgb, id, ms);
}
/**
*
**/
async end(rgb, id, ms) {
let res;
//console.trace()
this.log.info(`Light set to ${rgb.join(',')}`, 'LIGHT', true, true);
try {
//console.dir({ rgb, id, ms })
res = await this.ui.send(this.id, { rgb, id, ms });
}
catch (err) {
console.error(err);
throw err;
}
return res;
}
}
module.exports = function (arduino, cfg, ui) {
return new Light(arduino, cfg, ui);
};
//# sourceMappingURL=index.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/light/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,iCAA8B;AAC9B,2BAA4B;AAE5B,MAAM,KAAK;IAYV;;QAEI;IACJ,YAAa,OAAiB,EAAE,GAAS,EAAE,EAAQ;QAd5C,UAAK,GAAS,EAAE,KAAK,EAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAA;QAOlC,YAAO,GAAa,IAAI,CAAC;QAEzB,OAAE,GAAY,OAAO,CAAC;QAM7B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,IAAI,EAAE,CAAC;IACb,CAAC;IAED;;QAEI;IACI,KAAK,CAAC,IAAI;QACjB,IAAI,CAAC,GAAG,GAAG,MAAM,GAAG,CAAC,EAAE,KAAK,EAAG,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1C,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC;QACvC,IAAI,CAAC,MAAM,EAAE,CAAC;IACf,CAAC;IAED;;QAEI;IACI,MAAM;QACb,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACpD,CAAC;IAED;;QAEI;IACI,KAAK,CAAC,QAAQ,CAAE,KAAW,EAAE,GAAS;QAC7C,IAAI,OAAO,GAAG,CAAC,GAAG,KAAK,WAAW,EAAE;YACnC,IAAI;gBACH,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;aACtC;YAAC,OAAO,GAAG,EAAE;gBACb,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,qBAAqB,EAAE,GAAG,CAAC,CAAC;aAE3C;SACD;aAAM,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,WAAW,EAAE;YAC7C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;SACpB;aAAM,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,WAAW,EAAE;YAC9C,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;SACrB;QACD,OAAO,IAAI,CAAC;IACb,CAAC;IAED;;QAEI;IACG,KAAK,CAAC,GAAG,CAAE,GAAc,EAAE,EAAW,EAAE,KAAe,IAAI;QACjE,MAAM,GAAG,GAAY,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnC,IAAI,EAAQ,CAAC;QAEb,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC;QACvB,IAAI;YACH,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;SAClE;QAAC,OAAO,GAAG,EAAE;YACb,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;SACnD;QACD,MAAM,IAAA,aAAK,EAAC,CAAC,CAAC,CAAC;QACf,IAAI;YACH,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;SACtC;QAAC,OAAO,GAAG,EAAE;YACb,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,4BAA4B,EAAE,GAAG,CAAC,CAAC;SAClD;QACD,MAAM,IAAA,aAAK,EAAC,CAAC,CAAC,CAAC;QACf,MAAM,EAAE,CAAC;QACT,OAAO,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IACpC,CAAC;IAED;;QAEI;IACI,KAAK,CAAC,GAAG,CAAE,GAAc,EAAE,EAAW,EAAE,EAAW;QAC1D,IAAI,GAAG,CAAC;QACR,iBAAiB;QACjB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACpE,IAAI;YACH,8BAA8B;YAC9B,GAAG,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;SACnD;QAAC,OAAO,GAAG,EAAE;YACb,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACnB,MAAM,GAAG,CAAA;SACT;QACD,OAAO,GAAG,CAAC;IACZ,CAAC;CACD;AAED,MAAM,CAAC,OAAO,GAAG,UAAU,OAAiB,EAAE,GAAS,EAAE,EAAQ;IAChE,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;AACpC,CAAC,CAAA"}

View File

@ -0,0 +1,11 @@
{
"name": "light",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

8
app/lib/log/Readme.md Normal file
View File

@ -0,0 +1,8 @@
<a name="logFile"></a>
## logFile() ⇒ <code>string</code>
Determine the location of the log file based on the operating system
and return as an absolute string from os.homedir()
**Kind**: global function
**Returns**: <code>string</code> - Path to log file

1
app/lib/log/index.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export {};

85
app/lib/log/index.js Normal file
View File

@ -0,0 +1,85 @@
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
const winston_1 = require("winston");
const path_1 = require("path");
const fs_extra_1 = require("fs-extra");
const os_1 = require("os");
const logTime = 'MM/DD/YY-HH:mm:ss';
let transport;
/**
* Determine the location of the log file based on the operating system
* and return as an absolute string from os.homedir()
*
* @returns {string} Path to log file
**/
async function logFile() {
const homeDir = (0, os_1.homedir)();
const linuxDir = `/.mcopy/`;
const macDir = `/Library/Logs/mcopy/`;
const winDir = `/AppData/Roaming/mcopy/`;
let logPath = (0, path_1.normalize)((0, path_1.join)(homeDir, linuxDir));
let dirExists;
if (process.platform === 'darwin') {
logPath = (0, path_1.normalize)((0, path_1.join)(homeDir, macDir));
}
else if (process.platform === 'win32') {
logPath = (0, path_1.normalize)((0, path_1.join)(homeDir, winDir));
}
try {
dirExists = await (0, fs_extra_1.exists)(logPath);
}
catch (err) {
console.error(err);
}
if (!dirExists) {
try {
await (0, fs_extra_1.mkdir)(logPath);
}
catch (err) {
console.error(`Error creating directory for mcopy log file, ${logPath}`);
console.error(err);
}
}
return (0, path_1.join)(logPath, 'mcopy.log');
}
/**
* Create and return the logger transport based on settings determined in
* arguments object
*
* @param {object} arg Arguments from process
*
* @returns {object} Logger transport
**/
module.exports = async function Log(arg) {
let consoleFormat = {
colorize: true
};
let fileFormat = {
filename: await logFile(),
json: true
};
if (arg && arg.quiet) {
transport = {
info: function () { return false; },
warn: function () { return false; },
error: function () { return false; }
};
}
else {
if (arg && arg.label) {
consoleFormat.label = arg.label;
fileFormat.label = arg.label;
}
transport = (0, winston_1.createLogger)({
format: winston_1.format.combine(winston_1.format.label({ label: arg.label || 'mcopy' }), winston_1.format.timestamp({
format: 'YYYY-MM-DD HH:mm:ss'
}), winston_1.format.printf((info) => `${info.timestamp} [${info.label}] ${info.level}: ${info.message}` + (info.splat !== undefined ? `${info.splat}` : " "))),
transports: [
new (winston_1.transports.Console)(consoleFormat),
new (winston_1.transports.File)(fileFormat)
]
});
}
return transport;
};
//# sourceMappingURL=index.js.map

1
app/lib/log/index.js.map Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/log/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,qCAA2D;AAC3D,+BAAuC;AACvC,uCAAyC;AACzC,2BAA6B;AAE7B,MAAM,OAAO,GAAG,mBAAmB,CAAA;AACnC,IAAI,SAAe,CAAA;AAEnB;;;;;IAKI;AACJ,KAAK,UAAU,OAAO;IACrB,MAAM,OAAO,GAAY,IAAA,YAAO,GAAE,CAAC;IACnC,MAAM,QAAQ,GAAY,UAAU,CAAC;IACrC,MAAM,MAAM,GAAY,sBAAsB,CAAC;IAC/C,MAAM,MAAM,GAAY,yBAAyB,CAAC;IAClD,IAAI,OAAO,GAAY,IAAA,gBAAS,EAAC,IAAA,WAAI,EAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC1D,IAAI,SAAmB,CAAC;IAExB,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE;QAClC,OAAO,GAAG,IAAA,gBAAS,EAAC,IAAA,WAAI,EAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;KAC3C;SAAM,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE;QACxC,OAAO,GAAG,IAAA,gBAAS,EAAC,IAAA,WAAI,EAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;KAC3C;IAED,IAAI;QACH,SAAS,GAAG,MAAM,IAAA,iBAAM,EAAC,OAAO,CAAC,CAAC;KAClC;IAAC,OAAO,GAAG,EAAE;QACb,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;KACnB;IAED,IAAI,CAAC,SAAS,EAAE;QACf,IAAI;YACH,MAAM,IAAA,gBAAK,EAAC,OAAO,CAAC,CAAC;SACrB;QAAC,OAAO,GAAG,EAAE;YACb,OAAO,CAAC,KAAK,CAAC,gDAAgD,OAAO,EAAE,CAAC,CAAC;YACzE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;SACnB;KACD;IAED,OAAO,IAAA,WAAI,EAAC,OAAO,EAAE,WAAW,CAAC,CAAC;AACnC,CAAC;AACD;;;;;;;IAOI;AACJ,MAAM,CAAC,OAAO,GAAG,KAAK,UAAU,GAAG,CAAE,GAAS;IAC7C,IAAI,aAAa,GAAS;QACzB,QAAQ,EAAG,IAAI;KACf,CAAA;IACD,IAAI,UAAU,GAAS;QACtB,QAAQ,EAAG,MAAM,OAAO,EAAE;QAC1B,IAAI,EAAG,IAAI;KACX,CAAA;IACD,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,EAAE;QACrB,SAAS,GAAG;YACX,IAAI,EAAG,cAAc,OAAO,KAAK,CAAA,CAAC,CAAC;YACnC,IAAI,EAAG,cAAc,OAAO,KAAK,CAAA,CAAC,CAAC;YACnC,KAAK,EAAG,cAAc,OAAO,KAAK,CAAA,CAAC,CAAC;SACpC,CAAA;KACD;SAAM;QACN,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,EAAE;YACrB,aAAa,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;YAChC,UAAU,CAAC,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;SAC7B;QACD,SAAS,GAAG,IAAA,sBAAY,EAAC;YACxB,MAAM,EAAG,gBAAM,CAAC,OAAO,CACnB,gBAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAG,GAAG,CAAC,KAAK,IAAI,OAAO,EAAE,CAAC,EACjD,gBAAM,CAAC,SAAS,CAAC;gBAChB,MAAM,EAAE,qBAAqB;aAC7B,CAAC,EACF,gBAAM,CAAC,MAAM,CAAC,CAAC,IAAU,EAAG,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,OAAO,EAAE,GAAC,CAAC,IAAI,CAAC,KAAK,KAAG,SAAS,CAAA,CAAC,CAAA,GAAG,IAAI,CAAC,KAAK,EAAE,CAAA,CAAC,CAAA,GAAG,CAAC,CAAC,CAC7I;YACH,UAAU,EAAE;gBACX,IAAI,CAAC,oBAAU,CAAC,OAAO,CAAC,CAAC,aAAa,CAAC;gBACvC,IAAI,CAAC,oBAAU,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC;aACjC;SACD,CAAC,CAAA;KACF;IACD,OAAO,SAAS,CAAA;AACjB,CAAC,CAAA"}

11
app/lib/log/package.json Normal file
View File

@ -0,0 +1,11 @@
{
"name": "log",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

View File

@ -24,6 +24,7 @@
* [.light_to_arr()](#module_lib/mscript..Mscript+light_to_arr)
* [.light_state()](#module_lib/mscript..Mscript+light_state)
* [.fail()](#module_lib/mscript..Mscript+fail)
* [~startsWith()](#module_lib/mscript..startsWith)
<a name="module_lib/mscript..Mscript"></a>
@ -70,55 +71,55 @@ of steps to be fed into the mcopy.
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+basic_cmd"></a>
#### mscript.basic_cmd()
#### mscript.basic\_cmd()
Apply a basic two character command
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+new_loop"></a>
#### mscript.new_loop()
#### mscript.new\_loop()
Start a new loop
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+end_loop"></a>
#### mscript.end_loop()
#### mscript.end\_loop()
Close the most recent loop
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+move_cam"></a>
#### mscript.move_cam()
#### mscript.move\_cam()
Move camera to explicitly-defined frame
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+move_proj"></a>
#### mscript.move_proj()
#### mscript.move\_proj()
Move projector to explicitly-defined frame
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+set_state"></a>
#### mscript.set_state()
#### mscript.set\_state()
Set the state of either the cam or projector
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+last_loop"></a>
#### mscript.last_loop()
#### mscript.last\_loop()
Return the last loop
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+parent_loop"></a>
#### mscript.parent_loop()
#### mscript.parent\_loop()
Return the second-last loop
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+loop_count"></a>
#### mscript.loop_count()
#### mscript.loop\_count()
Extract the loop count integer from a LOOP cmd
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
@ -130,19 +131,19 @@ Execute a fade of frame length, from color to another color
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+fade_count"></a>
#### mscript.fade_count()
#### mscript.fade\_count()
Extract the fade length integer from a FADE cmd
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+fade_start"></a>
#### mscript.fade_start()
#### mscript.fade\_start()
Extract the start color from a string
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+fade_end"></a>
#### mscript.fade_end()
#### mscript.fade\_end()
Extract the end color from a string
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
@ -155,19 +156,19 @@ by the value defined in val
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+str_to_arr"></a>
#### mscript.str_to_arr()
#### mscript.str\_to\_arr()
Split string on command, extract any integers from string
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+light_to_arr"></a>
#### mscript.light_to_arr()
#### mscript.light\_to\_arr()
Split a string on a command to extract data for light array
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..Mscript+light_state"></a>
#### mscript.light_state()
#### mscript.light\_state()
Split a string to extract an rgb color value
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
@ -177,3 +178,9 @@ Split a string to extract an rgb color value
Throw an error with specific message
**Kind**: instance method of [<code>Mscript</code>](#module_lib/mscript..Mscript)
<a name="module_lib/mscript..startsWith"></a>
### lib/mscript~startsWith()
startswith function from lodash, do not want the entire lib for this
**Kind**: inner method of [<code>lib/mscript</code>](#module_lib/mscript)

View File

@ -7,4 +7,7 @@ Bash-like variables?
Similar to LESS/SASS?
Makes a tokenization easier
@ is better than $
@ is better than $
RangeError: Invalid array length
at Mscript.str_to_arr (./mcopy/app/lib/mscript/index.js:474:9)

249
app/lib/mscript/index.d.ts vendored Normal file
View File

@ -0,0 +1,249 @@
/** @module lib/mscript */
interface RGB extends Array<number> {
[index: number]: number;
}
/** class Mscript */
export default class Mscript {
output: any;
lines: string[];
cam: number;
cam2: number;
proj: number;
proj2: number;
color: string;
loops: any[];
rec: number;
two: string;
three: string;
four: string;
arr: any[];
meta: string[];
target: number;
dist: number;
variables: any;
/**
* @constructor
* Create new Mscript interpreter
**/
constructor();
/**
* Clear the state of the script
*/
clear(): void;
/**
* Main function, accepts multi-line string, parses into lines
* and interprets the instructions from the text. Returns an array
* of steps to be fed into the mcopy sequence.
*
* @param {string} text Mscript text to interpret
* @param {function} callback Function to call when string is interpreted
*
* @returns {object} if callback is not provided
*/
interpret(text: string, callback?: Function): any;
/**
* Interprets variables for complex sequence behavior.
* TODO: Fully implement, add test coverage
*
* @param {string} line Line containing a variable assignment
*
**/
variable(line: string): void;
/**
* Replace variable with value at time of interpretation
* TODO: Implement this please
*
* @param {string} line Line containing variable to be replaced with value
*
* @returns {string} New string to be interpreted
**/
variable_replace(line: string): string;
/**
* Interpret a basic two character command
*
* @param {string} line Line of script to interpret
* @param {string} short The short command to use
*/
basic_cmd(line: string, short: string): void;
/**
* Start a new loop
*
* @param {string} line Line to evaluate as either loop or fade
* @param {boolean} fade Flag as true if fade
*/
new_loop(line: string, fade?: boolean): void;
/**
* Close the most recent loop
*
* @param {string} line Line to interpret
*/
end_loop(line: string): void;
/**
* Move camera to explicitly-defined frame
*
* @param {string} line Line to interpret with camera move statement
*/
move_cam(line: string): void;
/**
* Move secondary camera to explicitly-defined frame
*
* @param {string} line Line to interpret with camera move statement
*/
move_cam2(line: string): void;
/**
* Move projector to explicitly-defined frame
*
* @param {string} line Line containing `move` statement to interpret
*/
move_proj(line: string): void;
/**
* Move projector to explicitly-defined frame
*
* @param {string} line Line containing `move` statement to interpret
*/
move_proj2(line: string): void;
/**
* Set the state of either the cam or projector
*
* @param line {string} String containing set statement
*/
set_state(line: string): void;
/**
* Return the last loop
*
* @returns {object}
*/
last_loop(): any;
/**
* Return the second-last loop
*
* @returns {object} Loop array
*/
parent_loop(): any;
/**
* Extract the loop count integer from a LOOP cmd
*
* @returns {integer} Loop count in string parsed into integer
*/
loop_count(str: string): number;
/**
* Execute a fade of frame length, from color to another color
*
* @param {string} line Line containing a fade initiator
*/
fade(line: string): void;
/**
* Extract the fade length integer from a FADE cmd
*
* @param {string} str Line containing the length of fade in frames
*/
fade_count(str: string): number;
/**
* Extract the start color from a string
*
* @param {string} str Line containing the start color value in a fade initiator
*
* @returns {array} Array containing RGB color values
*/
fade_start(str: string): RGB;
/**
* Extract the end color from a string
*
* @param {string} str Line containing the end color value in a fade initiator
*
* @returns {array} Array containing RGB color values
*/
fade_end(str: string): RGB;
/**
* Determine the state of a fade at a particular frame in the sequence, x
*
* @param {array} start Color the fade starts at
* @param {array} end Color the fade finishes at
* @param {integer} len Total length of the fade in frames
* @param {integer} x Position of the fade to get color value of
*
* @returns {array} Array containing RGB color values
*/
fade_rgb(start: RGB, end: RGB, len: number, x: number): string;
/**
* Parse string into array of RGB color values. 0-255 octet.
*
* @param {string} str String containing only color values as `#,#,#`
**/
rgb(str: string): RGB;
/**
* Cast RGB color values as string
*
* @param {array} arr Array to join into string
*
* @returns {string} String of RGB values
**/
rgb_str(arr: RGB): string;
/**
* Increase the state of a specific object, such as the camera/projector,
* by the value defined in val.
*
* @param {string} cmd String representing command to interpret and update state
*/
update(cmd: string, val?: number): void;
/**
* Split string on command, turn into array of commands
* as long as count variable. Default 1.
*
* @param {string} str String to split
* @param {string} cmd String representing command to split at
*
* @returns {array} Array containing commands
*/
str_to_arr(str: string, cmd: string): string[];
/**
* Split a string on a command to extract data for light array
*
* @param {string} str String containing light command
* @param {string} cmd String representing command
*
* @returns {array} An RGB array containing the color values
*/
light_to_arr(str: string, cmd: string): RGB;
/**
* Split a string to extract an rgb color value
*
* @param {string} Color string assign to color property
*/
light_state(str: string): void;
/**
* Interpret a delay command
*
* @param {string} line String containing delay command
**/
delay(line: string): void;
/**
* Interpret an alert command
*
* @param {string} line String containing alert message
**/
alert(line: string): void;
/**
* Interpret an pause command
*
* @param {string} line String containing alert message
**/
pause(line: string): void;
/**
* Throw an error with specific message
*
* @param {string} msg Error message to print
*/
fail(msg: string): void;
/**
* Determine if array contains matching elements of
* another array
*
* @param {Array} arr Original array to compare
* @param {Array} arr2 Array to compare elements from
*
* @returns {boolean} Whether arr contains elements in arr2
**/
contains(arr: string[], arr2: string[]): boolean;
}
export {};

Some files were not shown because too many files have changed in this diff Show More