├── favicon.ico
├── dev
├── images
│ └── device_concept.png
├── midi_files
│ ├── pachelbel-canon.mid
│ ├── MarbleMachineLeftHand.mid
│ ├── MarbleMachineRightHand.mid
│ └── MarbleMachinePianoVersionBothHands.mid
├── midi_libraries
│ ├── index.html
│ ├── styles
│ │ └── styles.css
│ ├── MidiConvert.html
│ └── midi_parser.html
└── UML
│ └── Application model.xml
├── experimental
├── whitebird
│ ├── a.mid
│ ├── favicon.ico
│ ├── custom.css
│ └── FileSaver.min.js
├── sandbox
│ ├── images
│ │ ├── page.png
│ │ ├── strip.png
│ │ ├── screen.png
│ │ ├── chBck_invalid.gif
│ │ ├── chBck_valid.gif
│ │ ├── channel_background.gif
│ │ └── screen_collapsed.png
│ ├── midi
│ │ └── pachelbel-canon.mid
│ ├── inc
│ │ ├── scalemodes.js
│ │ ├── scalesandnotes.js
│ │ ├── scales.js
│ │ └── devices.json
│ ├── templates
│ │ ├── A4-01.svg
│ │ ├── strip_dimensions.xml
│ │ ├── strip_event_orientations
│ │ ├── object_dimensions.xml
│ │ ├── layout_anchors_2.xml
│ │ └── layout_anchors
│ ├── styles
│ │ ├── styles.css
│ │ └── device_concept.css
│ └── index.html
└── musicboxeditor
│ ├── typings.json
│ ├── src
│ ├── assets
│ │ ├── favicon.png
│ │ ├── fonts
│ │ │ ├── opensans.woff2
│ │ │ └── source
│ │ │ │ └── segoeui.ttf
│ │ └── icons
│ │ │ └── source
│ │ │ ├── interactor-font-icons
│ │ │ ├── fonts
│ │ │ │ ├── interactor-icons.ttf
│ │ │ │ └── interactor-icons.woff
│ │ │ ├── Read Me.txt
│ │ │ ├── demo-files
│ │ │ │ ├── demo.js
│ │ │ │ └── demo.css
│ │ │ └── style.css
│ │ │ ├── square.svg
│ │ │ ├── chevron-down.svg
│ │ │ ├── chevron-right.svg
│ │ │ ├── chevron-up.svg
│ │ │ ├── chevron-left.svg
│ │ │ ├── circle.svg
│ │ │ ├── message.svg
│ │ │ ├── delete.svg
│ │ │ ├── file.svg
│ │ │ ├── menu.svg
│ │ │ ├── checkbox-old.svg
│ │ │ ├── folder.svg
│ │ │ ├── package.svg
│ │ │ ├── checkbox-o.svg
│ │ │ ├── alert-circle.svg
│ │ │ ├── info-circle.svg
│ │ │ ├── checkbox-minus.svg
│ │ │ ├── account.svg
│ │ │ ├── checkbox-plus.svg
│ │ │ ├── folder-open.svg
│ │ │ ├── radiobox.svg
│ │ │ ├── approve.svg
│ │ │ ├── save.svg
│ │ │ ├── package-open.svg
│ │ │ ├── asterisk.svg
│ │ │ ├── exit.svg
│ │ │ ├── medical-bag.svg
│ │ │ ├── gender-female.svg
│ │ │ ├── refresh.svg
│ │ │ ├── gender-male.svg
│ │ │ ├── radiobox-marked.svg
│ │ │ ├── cross.svg
│ │ │ ├── search.svg
│ │ │ ├── gender-male-female.svg
│ │ │ ├── checkbox-inc-old.svg
│ │ │ ├── gender-transgender.svg
│ │ │ ├── checkbox-inc.svg
│ │ │ ├── checkbox.svg
│ │ │ ├── script
│ │ │ ├── iconFont.js
│ │ │ └── template.css
│ │ │ └── persons.svg
│ ├── app
│ │ ├── ui
│ │ │ ├── contextMenu
│ │ │ │ ├── contextMenuRenderer.component.html
│ │ │ │ ├── contextMenu.interface.ts
│ │ │ │ ├── contextMenu.component.html
│ │ │ │ ├── contextMenuRenderer.component.css
│ │ │ │ ├── contextMenu.component.css
│ │ │ │ ├── contextMenu.directive.ts
│ │ │ │ ├── contextMenu.module.ts
│ │ │ │ ├── contextMenuRenderer.component.ts
│ │ │ │ ├── contextMenu.component.ts
│ │ │ │ └── contextMenu.service.ts
│ │ │ ├── hint
│ │ │ │ ├── hint.component.html
│ │ │ │ ├── hint.component.css
│ │ │ │ ├── hint.module.ts
│ │ │ │ ├── hint.service.ts
│ │ │ │ ├── hint.directive.ts
│ │ │ │ ├── hint.spec.ts
│ │ │ │ └── hint.component.ts
│ │ │ ├── tabMenu
│ │ │ │ ├── tabMenu.component.html
│ │ │ │ ├── tabMenu.interface.ts
│ │ │ │ ├── tabMenu.module.ts
│ │ │ │ ├── tabMenu.component.css
│ │ │ │ ├── tabMenu.component.ts
│ │ │ │ └── tabMenu.spec.ts
│ │ │ ├── subMenu
│ │ │ │ ├── subMenu.component.html
│ │ │ │ ├── subMenu.interface.ts
│ │ │ │ ├── subMenu.module.ts
│ │ │ │ ├── subMenu.component.css
│ │ │ │ ├── subMenu.component.ts
│ │ │ │ └── subMenu.spec.ts
│ │ │ └── dialog
│ │ │ │ ├── dialog.interface.ts
│ │ │ │ ├── dialog.module.ts
│ │ │ │ ├── dialog.component.html
│ │ │ │ ├── dialog.service.ts
│ │ │ │ ├── dialog.component.css
│ │ │ │ └── dialog.component.ts
│ │ ├── service
│ │ │ ├── log
│ │ │ │ ├── log.module.ts
│ │ │ │ └── log.service.ts
│ │ │ ├── mtosState
│ │ │ │ ├── mtosState.module.ts
│ │ │ │ └── mtosState.service.ts
│ │ │ └── input.service.ts
│ │ ├── directive
│ │ │ └── dragAndDrop
│ │ │ │ ├── dragAndDrop.module.ts
│ │ │ │ ├── dragAndDrop.service.ts
│ │ │ │ └── dragAndDrop.directive.ts
│ │ ├── app.module.ts
│ │ ├── app.component.css
│ │ └── app.component.html
│ ├── index.html
│ ├── main.jit.ts
│ ├── main.aot.ts
│ ├── main.test.ts
│ ├── styles.css
│ └── typings.d.ts
│ ├── dist
│ ├── assets
│ │ ├── favicon.png
│ │ └── fonts
│ │ │ └── opensans.woff2
│ ├── index.html
│ └── styles.css
│ ├── .gitignore
│ ├── tsconfig.json
│ ├── lite-server.config.js
│ ├── TODO.md
│ ├── README.md
│ ├── karma.config.js
│ ├── package.json
│ └── webpack.config.js
├── inc
├── custom.css
├── processing.js
├── scaleandmusicbox.js
├── drawing.js
└── user-interface.js
├── README.md
├── CONTRIBUTING.md
└── LICENSE.md
/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/favicon.ico
--------------------------------------------------------------------------------
/dev/images/device_concept.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/dev/images/device_concept.png
--------------------------------------------------------------------------------
/experimental/whitebird/a.mid:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/experimental/whitebird/a.mid
--------------------------------------------------------------------------------
/dev/midi_files/pachelbel-canon.mid:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/dev/midi_files/pachelbel-canon.mid
--------------------------------------------------------------------------------
/experimental/whitebird/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/experimental/whitebird/favicon.ico
--------------------------------------------------------------------------------
/experimental/sandbox/images/page.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/experimental/sandbox/images/page.png
--------------------------------------------------------------------------------
/experimental/sandbox/images/strip.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/experimental/sandbox/images/strip.png
--------------------------------------------------------------------------------
/dev/midi_files/MarbleMachineLeftHand.mid:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/dev/midi_files/MarbleMachineLeftHand.mid
--------------------------------------------------------------------------------
/experimental/sandbox/images/screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/experimental/sandbox/images/screen.png
--------------------------------------------------------------------------------
/dev/midi_files/MarbleMachineRightHand.mid:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/dev/midi_files/MarbleMachineRightHand.mid
--------------------------------------------------------------------------------
/experimental/musicboxeditor/typings.json:
--------------------------------------------------------------------------------
1 | {
2 | "globalDependencies": {
3 | "core-js": "registry:dt/core-js#0.0.0+20160914114559"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/experimental/sandbox/images/chBck_invalid.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/experimental/sandbox/images/chBck_invalid.gif
--------------------------------------------------------------------------------
/experimental/sandbox/images/chBck_valid.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/experimental/sandbox/images/chBck_valid.gif
--------------------------------------------------------------------------------
/experimental/sandbox/midi/pachelbel-canon.mid:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/experimental/sandbox/midi/pachelbel-canon.mid
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/experimental/musicboxeditor/src/assets/favicon.png
--------------------------------------------------------------------------------
/experimental/sandbox/images/channel_background.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/experimental/sandbox/images/channel_background.gif
--------------------------------------------------------------------------------
/experimental/sandbox/images/screen_collapsed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/experimental/sandbox/images/screen_collapsed.png
--------------------------------------------------------------------------------
/experimental/musicboxeditor/dist/assets/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/experimental/musicboxeditor/dist/assets/favicon.png
--------------------------------------------------------------------------------
/dev/midi_files/MarbleMachinePianoVersionBothHands.mid:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/dev/midi_files/MarbleMachinePianoVersionBothHands.mid
--------------------------------------------------------------------------------
/experimental/musicboxeditor/.gitignore:
--------------------------------------------------------------------------------
1 | /.vscode/
2 | /build/
3 | /node_modules/
4 | /typings/
5 | /.idea/
6 | *.css.shim.ts
7 | *.ngfactory.ts
8 | *.mid
9 | *.log
10 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/dist/assets/fonts/opensans.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/experimental/musicboxeditor/dist/assets/fonts/opensans.woff2
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/fonts/opensans.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/experimental/musicboxeditor/src/assets/fonts/opensans.woff2
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/fonts/source/segoeui.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/experimental/musicboxeditor/src/assets/fonts/source/segoeui.ttf
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/contextMenu/contextMenuRenderer.component.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/hint/hint.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/interactor-font-icons/fonts/interactor-icons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/experimental/musicboxeditor/src/assets/icons/source/interactor-font-icons/fonts/interactor-icons.ttf
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/interactor-font-icons/fonts/interactor-icons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Wintergatan/Midi-to-laser-cutter/HEAD/experimental/musicboxeditor/src/assets/icons/source/interactor-font-icons/fonts/interactor-icons.woff
--------------------------------------------------------------------------------
/inc/custom.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding-top: 70px;
3 | /* Required padding for .navbar-fixed-top. Remove if using .navbar-static-top. Change if height of navigation changes. */
4 | }
5 |
6 | #export-row {
7 | padding-top: 20px;
8 | }
9 |
10 | #download-btn {
11 | margin: 20px 0;
12 | }
13 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/contextMenu/contextMenu.interface.ts:
--------------------------------------------------------------------------------
1 | export interface IContextMenuOptions {
2 | width?: number;
3 | height?: number;
4 | x?: number;
5 | y?: number;
6 | text?: string;
7 | icon?: string;
8 | menu?: IContextMenuOptions[];
9 | callback?: ()=>void;
10 | }
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/tabMenu/tabMenu.component.html:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/square.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/tabMenu/tabMenu.interface.ts:
--------------------------------------------------------------------------------
1 | import { TabMenuComponent } from './tabMenu.component';
2 |
3 | export interface ITabMenuButton {
4 | text: string;
5 | callback?: ()=>boolean;
6 | }
7 |
8 | export interface ITabMenuComponentOptions {
9 | component?: TabMenuComponent;
10 | onInit?: ()=>void;
11 | buttons?: ITabMenuButton[];
12 | }
--------------------------------------------------------------------------------
/experimental/musicboxeditor/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "es2015",
5 | "moduleResolution": "node",
6 | "experimentalDecorators": true,
7 | "emitDecoratorMetadata": true,
8 | "sourceMap": true
9 | },
10 | "compileOnSave": false,
11 | "angularCompilerOptions": {
12 | "skipMetadataEmit": true
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/chevron-down.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/chevron-right.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/chevron-up.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/chevron-left.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/circle.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/message.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/delete.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/file.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/menu.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/checkbox-old.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/folder.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/package.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/subMenu/subMenu.component.html:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/checkbox-o.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/alert-circle.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/info-circle.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/service/log/log.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule, ModuleWithProviders } from '@angular/core';
2 | import { LogService, Logger } from './log.service';
3 |
4 | export { LogService, Logger };
5 |
6 | @NgModule({})
7 | export class LogModule {
8 | static forRoot(): ModuleWithProviders {
9 | return {
10 | ngModule: LogModule,
11 | providers: [ LogService ]
12 | };
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/checkbox-minus.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Musicbox Editor
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/account.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/tabMenu/tabMenu.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 | import { TabMenuComponent } from './tabMenu.component';
4 |
5 | export { TabMenuComponent };
6 | export * from './tabMenu.interface';
7 |
8 | @NgModule({
9 | imports: [CommonModule],
10 | declarations: [TabMenuComponent],
11 | exports: [TabMenuComponent]
12 | })
13 | export class TabMenuModule { }
14 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/checkbox-plus.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/folder-open.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/radiobox.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/approve.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/save.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/contextMenu/contextMenu.component.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/package-open.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
--------------------------------------------------------------------------------
/dev/midi_libraries/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | MIDI Library Tests
6 |
7 |
8 |
9 |
10 |
14 |
15 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/dialog/dialog.interface.ts:
--------------------------------------------------------------------------------
1 | export interface IDialogButton {
2 | text?: string;
3 | disableClose?: boolean;
4 | callback?: ()=>void;
5 | };
6 |
7 | export interface IDialogSelect {
8 | text?: string;
9 | selected?: any;
10 | options?: any; //{key: string, value: string};
11 | };
12 |
13 | export interface IDialog {
14 | heading?: string;
15 | content?: string;
16 | level?: string;
17 | buttons?: IDialogButton[];
18 | select?: IDialogSelect[];
19 | };
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/asterisk.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/exit.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/medical-bag.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/service/mtosState/mtosState.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule, ModuleWithProviders } from '@angular/core';
2 | import { MtosStateService, IHeader, INote, ITrack } from "./mtosState.service";
3 |
4 | export { MtosStateService, IHeader, INote, ITrack };
5 |
6 | @NgModule({})
7 | export class MtosStateModule {
8 | static forRoot(): ModuleWithProviders {
9 | return {
10 | ngModule: MtosStateModule,
11 | providers: [ MtosStateService ]
12 | };
13 | }
14 | }
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/hint/hint.component.css:
--------------------------------------------------------------------------------
1 | :host{
2 | pointer-events: none;
3 | position: absolute;
4 | top: 0;
5 | left: 0;
6 | width: 0;
7 | height: 0;
8 | overflow: hidden;
9 | }
10 |
11 | .box {
12 | position: fixed;
13 | padding: 0.5em;
14 | max-width: 20em;
15 | color: #444444;
16 | background-color: white;
17 | border: 1px solid #e0e0e0;
18 | box-shadow: rgba(0, 0, 0, 0.1) 2px 2px 0 0;
19 | /*box-shadow: 1px 1px 5px rgba(0, 0, 0, 0.25);*/
20 | }
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/subMenu/subMenu.interface.ts:
--------------------------------------------------------------------------------
1 | import { SubMenuComponent } from './subMenu.component';
2 |
3 | export interface ISubMenuButton {
4 | text: string;
5 | callback?: ()=>void;
6 | iconClass?: string;
7 | }
8 |
9 | export interface ISubMenuComponentOptions {
10 | component?: SubMenuComponent;
11 | onInit?: ()=>void;
12 | disableBackground?: boolean;
13 | disableIcons?: boolean;
14 | disableText?: boolean;
15 | iconSize?: string;
16 | buttons?: ISubMenuButton[];
17 | }
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/gender-female.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/subMenu/subMenu.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 |
4 | import { HintModule } from '../hint/hint.module';
5 | import { SubMenuComponent } from './subMenu.component';
6 |
7 | export * from './subMenu.interface';
8 | export { SubMenuComponent };
9 |
10 | @NgModule({
11 | imports: [CommonModule, HintModule ],
12 | declarations: [SubMenuComponent],
13 | exports: [SubMenuComponent]
14 | })
15 | export class SubMenuModule { }
16 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/refresh.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/gender-male.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/radiobox-marked.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/cross.svg:
--------------------------------------------------------------------------------
1 |
2 |
5 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/search.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Musicbox Editor
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/tabMenu/tabMenu.component.css:
--------------------------------------------------------------------------------
1 | .tab-menu {
2 | display: flex;
3 | flex-wrap: wrap;
4 | }
5 |
6 | .button {
7 | display: flex;
8 | padding: 0.2em 0.5em;
9 | color: #888888;
10 | }
11 |
12 | .button:hover{
13 | border-bottom: 3px solid ;
14 | }
15 |
16 | .button+.button{
17 | margin-left: 0.5em;
18 | }
19 |
20 | .isSelected {
21 | color: #028478;
22 | border-bottom: 3px solid #028478;
23 | }
24 |
25 | button {
26 | box-sizing: content-box;
27 | background-color: transparent;
28 | border-bottom: 3px solid transparent;
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/gender-male-female.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/whitebird/custom.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding-top: 70px;
3 | /* Required padding for .navbar-fixed-top. Remove if using .navbar-static-top. Change if height of navigation changes. */
4 | }
5 |
6 | #export-row {
7 | padding-top: 20px;
8 | }
9 |
10 | #download-btn {
11 | margin: 20px 0;
12 | }
13 |
14 | #preview-box {
15 | margin-top:20px;
16 | }
17 |
18 | #preview-wrapper {
19 | overflow-y: hidden;
20 | overflow-x: scroll;
21 | }
22 |
23 | #preview {
24 | width:100%;
25 | height:98%;
26 | border: 1px solid black;
27 | }
28 |
29 | .note-selector {
30 | margin-bottom:6px;
31 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Midi to laser cutter
2 | This repository will host the code for the future midi to laser cutter converter.
3 |
4 | - General chatting can be done at [Gitter](https://gitter.im/Wintergatan/Midi-to-laser-cutter)
5 | - Slow discussions can be started in the [Issue tracker](https://github.com/Wintergatan/Midi-to-laser-cutter/issues)
6 | - See current version here: [Link](https://wintergatan.github.io/Midi-to-laser-cutter/)
7 | - Prototype B here (Supports Chrome and Firefox): [Link](https://wintergatan.github.io/Midi-to-laser-cutter/experimental/musicboxeditor/dist/)
8 | - [Info on how to contribute](https://github.com/Wintergatan/Midi-to-laser-cutter/blob/master/CONTRIBUTING.md)
9 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/checkbox-inc-old.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/main.jit.ts:
--------------------------------------------------------------------------------
1 |
2 | import "reflect-metadata"; //only needed for jit.
3 |
4 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
5 | import { AppModule } from './app/app.module';
6 |
7 |
8 | console.info('app.environment:', app.environment);
9 | if(document.readyState === "complete" || document.readyState === "interactive") {
10 | console.log('Bootstrapping app');
11 | platformBrowserDynamic().bootstrapModule(AppModule);
12 | }
13 | else {
14 | document.addEventListener("DOMContentLoaded", function() {
15 | console.log('Bootstrapping app');
16 | platformBrowserDynamic().bootstrapModule(AppModule);
17 | });
18 | }
19 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/lite-server.config.js:
--------------------------------------------------------------------------------
1 | const proxyMiddleware = require('http-proxy-middleware');
2 |
3 | const useGzip = process.env.APP_ENVIRONMENT == 'gzip';
4 |
5 | var config = {
6 | "port": 9100,
7 | "files": ["./build/**/*.{html,htm,css,js}"],
8 | "server": {
9 | "baseDir": "./build",
10 | middleware: {
11 | 1: proxyMiddleware('/interactor', {
12 | target: 'http://localhost:8080/',
13 | changeOrigin: true
14 | })
15 | }
16 | }
17 | };
18 |
19 | /*
20 | if(useGzip){
21 |
22 | config.server.middleware = { 1 : require('compression')() };
23 | }
24 | */
25 |
26 |
27 | module.exports = config;
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/contextMenu/contextMenuRenderer.component.css:
--------------------------------------------------------------------------------
1 | :host{
2 | position: absolute;
3 | top: 0;
4 | bottom: 0;
5 | left: 0;
6 | right: 0;
7 | pointer-events: none;
8 | }
9 |
10 | :host>*{
11 | pointer-events: initial;
12 | }
13 |
14 | :host *{
15 | user-select: none;
16 | cursor: default;
17 | box-sizing: border-box;
18 | }
19 |
20 | .context-menu{
21 | position: fixed;
22 | padding: 0.5em 0;
23 | border: 1px solid #444444;
24 | background-color: #ffffff;
25 | overflow-y: auto;
26 | }
27 |
28 | .element{
29 | padding: 0.25em 0.5em;
30 | }
31 |
32 | .element:hover{
33 | background-color: rgba(0, 0, 0, 0.1);
34 | }
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/hint/hint.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule, ModuleWithProviders } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 |
4 | import { HintService } from './hint.service';
5 | import { HintComponent } from './hint.component';
6 | import { Hint } from './hint.directive';
7 |
8 | export { HintComponent, Hint };
9 |
10 | @NgModule({
11 | imports: [CommonModule],
12 | declarations: [Hint, HintComponent],
13 | exports: [Hint, HintComponent]
14 | })
15 | export class HintModule {
16 | static forRoot(): ModuleWithProviders {
17 | return {
18 | ngModule: HintModule,
19 | providers: [ HintService ]
20 | };
21 | }
22 | }
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/gender-transgender.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/checkbox-inc.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/checkbox.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/service/input.service.ts:
--------------------------------------------------------------------------------
1 |
2 | export class InputService {
3 |
4 | static keyCode = {
5 | Enter: 13,
6 | ArrowUp: 38,
7 | ArrowDown: 40,
8 | ArrowLeft: 37,
9 | ArrowRight: 39
10 | };
11 |
12 | static isKeyDown(event: KeyboardEvent ,keyCode: number){
13 | if(event.keyCode === keyCode){
14 | return true;
15 | }
16 |
17 | if(event.which === keyCode){
18 | return true;
19 | }
20 |
21 | if(InputService.keyCode[event.code] === keyCode){
22 | return true;
23 | }
24 |
25 | if(InputService.keyCode[event.key] === keyCode){
26 | return true;
27 | }
28 |
29 | return false;
30 | }
31 | }
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/main.aot.ts:
--------------------------------------------------------------------------------
1 |
2 | import "reflect-metadata"; //only needed for jit.
3 |
4 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
5 | import { enableProdMode } from '@angular/core';
6 | import { AppModule } from './app/app.module';
7 |
8 | console.info('app.environment:', app.environment);
9 | if(document.readyState === "complete" || document.readyState === "interactive") {
10 | console.log('Bootstrapping app');
11 | enableProdMode();
12 | platformBrowserDynamic().bootstrapModule(AppModule);
13 | }
14 | else {
15 | document.addEventListener("DOMContentLoaded", function() {
16 | console.log('Bootstrapping app');
17 | enableProdMode();
18 | platformBrowserDynamic().bootstrapModule(AppModule);
19 | });
20 | }
21 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/hint/hint.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from '@angular/core';
2 | import { HintComponent } from './hint.component';
3 |
4 | @Injectable()
5 | export class HintService {
6 | public renderer: HintComponent = null;
7 |
8 | constructor() { }
9 |
10 | public setRenderer(renderer: HintComponent) {
11 | this.renderer = renderer;
12 | }
13 |
14 | public open(hint: string, bbox: ClientRect): void {
15 | if (this.renderer) {
16 | this.renderer.open(hint, bbox);
17 | } else {
18 | console.log('Hint renderer not found, is it added to template?');
19 | }
20 | }
21 |
22 | public close(): void {
23 | if (this.renderer) {
24 | this.renderer.close();
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/contextMenu/contextMenu.component.css:
--------------------------------------------------------------------------------
1 | :host{
2 | position: fixed;
3 | padding: 0.5em 0;
4 | color: #444444;
5 | background-color: white;
6 | border: 1px solid #444444;
7 | box-shadow: rgba(0, 0, 0, 0.1) 2px 2px 0 0;
8 | overflow-y: auto;
9 | }
10 |
11 | :host:focus{
12 | outline: none;
13 | }
14 |
15 | .element{
16 | padding: 0.25em 0.5em;
17 | display: flex;
18 | align-items: center;
19 | }
20 |
21 | .element:hover{
22 | background-color: rgba(0, 0, 0, 0.1);
23 | }
24 |
25 | .icon{
26 | display: block;
27 | width: 1em;
28 | }
29 |
30 | .text{
31 | margin-left: 0.5em;
32 | }
33 |
34 | .space{
35 | flex: 100 100 50%;
36 | min-width: 0;
37 | }
38 |
39 | .sub-menu-icon{
40 | display: block;
41 | width: 1em;
42 | }
--------------------------------------------------------------------------------
/experimental/musicboxeditor/TODO.md:
--------------------------------------------------------------------------------
1 | # TODO
2 |
3 | ## Multipart download
4 | * Option for multipart download in gui (checkbox or select).
5 |
6 | ## Scale options
7 | * more options?
8 |
9 | ## Add note
10 | * In track view.
11 | * Show ghost note on hover.
12 | * On click add note and sort notes.
13 |
14 |
15 | ## Move note
16 | * In track view.
17 | * On click down, remove note.
18 | * Show ghost note.
19 | * On click up add ghost note and sort notes.
20 | * Hold shift for snap to grid.
21 | * If action is not completed (drag outside of screen). Add note to old position.
22 |
23 |
24 | ## Show more info
25 | * Number of notes
26 | * Number of track parts.
27 | * Length of track in mm.
28 | * Colliding notes -> orange?
29 |
30 |
31 | ## Extra options
32 | * Show and hide grid.
33 | * Show and hide track part number
34 |
35 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/directive/dragAndDrop/dragAndDrop.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule, ModuleWithProviders } from '@angular/core';
2 | import { DragAndDropService } from "./dragAndDrop.service";
3 | import { DragStartDirective, DragOverDirective, DropDirective, DragSuccessDirective } from "./dragAndDrop.directive";
4 |
5 | export { DragAndDropService };
6 |
7 | @NgModule({
8 | declarations: [DragStartDirective, DragSuccessDirective, DropDirective, DragOverDirective],
9 | exports: [DragStartDirective, DragSuccessDirective, DropDirective, DragOverDirective],
10 | })
11 | export class DragAndDropModule {
12 | static forRoot(): ModuleWithProviders {
13 | return {
14 | ngModule: DragAndDropModule,
15 | providers: [ DragAndDropService ]
16 | };
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/interactor-font-icons/Read Me.txt:
--------------------------------------------------------------------------------
1 | Open *demo.html* to see a list of all the glyphs in your font along with their codes/ligatures.
2 |
3 | To use the generated font in desktop programs, you can install the TTF font. In order to copy the character associated with each icon, refer to the text box at the bottom right corner of each glyph in demo.html. The character inside this text box may be invisible; but it can still be copied. See this guide for more info: https://icomoon.io/#docs/local-fonts
4 |
5 | You won't need any of the files located under the *demo-files* directory when including the generated font in your own projects.
6 |
7 | You can import *selection.json* back to the IcoMoon app using the *Import Icons* button (or via Main Menu → Manage Projects) to retrieve your icon selection.
8 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/dialog/dialog.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule, ModuleWithProviders } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 |
4 | import { DialogComponent } from './dialog.component';
5 | import { DialogService } from './dialog.service';
6 |
7 |
8 | export { DialogService, DialogComponent };
9 | export * from './dialog.interface'; //<- this do not work in plunker for some reason. But you get the idea.
10 | import { FormsModule } from "@angular/forms";
11 |
12 |
13 | @NgModule({
14 | imports: [ CommonModule, FormsModule ],
15 | declarations: [ DialogComponent ],
16 | exports: [ DialogComponent ]
17 | })
18 | export class DialogModule {
19 | static forRoot() {
20 | return {
21 | ngModule: DialogModule,
22 | providers: [ DialogService ]
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/directive/dragAndDrop/dragAndDrop.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 |
3 | @Injectable()
4 | export class DragAndDropService {
5 |
6 | private success: boolean;
7 | private data: any;
8 |
9 | constructor() {
10 | this.data = {};
11 | this.success = false;
12 | }
13 |
14 | clear() {
15 | this.data = {};
16 | this.success = false;
17 | }
18 |
19 | setData(type: string, data: any) {
20 | this.data[type] = data;
21 | }
22 |
23 | getData(type: string): any | null {
24 | if (this.data[type]) {
25 | return this.data[type];
26 | }
27 | return null;
28 | }
29 |
30 | setSuccess(success: boolean){
31 | this.success = true;
32 | }
33 |
34 | getSuccess():boolean{
35 | return this.success;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/subMenu/subMenu.component.css:
--------------------------------------------------------------------------------
1 | .sub-menu {
2 | display: flex;
3 | flex-wrap: wrap;
4 | background-color: #e0e0e0;
5 | }
6 |
7 | .disableBackground {
8 | background-color: transparent;
9 | }
10 |
11 | .button {
12 | padding: 0.2em 0.75em;
13 | color: white;
14 | /*color: #444444;*/
15 | user-select: none;
16 | cursor: default;
17 | }
18 |
19 | .button+.button{
20 | margin-left: 0.5em;
21 | }
22 |
23 | .button:hover {
24 | background-color: rgba(0, 0, 0, 0.10);
25 | }
26 |
27 | .button:active {
28 | background-color: rgba(0, 0, 0, 0.2);
29 | }
30 |
31 | button {
32 | display: flex;
33 | align-items: center;
34 | height: 2.25em;
35 | background-color: transparent;
36 | }
37 |
38 | button *+*{
39 | margin-left: 0.25em;
40 | }
41 |
42 | i {
43 | font-size: 1.25em;
44 | }
45 |
46 | i.big {
47 | font-size: 1.5em;
48 | }
49 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/dialog/dialog.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
{{dialog.heading}}
6 |
{{dialog.content}}
7 |
8 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to Wintergatan midi to laser cutter
2 |
3 | ## Issue Contributions
4 |
5 | When opening issues, search for it to see if it doesn't already exist.
6 |
7 | ## Code Contributions
8 |
9 | Contact [whitebird](https://github.com/whitebird) if you wish to join the organisation to contribute code. This is also possible without joining, but mention that to him. You can contact him on Gitter : https://gitter.im/Wintergatan/Midi-to-laser-cutter
10 | Before adding a feature, check the To-Do list at the project overview: https://github.com/Wintergatan/Midi-to-laser-cutter/projects/2
11 |
12 | [Specific information about the experimental version](https://github.com/Wintergatan/Midi-to-laser-cutter/blob/master/experimental/musicboxeditor/README.md)
13 |
14 | There are currently two versions: main and experimental. THe experimental version has the most features at the moment and is most actively being developed.
15 | Before adding a feature, mention it in the Gitter lobby.
16 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/contextMenu/contextMenu.directive.ts:
--------------------------------------------------------------------------------
1 | import { Directive, ElementRef, HostListener, Input } from '@angular/core';
2 | import { ContextMenuService } from "./contextMenu.service";
3 | import { IContextMenuOptions } from "./contextMenu.interface";
4 |
5 |
6 | @Directive({
7 | selector: '[context-menu]'
8 | })
9 | export class ContextMenuDirective {
10 | @Input('context-menu') private options: IContextMenuOptions;
11 |
12 | constructor(private contextMenuService: ContextMenuService) { }
13 |
14 | @HostListener('contextmenu', ['$event'])
15 | onMouseEnter(event: MouseEvent) {
16 | if (this.options) {
17 | this.options.x = event.clientX;
18 | this.options.y = event.clientY;
19 | this.contextMenuService.openContextMenu(this.options);
20 | event.preventDefault();
21 | }
22 | }
23 |
24 | @HostListener('mousedown')
25 | onMouseDown() {
26 | this.contextMenuService.closeContextMenu();
27 | }
28 | }
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/contextMenu/contextMenu.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule, ModuleWithProviders } from '@angular/core';
2 | import { CommonModule } from '@angular/common';
3 | import { ContextMenuComponent } from "./contextMenu.component";
4 | import { ContextMenuService } from "./contextMenu.service";
5 | import { ContextMenuDirective } from "./contextMenu.directive";
6 | import { ContextMenuRendererComponent } from "./contextMenuRenderer.component";
7 |
8 |
9 | export { ContextMenuDirective, ContextMenuComponent, ContextMenuService }
10 | export * from './contextMenu.interface';
11 |
12 | @NgModule({
13 | imports: [ CommonModule ],
14 | declarations: [ ContextMenuComponent, ContextMenuRendererComponent, ContextMenuDirective ],
15 | exports: [ ContextMenuComponent, ContextMenuRendererComponent, ContextMenuDirective ]
16 | })
17 | export class ContextMenuModule {
18 | static forRoot() {
19 | return {
20 | ngModule: ContextMenuModule,
21 | providers: [ ContextMenuService ]
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/experimental/sandbox/inc/scalemodes.js:
--------------------------------------------------------------------------------
1 |
2 | // Can anyone fill in the blanks??
3 |
4 | var scaleModes = {
5 | major: {
6 | ionian: [2,2,1,2,2,2,1], // last 1 added for 'wrap around'
7 | dorian: [2,1,2,2,2,1,2],
8 | phyrigian: [1,2,2,2,1,2,2],
9 | lydian: [2,2,2,1,2,2,1],
10 | mixolydian: [2,2,1,2,2,1,2],
11 | aeolian: [2,1,2,2,1,2,2],
12 | locrian: [1,2,2,1,2,2,2]
13 | },
14 | harmonic_minor: {
15 | harmminor: [2,1,2,2,1,3,1],
16 | locriansharpsix:[1,2,2,1,3,1,2],
17 | ionianaug: [2,2,1,3,1,2,1],
18 | romanian: [2,1,3,1,2,1,2],
19 | phrygiandom: [1,3,1,2,1,2,2],
20 | lydiansharptwo: [3,1,2,1,2,2,1],
21 | ultralocrian: [1,2,1,2,2,1,3]
22 | },
23 | melodic_minor: {
24 | jazz_minor: [2,1,2,2,2,2,1],
25 | dorianflatnine: [1,2,2,2,2,1,2],
26 | lydianaug: [2,2,2,2,1,2,1],
27 | lydiandom: [2,2,2,1,2,1,2],
28 | mixolydianflatsix: [2,2,1,2,1,2,2],
29 | semilocrian: [2,1,2,1,2,2,2],
30 | superlocrian: [1,2,1,2,2,2,2]
31 | }
32 | };
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 Wintergatan
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/main.test.ts:
--------------------------------------------------------------------------------
1 | /*when hosting .html*/
2 | /*
3 | import 'jasmine-core/lib/jasmine-core/jasmine.css';
4 | import 'jasmine-core/lib/jasmine-core/jasmine.js';
5 | import 'jasmine-core/lib/jasmine-core/jasmine-html.js';
6 | import 'jasmine-core/lib/jasmine-core/boot.js';
7 | */
8 |
9 | import 'reflect-metadata';
10 | import 'core-js/es6';
11 | import 'core-js/es7/reflect';
12 |
13 | import "zone.js/dist/zone";
14 | import "zone.js/dist/long-stack-trace-zone";
15 | import "zone.js/dist/async-test";
16 | import "zone.js/dist/fake-async-test";
17 | import "zone.js/dist/sync-test";
18 | import "zone.js/dist/proxy";
19 | import "zone.js/dist/jasmine-patch";
20 |
21 | import 'rxjs/add/operator/map';
22 | import 'rxjs/add/observable/of';
23 |
24 | import { TestBed } from "@angular/core/testing";
25 | import { BrowserDynamicTestingModule, platformBrowserDynamicTesting} from "@angular/platform-browser-dynamic/testing";
26 |
27 | TestBed.initTestEnvironment(
28 | BrowserDynamicTestingModule,
29 | platformBrowserDynamicTesting());
30 |
31 | let testContext = require.context('./app', true, /\.spec/);
32 | testContext.keys().forEach(testContext);
--------------------------------------------------------------------------------
/experimental/sandbox/templates/A4-01.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
16 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/interactor-font-icons/demo-files/demo.js:
--------------------------------------------------------------------------------
1 | if (!('boxShadow' in document.body.style)) {
2 | document.body.setAttribute('class', 'noBoxShadow');
3 | }
4 |
5 | document.body.addEventListener("click", function(e) {
6 | var target = e.target;
7 | if (target.tagName === "INPUT" &&
8 | target.getAttribute('class').indexOf('liga') === -1) {
9 | target.select();
10 | }
11 | });
12 |
13 | (function() {
14 | var fontSize = document.getElementById('fontSize'),
15 | testDrive = document.getElementById('testDrive'),
16 | testText = document.getElementById('testText');
17 | function updateTest() {
18 | testDrive.innerHTML = testText.value || String.fromCharCode(160);
19 | if (window.icomoonLiga) {
20 | window.icomoonLiga(testDrive);
21 | }
22 | }
23 | function updateSize() {
24 | testDrive.style.fontSize = fontSize.value + 'px';
25 | }
26 | fontSize.addEventListener('change', updateSize, false);
27 | testText.addEventListener('input', updateTest, false);
28 | testText.addEventListener('change', updateTest, false);
29 | updateSize();
30 | }());
31 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core';
2 | import { BrowserModule } from '@angular/platform-browser';
3 | import { FormsModule } from '@angular/forms';
4 |
5 | import { AppComponent } from './app.component';
6 | import { TabMenuModule, ITabMenuComponentOptions, ITabMenuButton } from './ui/tabMenu/tabMenu.module';
7 | import { SubMenuModule } from './ui/subMenu/subMenu.module';
8 | import { HintModule } from './ui/hint/hint.module';
9 | import { DialogModule } from './ui/dialog/dialog.module';
10 |
11 | import { DragAndDropModule } from "./directive/dragAndDrop/dragAndDrop.module";
12 |
13 |
14 | import { LogModule } from './service/log/log.module';
15 | import { ContextMenuModule } from "./ui/contextMenu/contextMenu.module";
16 | import { MtosStateModule } from "./service/mtosState/mtosState.module";
17 |
18 | @NgModule({
19 | imports: [
20 | BrowserModule,
21 | FormsModule,
22 | LogModule.forRoot(),
23 | MtosStateModule.forRoot(),
24 | DragAndDropModule.forRoot(),
25 | TabMenuModule,
26 | SubMenuModule,
27 | HintModule.forRoot(),
28 | DialogModule.forRoot(),
29 | ContextMenuModule.forRoot(),
30 | ],
31 | declarations: [AppComponent],
32 | bootstrap: [AppComponent]
33 | })
34 | export class AppModule {
35 | }
36 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/hint/hint.directive.ts:
--------------------------------------------------------------------------------
1 | import { Directive, ElementRef, HostListener, Input } from '@angular/core';
2 | import { HintService } from './hint.service';
3 |
4 |
5 | @Directive({
6 | selector: '[hint]'
7 | })
8 | export class Hint {
9 | @Input('hint') private hint: string;
10 |
11 | private timeout;
12 |
13 | constructor(private hintService: HintService) {}
14 |
15 |
16 | private openHint(bbox: ClientRect) {
17 | if (this.hintService) {
18 | this.hintService.open(this.hint, bbox);
19 | }
20 | }
21 |
22 | private closeHint() {
23 | if (this.hintService) {
24 | this.hintService.close();
25 | }
26 | }
27 |
28 | @HostListener('mouseenter', ['$event'])
29 | onMouseEnter(event:MouseEvent) {
30 | if(this.hint && this.hint.trim() !== ''){
31 | this.timeout = setTimeout(()=>{
32 | this.openHint((event.target).getBoundingClientRect());
33 | }, 200);
34 | }
35 | }
36 |
37 | @HostListener('mouseleave')
38 | onMouseLeave() {
39 | clearTimeout(this.timeout);
40 | this.closeHint();
41 | }
42 |
43 | @HostListener('mousedown')
44 | onMouseDown() {
45 | clearTimeout(this.timeout);
46 | this.closeHint();
47 | }
48 | }
--------------------------------------------------------------------------------
/dev/midi_libraries/styles/styles.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: Arial, sans-serif;
3 | font-size: 100%;
4 | margin: 0;
5 | padding: 0;
6 | background-color: #f2f2f2;
7 | }
8 |
9 | #container {
10 | position: relative;
11 | width: 85%;
12 | min-height: 720px;
13 | margin-left: auto;
14 | margin-right: auto;
15 | margin-top: 20px;
16 | padding: 20px;
17 | }
18 |
19 | #controls {
20 | position: relative;
21 | width: 16%;
22 | float: left;
23 | }
24 |
25 | #output {
26 | position: relative;
27 | border: 1px solid darkgray;
28 | float: right;
29 | width: 75%;
30 | min-height: 680px;
31 | border-radius: 10px;
32 | background-color: white;
33 | padding: 20px;
34 | }
35 |
36 | h1 {
37 | margin-top: 0;
38 | font-size: 1em;
39 | }
40 |
41 | #controls p {
42 | font-size: 0.6em;
43 | }
44 |
45 | #json-view {
46 | position: relative;
47 | width: 99%;
48 | min-height: 680px;
49 | overflow: scroll;
50 | }
51 | header{
52 | margin-top:10px;
53 | position: relative;
54 | width: 85%;
55 | height: 20px;
56 | margin-left:auto;
57 | margin-right:auto;
58 | padding-left: 25%;
59 | }
60 | header a{
61 |
62 | display:inline-block;
63 | width: 150px;
64 | height: 40px;
65 | line-height: 40px;
66 | background-color: darkgray;
67 | color:white;
68 | text-align: center;
69 | margin-right: 20px;
70 | border-radius: 5px;
71 | }
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/hint/hint.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 | import { HintModule, HintComponent } from './hint.module';
3 | import { HintService } from "./hint.service";
4 |
5 | describe('HintComponent', () => {
6 |
7 | let fixture: ComponentFixture;
8 | let comp: HintComponent;
9 | let el: HTMLElement;
10 | let service: HintService;
11 |
12 | beforeEach(() => {
13 |
14 | TestBed.configureTestingModule({
15 | imports: [
16 | HintModule.forRoot()
17 | ]
18 | });
19 |
20 | fixture = TestBed.createComponent(HintComponent);
21 | comp = fixture.componentInstance;
22 | el = fixture.debugElement.nativeElement;
23 | service = fixture.debugElement.injector.get(HintService);
24 |
25 | });
26 |
27 | it('should create the HintComponent', () => {
28 | expect(comp).toBeTruthy();
29 | });
30 |
31 |
32 | it('should have default values', () => {
33 | expect(comp.hint).toBeUndefined();
34 | expect(comp.pos.x).toBe(0);
35 | expect(comp.pos.y).toBe(0);
36 | expect(comp.bbox).toBeUndefined();
37 | });
38 |
39 | it('should display hint', ()=>{
40 | service.open('This is a hint', {top: 0, left: 0, bottom: 100, right: 100, width: 100, height: 100 })
41 |
42 | fixture.detectChanges();
43 |
44 | expect(comp.hint).toBe('This is a hint');
45 | expect(el.getElementsByTagName('label')[0].textContent).toBe('This is a hint');
46 | });
47 |
48 | });
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/script/iconFont.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 |
3 | function getContent(className, str){
4 | var regex = new RegExp('\.int-icon-' + className + '[\\s\\S]*?(".*")[\\s\\S]*?}');
5 | var m;
6 | if ((m = regex.exec(str)) !== null) {
7 | return m[1];
8 | }
9 | console.log(regex);
10 | }
11 |
12 | var fontFile = fs.readFileSync('../interactor-font-icons/fonts/interactor-icons.ttf').toString('base64');
13 | var cssFile = fs.readFileSync('../interactor-font-icons/style.css').toString();
14 | var templateFile = fs.readFileSync('./template.css').toString();
15 |
16 | var newFile = templateFile.replace(/FILE/, fontFile);
17 |
18 |
19 | const classReg = /(\.int-icon-[\s\S]*?})/g;
20 | let m;
21 | let strings = [];
22 | while ((m = classReg.exec(cssFile)) !== null) {
23 | if (m.index === classReg.lastIndex) {
24 | classReg.lastIndex++;
25 | }
26 |
27 | if(m){
28 | strings.push(m[1]);
29 | }
30 | }
31 |
32 | newFile = newFile.replace(/STYLES/, strings.join('\n'));
33 |
34 |
35 | //const radioReg = /\.int-icon-radiobox[\s\S]*?(".*")[\s\S]*?}/;
36 |
37 | newFile = newFile.replace(/RADIO_CONTENT/, getContent('radiobox', cssFile));
38 | newFile = newFile.replace(/RADIO_CHECKED_CONTENT/, getContent('radiobox-marked', cssFile));
39 | newFile = newFile.replace(/CHECKBOX_CONTENT/, getContent('checkbox-o', cssFile));
40 | newFile = newFile.replace(/CHECKBOX_CHECKED_CONTENT/, getContent('checkbox', cssFile));
41 |
42 | fs.writeFileSync('../../interactor-icons.css', newFile);
43 |
44 | //console.log(newFile);
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/service/mtosState/mtosState.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 |
3 |
4 | export interface IHeader {
5 | PPQ?: number;
6 | bpm?: number;
7 | timeSignature?: number[];
8 | }
9 |
10 | export interface INote {
11 | name?: string;
12 | midi?: number;
13 | time?: number;
14 | velocity?: number;
15 | duration?: number;
16 | }
17 |
18 | export interface ITrack {
19 | duration?: number;
20 | name?: string;
21 | notes?: INote[];
22 | controlChanges?: any;
23 | instrumentNumber?: number;
24 | }
25 |
26 |
27 | @Injectable()
28 | export class MtosStateService {
29 |
30 | public header: IHeader;
31 | public tracks: ITrack[];
32 | public selectedTrack: ITrack;
33 | public selectedNote: INote;
34 |
35 | constructor() { }
36 |
37 | setHeader(header: IHeader){
38 | this.header = header;
39 | }
40 |
41 | setTracks(tracks: ITrack[]){
42 | this.tracks = tracks;
43 | }
44 |
45 | selectTrack(index: number){
46 | if(index < 0 || index >= this.tracks.length){
47 | console.log('selectTrack: invalid track index.');
48 | return;
49 | }
50 |
51 | this.selectedTrack = this.tracks[index];
52 | this.selectedNote = false;
53 | }
54 |
55 | selectNote(index: number){
56 | if(index < 0 || index >= this.selectedTrack.notes.length){
57 | console.log('selectNote: invalid note index.');
58 | return;
59 | }
60 |
61 | this.selectedNote = this.selectedTrack.notes[index];
62 | }
63 | }
--------------------------------------------------------------------------------
/experimental/sandbox/inc/scalesandnotes.js:
--------------------------------------------------------------------------------
1 |
2 | var noteLetters = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
3 |
4 | var scaleModes = {
5 | major: {
6 | ionian: [2,2,1,2,2,2,1], // last 1 added for 'wrap around'
7 | dorian: [2,1,2,2,2,1,2],
8 | phyrigian: [1,2,2,2,1,2,2],
9 | lydian: [2,2,2,1,2,2,1],
10 | mixolydian: [2,2,1,2,2,1,2],
11 | aeolian: [2,1,2,2,1,2,2],
12 | locrian: [1,2,2,1,2,2,2]
13 | },
14 | harmonic_minor: {
15 | harmminor: [2,1,2,2,1,3,1],
16 | locriansharpsix:[1,2,2,1,3,1,2],
17 | ionianaug: [2,2,1,3,1,2,1],
18 | romanian: [2,1,3,1,2,1,2],
19 | phrygiandom: [1,3,1,2,1,2,2],
20 | lydiansharptwo: [3,1,2,1,2,2,1],
21 | ultralocrian: [1,2,1,2,2,1,3]
22 | },
23 | melodic_minor: {
24 | jazz_minor: [2,1,2,2,2,2,1],
25 | dorianflatnine: [1,2,2,2,2,1,2],
26 | lydianaug: [2,2,2,2,1,2,1],
27 | lydiandom: [2,2,2,1,2,1,2],
28 | mixolydianflatsix: [2,2,1,2,1,2,2],
29 | semilocrian: [2,1,2,1,2,2,2],
30 | superlocrian: [1,2,1,2,2,2,2]
31 | }
32 | };
33 |
34 |
35 |
36 | function getOctaveFromNoteNumber(noteNumber){
37 | //return Math.floor(noteNumber/12) - 1; // Possibly -1 depending on which 'standard' you work with
38 | return Math.floor(noteNumber/12);
39 | }
40 |
41 |
42 | function noteNumberToNoteName(noteNumber, showOctave){
43 |
44 | var noteName = noteLetters[noteNumber % 12];
45 | if(showOctave){
46 | noteName += getOctaveFromNoteNumber(noteNumber);
47 | }
48 |
49 | return noteName;
50 | }
51 |
--------------------------------------------------------------------------------
/experimental/sandbox/inc/scales.js:
--------------------------------------------------------------------------------
1 | var noteLetters = ["c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "b"]
2 | var notes = [];
3 |
4 | for (var num = 0; num < 128; num++) {
5 | notes.push({letter: noteLetters[num%12], octave: Math.floor(num/12)});
6 | }
7 |
8 | var scaleModes = {
9 | major: {
10 | ionian: [2,2,1,2,2,2],
11 | dorian: [2,1,2,2,2,1],
12 | phyrigian: [1,2,2,2,1,2],
13 | lydian: [2,2,2,1,2,2],
14 | mixolydian: [2,2,1,2,2,1],
15 | aeolian: [2,1,2,2,1,2],
16 | locrian: [1,2,2,1,2,2]
17 | },
18 | harmonic_minor: {
19 | harmminor: [2,1,2,2,1,3],
20 | locriansharpsix:[1,2,2,1,3,1],
21 | ionianaug: [2,2,1,3,1,2],
22 | romanian: [2,1,3,1,2,1],
23 | phrygiandom: [1,3,1,2,1,2],
24 | lydiansharptwo: [3,1,2,1,2,2],
25 | ultralocrian: [1,2,1,2,2,1]
26 | },
27 | melodic_minor: {
28 | jazz_minor: [2,1,2,2,2,2],
29 | dorianflatnine: [1,2,2,2,2,1],
30 | lydianaug: [2,2,2,2,1,2],
31 | lydiandom: [2,2,2,1,2,1],
32 | mixolydianflatsix: [2,2,1,2,1,2],
33 | semilocrian: [2,1,2,1,2,2],
34 | superlocrian: [1,2,1,2,2,2]
35 | }
36 | };
37 |
38 | function generateScale(root, scale, mode) {
39 | var result = [];
40 | var gaps = scaleModes[scale][mode];
41 | if (gaps === undefined) return undefined;
42 | result.push(root);
43 | var lastNoteNum = noteLetters.indexOf(root);
44 | for (var i=0; ivoid){
36 | var dialog: IDialog = {
37 | heading: heading,
38 | content: content,
39 | select: [select],
40 | level: 'info',
41 | buttons: [{ text: 'Ok', callback: callback }]
42 | }
43 |
44 | return this.openDialog(dialog);
45 | }
46 |
47 | public openQuestion(heading: string, content: string, confirm: ()=>void, decline: ()=>void){
48 | var dialog: IDialog = {
49 | heading: heading,
50 | content: content,
51 | level: 'info',
52 | buttons: [
53 | { text: 'Yes', callback: confirm },
54 | { text: 'No', callback: decline }
55 | ]
56 | }
57 |
58 | return this.openDialog(dialog);
59 | }
60 | }
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/persons.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/README.md:
--------------------------------------------------------------------------------
1 | # Warning
2 |
3 | **This project environment is setup to work on windows. I can not guarantee it will work in other environments**.
4 |
5 | # Prerequisites
6 |
7 | You will need [Node js](https://nodejs.org/en/) or node package manager.
8 |
9 | IDE that supports [Typescript](https://www.typescriptlang.org/). I recommend [Visual studio code](https://code.visualstudio.com/)
10 |
11 | This project uses Angular 2 as a framwork. If you do not know it here are some places to start.
12 |
13 | [angular.io](https://angular.io/) and
14 | [egghead.io](https://egghead.io/courses/get-started-with-angular-2)
15 |
16 | # Getting started
17 |
18 | Open CMD in the same folder as package.js.
19 |
20 | Type and run `npm install`
21 |
22 | This will download all dependencies.
23 |
24 | Type and run `npm run build:dev`
25 |
26 | This will build the project to the dist folder and watch the project files.
27 | First run will takes some time but the next after that will be way faster.
28 | If you make changes to the files it will automatically rebuild the project.
29 |
30 | You will get some typing errors. Do not mind those. They have no effect on the acctual code.
31 |
32 | Open a new CMD and type and run `npm run server`
33 |
34 | This will server the file from a small server and it should open a browser on the correct page.
35 |
36 | Happy coding.
37 |
38 | # Build new version
39 |
40 | Type and run `npm run build:prod`
41 |
42 | Open a new CMD and type and run `npm run server`
43 |
44 | Test application.
45 |
46 | Copy the content in build folder.
47 |
48 | Remove app.[hash].js and polyfills.[hash].js from dist folder.
49 |
50 | Paste clipboard to dist folder. Overwrite every file.
51 |
52 | Commit, push and check if your changes appears on the website.
--------------------------------------------------------------------------------
/experimental/musicboxeditor/karma.config.js:
--------------------------------------------------------------------------------
1 | const webpackConfig = require("./webpack.config.js");
2 |
3 | var testEnvironment = process.env.TEST_ENVIRONMENT || 'prod';
4 |
5 | console.log('Testing with test environment: ', testEnvironment);
6 |
7 | var karmaConfig = {
8 | basePath: '',
9 |
10 | frameworks: ['jasmine'],
11 |
12 | exclude:[],
13 |
14 | files: [
15 | {pattern: './src/main.test.ts', watched: false},
16 | {pattern: './src/styles.css', watched: false},
17 | {pattern: './src/assets/icons/interactor-icons.css', watched: false}
18 | ],
19 |
20 | preprocessors: {
21 | './src/main.test.ts':["webpack", 'sourcemap']
22 | },
23 | webpack: webpackConfig,
24 |
25 | webpackServer: {noInfo: true},
26 |
27 | port: 9876,
28 |
29 | colors: true,
30 |
31 | reporters: ["spec"],
32 |
33 | specReporter: {
34 | maxLogLines: 5, // limit number of lines logged per test
35 | suppressErrorSummary: true, // do not print error summary
36 | suppressFailed: false, // do not print information about failed tests
37 | suppressPassed: false, // do not print information about passed tests
38 | suppressSkipped: true, // do not print information about skipped tests
39 | showSpecTiming: true // print the time elapsed for each spec
40 | },
41 |
42 | browsers: ['Chrome'],
43 |
44 | mime: {
45 | 'text/x-typescript': ['ts','tsx']
46 | },
47 |
48 | concurrency: Infinity,
49 |
50 | autoWatch: false,
51 |
52 | singleRun: true,
53 | };
54 |
55 | if(testEnvironment == 'dev'){
56 | karmaConfig.autoWatch = true;
57 | karmaConfig.singleRun = false;
58 | }
59 |
60 | module.exports = function (config) {
61 | config.set(karmaConfig);
62 | };
63 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/script/template.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'interactor-icons';
3 | src: url(data:application/octet-stream;charset=utf-8;base64,FILE) format('truetype');
4 | }
5 |
6 | [class^="int-icon-"], [class*=" int-icon-"] {
7 | /* use !important to prevent issues with browser extensions that change fonts */
8 | font-family: 'interactor-icons' !important;
9 | speak: none;
10 | font-style: normal;
11 | font-weight: normal;
12 | font-variant: normal;
13 | text-transform: none;
14 | line-height: 1em;
15 | /* Better Font Rendering =========== */
16 | -webkit-font-smoothing: antialiased;
17 | -moz-osx-font-smoothing: grayscale;
18 | }
19 |
20 | .icon-click {
21 | padding: 0.2em;
22 | }
23 |
24 | .icon-click:hover {
25 | background-color: rgba(0, 0, 0, 0.10);
26 | }
27 |
28 | .icon-click:active {
29 | background-color: rgba(0, 0, 0, 0.2);
30 | }
31 |
32 | input[type=radio], input[type=checkbox] {
33 | font-family: 'interactor-icons' !important;
34 | font-size: 1em;
35 | font-style: normal;
36 | font-weight: normal;
37 | font-variant: normal;
38 | text-transform: none;
39 | line-height: 1em;
40 | /* Better Font Rendering =========== */
41 | -webkit-font-smoothing: antialiased;
42 | -moz-osx-font-smoothing: grayscale;
43 |
44 | padding: 0;
45 | margin: 0;
46 | border: none;
47 | box-shadow: none;
48 | background: transparent;
49 | -webkit-appearance: none;
50 | }
51 |
52 | input[type=radio]::before {
53 | content: RADIO_CONTENT;
54 | }
55 |
56 | input[type=radio]:checked::before {
57 | content: RADIO_CHECKED_CONTENT;
58 | }
59 |
60 | input[type=checkbox]::before {
61 | content: CHECKBOX_CONTENT;
62 | }
63 |
64 | input[type=checkbox]:checked::before {
65 | content: CHECKBOX_CHECKED_CONTENT;
66 | }
67 |
68 | STYLES
--------------------------------------------------------------------------------
/dev/midi_libraries/MidiConvert.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | MidiConvert.js Object Viewer
6 |
7 |
8 |
9 |
10 |
41 |
42 |
43 |
44 |
45 |
46 |
49 |
50 |
51 |
MidiConvert.js object viewer
52 |
53 |
Load a MIDI file. A JSON reprsentation of the parsed MIDI will be displayed below.
54 |
MidiConvert GitHub
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/contextMenu/contextMenuRenderer.component.ts:
--------------------------------------------------------------------------------
1 | //our root app component
2 | import { Component, ViewChild, ElementRef, OnInit, Input } from '@angular/core';
3 | import { ContextMenuService } from "./contextMenu.service";
4 | import { IContextMenuOptions } from "./contextMenu.interface";
5 |
6 | @Component({
7 | selector: 'context-menu-renderer',
8 | templateUrl: './contextMenuRenderer.component.html',
9 | styleUrls: ['./contextMenuRenderer.component.css']
10 | })
11 | export class ContextMenuRendererComponent implements OnInit {
12 |
13 | @Input() options: IContextMenuOptions
14 |
15 | constructor(private elementRef: ElementRef, private contextMenuService: ContextMenuService) {
16 |
17 | }
18 |
19 | ngOnInit(): void {
20 | this.contextMenuService.setRenderer(this);
21 | }
22 |
23 | //logic
24 | open(options: IContextMenuOptions) {
25 | if (!options) {
26 | return;
27 | }
28 | this.options = options;
29 | setTimeout(()=>{
30 | this.elementRef.nativeElement.children[0].focus();
31 | }, 0);
32 | }
33 |
34 | close() {
35 | this.options = null;
36 | }
37 |
38 | getEncapsulationId(): string {
39 | if (!this.elementRef) {
40 | return '';
41 | }
42 |
43 | var attr = this.elementRef.nativeElement.attributes;
44 | for(let i = 0; i < attr.length; i++){
45 | let s:string = attr[i].name;
46 | if(s.includes('_nghost')){
47 | return '_ngcontent' + s.substring(7);
48 | }
49 | }
50 |
51 | return '';
52 | }
53 |
54 | //template
55 | showContextMenu(): boolean {
56 | if (!this.options) {
57 | return false;
58 | }
59 |
60 | return true;
61 | }
62 |
63 | onBlurContextMenu(){
64 | this.close();
65 | }
66 | }
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/app.component.css:
--------------------------------------------------------------------------------
1 | .app {
2 | position: absolute;
3 | top: 0;
4 | bottom: 0;
5 | right: 0;
6 | left: 0;
7 | padding: 0.5em;
8 | color: #444444;
9 | background-color: #f8f8f8;
10 | }
11 |
12 | .app>*+*{
13 | margin-top: 0.5em;
14 | }
15 |
16 | .header {
17 | display: flex;
18 | justify-content: space-between;
19 | color: #fff;
20 | background-color: #444;
21 | }
22 |
23 | .header>h1{
24 | padding: 0.25em;
25 | }
26 |
27 | sub-menu{
28 | color: white;
29 | }
30 |
31 | .main-view {
32 | display: flex;
33 | flex-direction: column;
34 | flex: 100 100 auto;
35 | min-height: 0;
36 | border: 1px solid #444444;
37 | background-color: white;
38 | }
39 |
40 | .menu-view{
41 | position: relative;
42 | display: flex;
43 | flex-wrap: wrap;
44 | align-items:stretch;
45 | }
46 |
47 | .cell{
48 | position: relative;
49 | flex: 100 100 33.3%;
50 | padding-bottom: 1em;
51 | }
52 |
53 | .sub-cell{
54 | overflow: auto;
55 | white-space:nowrap
56 | }
57 |
58 | .sub-cell>*{
59 | display: inline-block;
60 | }
61 |
62 | .menu-view>label>input,
63 | .menu-view>label>select{
64 | width: 200px;
65 | }
66 |
67 |
68 | .track-view{
69 | display: flex;
70 | border: 1px #666 solid;
71 | background-color: #fff;
72 | }
73 |
74 | .notes{
75 | border-right: 1px #666 solid;
76 | }
77 |
78 | text.note {
79 | cursor: pointer;
80 | }
81 |
82 | text.note:hover {
83 | fill: cornflowerblue;
84 | }
85 |
86 | .track{
87 | flex: 100 100 50%;
88 | min-width: 0;
89 | overflow-x: auto;
90 | }
91 |
92 | /*
93 | .main-view-column {
94 | position: relative;
95 | flex: 100 100 50%;
96 | min-width: 0;
97 | padding: 0.5em;
98 | overflow-x: hidden;
99 | overflow-y: auto;
100 | }
101 |
102 | .main-view-column+.main-view-column {
103 | border-left: 1px solid #444444;
104 | }
105 | */
106 |
--------------------------------------------------------------------------------
/dev/midi_libraries/midi_parser.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | midi-parser.js Object Viewer
6 |
7 |
8 |
9 |
10 |
42 |
43 |
44 |
45 |
46 |
49 |
50 |
51 |
52 |
midi-parser.js object viewer
53 |
54 |
Load a MIDI file. A JSON reprsentation of the parsed MIDI will be displayed below.
55 |
mid-parser.js GitHub
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/hint/hint.component.ts:
--------------------------------------------------------------------------------
1 | import {Component, ViewChild, ElementRef} from '@angular/core'
2 |
3 | import {HintService} from './hint.service';
4 |
5 | @Component({
6 | selector: 'hint-renderer',
7 | providers: [],
8 | templateUrl: './hint.component.html',
9 | styleUrls: ['./hint.component.css'],
10 | })
11 | export class HintComponent {
12 | private offset = 3;
13 |
14 |
15 | @ViewChild('box') public hintBox: ElementRef;
16 |
17 | public hint: string;
18 | public pos: { x: number, y: number };
19 | public bbox: ClientRect;
20 |
21 |
22 | constructor( private hintService: HintService) {
23 | this.hintService.setRenderer(this);
24 | this.pos = {x: 0, y: 0};
25 | }
26 |
27 |
28 | public close() {
29 | this.hint = null;
30 | }
31 |
32 | public open(hint: string, bbox: ClientRect) {
33 | this.hint = hint;
34 | this.bbox = this.getBbox();
35 |
36 | var left = bbox.left;
37 | if(left + this.bbox.width > window.innerWidth){
38 | left = bbox.right - this.bbox.width;
39 | }
40 |
41 | if(left < 0){
42 | left = 0 + this.offset;
43 | }
44 |
45 | var top = bbox.bottom + this.offset;
46 | if(top + this.bbox.height > window.innerHeight){
47 | top = bbox.top - this.bbox.height - this.offset;
48 | }
49 |
50 | if(top < 0){
51 | top = 0 + this.offset;
52 | }
53 |
54 | this.pos.x = left;
55 | this.pos.y = top;
56 | }
57 |
58 | public getBbox(): ClientRect {
59 | var test = this.getVirtualBox();
60 | document.body.appendChild(test);
61 | var bbox = test.children[0].getBoundingClientRect();
62 | document.body.removeChild(test);
63 | return bbox;
64 | }
65 |
66 | public getVirtualBox(): HTMLElement {
67 | var tag = document.createElement("hint-renderer");
68 | var box = document.createElement("div");
69 | var text = document.createElement("label");
70 | box.classList.add('box');
71 | text.classList.add('text');
72 | text.innerText = this.hint;
73 | box.appendChild(text);
74 | tag.appendChild(box);
75 |
76 | return tag;
77 | }
78 | }
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/tabMenu/tabMenu.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, Input } from '@angular/core';
2 | import { ITabMenuComponentOptions, ITabMenuButton } from './tabMenu.interface';
3 |
4 | @Component({
5 | selector: 'tab-menu',
6 | templateUrl: './tabMenu.component.html',
7 | styleUrls: ['./tabMenu.component.css'],
8 | })
9 | export class TabMenuComponent implements OnInit {
10 |
11 |
12 | @Input() options: ITabMenuComponentOptions;
13 |
14 | public selected: ITabMenuButton = null;
15 |
16 | constructor() { }
17 |
18 | ngOnInit(): void {
19 | if(this.options){
20 | this.options.component = this;
21 | if(this.options.onInit){
22 | this.options.onInit();
23 | }
24 | }
25 | }
26 |
27 | selectButton(indexOrButton: number | ITabMenuButton){
28 | let button: ITabMenuButton;
29 |
30 | if(typeof indexOrButton === 'number'){
31 | if(indexOrButton < 0 || indexOrButton >= this.options.buttons.length){
32 | return;
33 | }
34 | button = this.options.buttons[indexOrButton];
35 | }else{
36 | button = indexOrButton;
37 | }
38 |
39 | if(!button){ return; }
40 |
41 | if(button.callback && button.callback() === true){
42 | this.selected = button;
43 | }
44 | }
45 |
46 | onClickButton(button: ITabMenuButton) {
47 | this.selectButton(button);
48 | }
49 |
50 | showTabMenu():boolean {
51 | if(!this.options){
52 | return false;
53 | }
54 | return true;
55 | }
56 |
57 | getButtonClass(button: ITabMenuButton): Object {
58 | if(!button){ return {}; }
59 | return {
60 | isSelected: this.isSelectedButton(button)
61 | }
62 | }
63 |
64 | isSelectedButton(button: ITabMenuButton) {
65 | if(!button){ return false; }
66 | if(this.selected === button){
67 | return true;
68 | }
69 | return false;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/experimental/sandbox/templates/strip_dimensions.xml:
--------------------------------------------------------------------------------
1 | 7VvLcqM4FP0aV80skkISYLOMk56ZTVenKovpXspGtlUNyANyYufrR4AEekDs2DhxJ+1N4CJdxD33oSMpI3Sbbv/O8Xr1lcUkGUEv3o7Q3QhCOAk98aeU7GoJ8KGULHMaS1kreKDPRApVsw2NSWE05IwlnK5N4ZxlGZlzQ4bznD2ZzRYsMd+6xkviCB7mOHGl/9KYr6Q0DGD74B9Clyv1ahBG9ZMZnv9c5myTyReOIFpUv/pxipUy+aXFCsfsSROhLyN0mzPG66t0e0uS0rrKbnW/v3qeNgPPScYP6QDHdY9HnGyIGnI1ML5T1iBZfFMaVdzNE1wUdD5C04LjnLviFU8TIQDiMsbFisTazT3mnORZJYEerJTk7Ce5ZQnLq1chr/qJJ/UgSOzg1H4YaMwlHJGwlPB8J5o8tYAF0sgrDSoly0mCOX001WPpN8tGXfOGe0bFi6G3Vb4g9SgX90JTRcE2+ZzIXjoAtiK0T5Mw9JJwR5O40L67FVUA94A9ccBO8Zamm7T2cht4TrbcxDQnBX3Gs6pBCdO6HFU1zmA6Cu6EBCd0WUI8FzgRger0keScitC6kQ9SGsdl/2mCZySZNvGieYGMGOUFpQayNYCSgS9H0oaT7h+1a7sOIjVdedeeB8am7U/zDdWELRYFORUsf39gPq0oJw9rPC/vn0QuNsFyoisMZXQtaJIoecYyYkdrr90PiL++APGlW2vxCaDXEaFIgdllccOgL7n6Ga03gHWgb1ln0mEdz++wTtPzFOugDuuESRnrC1Z5cmum8L8NUw+uiqpS35TZ219v24fialn+feA5XYundzQlWUFZVii9YkS16rrhAanGtL/00g7HPTzhdAE+AJYWlOpWRzLqAHIIHAMHR87WX0W9oNnFWHjoxDJWX61CJ3BDZ9wVOAPYO3TsPWOcs/STmdxHb2dyd36akAX/4AYHYzOnwOjtDB45Bs/LF3x0i8PJ+5kcuHncMbRGwrpmbC9NXBpSJWyR774LoXcNgK8EPyqB502U4J7kon5XoFSTfLKlXPUK5H3ZCYhOvry3+4wO5G/iGyuiZMzaasajid6L5dncDI0tFYeyPFsR9C1Fw5E84BapKoDvcRzTbPlxIxi8ZwS7WfOzRPC7rcCAEJizEjVLefUSjMNVJ+dbgvE65zMfPTjhO05o1GgHZ7vbSye3g6MIrTjpoF6daxZDoNi1ojMEirtPhyKwUBy7KMJzoXjAqqZbJ4faVGjKoFYCq2Vg1FMDtXIb6MW2RWKIGe67llFkr0QqiF49xY1MRWNLz4A19Ci6NLQTAc2JNPf4rrvOD/1mIIp0aRyp0aMcKAqukf47kjI5es84KXNn73EJVEoz4SbQm5XWTPCObcrxCY+o9i28RXWFs9bWF1kyyqL2IMcE5b2xrVH+hiktoYWZYmR6ZTlXaUHuzPqlrPBmO9l95m6yRUnCgFFdrj2A9lM52Uujcr1lLJlVH7diOX0Ww8HJh1mhsbNEcOw+/NgqXwE8LN0Ix8E7rZncEe8fsG+y1kDui/amQXtce9qPw9e1B3Dy4oDERf2JxyZX5NKvotwmvNAjB1a4NmG876jKkYcUkDfqjB7tkAKKoAHQFRoocjq1DnqGAbmkbUG3VU2taqdbZXku0CmrLcmWvwuqU1BRxzmB81XUrmMCl1dRf5kzY+5uwrFnxuwFS0fTcHNj5DL2ImG8+MXS92lJGu1N0mYNvYKnOcywSbjzlMg3qVp87lStgM1ytfhVbNI/SpjrVn/2NatPP3xrR/mZczXwrakanPhOsgagI7/4Qb9nHJys3W2/i07W2tJaFEUjayer2drqpz9RNNHpTw/1ObQmXDbLAb6d8NGxpSMAtpOeh+cA3z4XB/cQEbsDmIytADiRiLhHiSoiIg/yf5JSFr6Yw0Ts+SEya9kwdOPK1AqgqWCYSueebzc2V+si5unzFym6/BMSb0k6rM3a4IykQ9y2/+xSQ97+TxH68j8=
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/dialog/dialog.component.css:
--------------------------------------------------------------------------------
1 | .dialog-renderer {
2 | font-family: sans-serif;
3 |
4 | display: block;
5 | position: absolute;
6 | top: 0;
7 | bottom: 0;
8 | right: 0;
9 | left: 0;
10 | }
11 |
12 | .background{
13 | position: absolute;
14 | width: 100%;
15 | height: 100%;
16 | background-color: transparent;
17 | background-color: rgba(0, 0, 0, 0.1);
18 | }
19 |
20 | .dialog-wrapper{
21 | display: flex;
22 | flex-direction: column;
23 | justify-content: center;
24 | position: absolute;
25 | /*
26 | left: 0;
27 | right: 0;
28 | bottom: 30%;
29 | transform: translate(0, 30%);
30 | */
31 | left: 50%;
32 | top: 50%;
33 | transform: translate(-50%, -50%);
34 | font-size: 14px;
35 | color: #696969;
36 | background: #F8F8F8;
37 | box-shadow: rgba(0, 0, 0, 0.2) 4px 4px 0 0;
38 | }
39 |
40 | .content{
41 | white-space: pre;
42 | }
43 |
44 | .dialog{
45 | position: relative;
46 | padding: 1em;
47 | /*flex: 100 100 50%;*/
48 | }
49 |
50 | .heading{
51 | font-size: 1.2em;
52 | }
53 |
54 | *+.content{
55 | margin-top: 0.5em;
56 | }
57 |
58 | *+.select{
59 | margin-top: 0.5em;
60 | }
61 |
62 | *+.buttons{
63 | margin-top: 0.5em;
64 | }
65 |
66 | .buttons{
67 | display: flex;
68 | justify-content: flex-end;
69 | }
70 |
71 | .buttons button+button{
72 | margin-left: 0.5em;
73 | }
74 |
75 | .buttons button{
76 | border: none;
77 | padding: 0.2em 0.5em;
78 | color: inherit;
79 | background-color: rgba(0, 0, 0, 0.2);
80 | }
81 |
82 | .buttons button:hover{
83 | color: inherit;
84 | background-color: rgba(0, 0, 0, 0.1);
85 | }
86 |
87 | .buttons button:active{
88 | color: inherit;
89 | background-color: rgba(0, 0, 0, 0.4);
90 | }
91 |
92 | .success{
93 | color: white;
94 | background: #346A3B;
95 | }
96 |
97 | .info{
98 | /*
99 | color: white;
100 | background: #35496A;
101 | */
102 | background: white;
103 | }
104 |
105 | .warning{
106 | color: white;
107 | background: #D69600;
108 | }
109 |
110 | .error{
111 | color: white;
112 | background: #980707;
113 | }
--------------------------------------------------------------------------------
/experimental/musicboxeditor/dist/styles.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: app-font;
3 | src: url(./assets/fonts/opensans.woff2);
4 | }
5 |
6 | html {
7 | font-family: app-font;
8 | speak: none;
9 | font-style: normal;
10 | font-weight: normal;
11 | font-variant: normal;
12 | text-transform: none;
13 | -webkit-font-smoothing: antialiased;
14 | -moz-osx-font-smoothing: grayscale;
15 | font-size: 12px;
16 | }
17 |
18 | h1 {
19 | margin: 0;
20 | font-size: 1.5em;
21 | }
22 |
23 | h2 {
24 | margin: 0;
25 | font-size: 1.25em;
26 | }
27 |
28 | h3 {
29 | margin: 0;
30 | font-size: 1.15em;
31 | }
32 |
33 | h4 {
34 | margin: 0;
35 | font-size: 1.1em;
36 | }
37 |
38 | h5 {
39 | margin: 0;
40 | font-size: 1.05em;
41 | }
42 |
43 | p {
44 | margin: 0;
45 | }
46 |
47 | *:focus {
48 | outline-offset: 1px;
49 | outline: 2px solid #6495ED;
50 | }
51 |
52 | button {
53 | font-family: app-font;
54 | border: none;
55 | padding: 0.2em 0.5em;
56 | background-color: rgba(0, 0, 0, 0.15);
57 | }
58 |
59 | button:hover {
60 | background-color: rgba(0, 0, 0, 0.10);
61 | }
62 |
63 | button:active {
64 | background-color: rgba(0, 0, 0, 0.2);
65 | }
66 |
67 | input[type=text],
68 | input[type=number],
69 | input[type=time],
70 | input[type=date],
71 | input[type=datetime],
72 | input[type=datetime-local],
73 | input[type=week],
74 | input[type=month],
75 | select {
76 | padding: 0.2em 0.2em;
77 | margin: 0;
78 | align-items: center;
79 | border: 1px solid #bbbbbb;
80 | box-shadow: inset 0px 0px 3px 0px rgba(0, 0, 0, 0.20);
81 | }
82 |
83 |
84 | /*hint component hack - can be removed when we get viewencaptulation.none working*/
85 | hint-renderer{
86 | font-family: app-font;
87 | pointer-events: none;
88 | position: absolute;
89 | top: 0;
90 | left: 0;
91 | width: 0;
92 | height: 0;
93 | overflow: hidden;
94 | }
95 |
96 | hint-renderer .box {
97 | position: fixed;
98 | padding: 0.5em;
99 | max-width: 20em;
100 | color: #444444;
101 | background-color: white;
102 | border: 1px solid #e0e0e0;
103 | box-shadow: rgba(0, 0, 0, 0.2) 4px 4px 0 0;
104 | }
105 |
106 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/styles.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: app-font;
3 | src: url(./assets/fonts/opensans.woff2);
4 | }
5 |
6 | html {
7 | font-family: app-font;
8 | speak: none;
9 | font-style: normal;
10 | font-weight: normal;
11 | font-variant: normal;
12 | text-transform: none;
13 | -webkit-font-smoothing: antialiased;
14 | -moz-osx-font-smoothing: grayscale;
15 | font-size: 12px;
16 | }
17 |
18 | h1 {
19 | margin: 0;
20 | font-size: 1.5em;
21 | }
22 |
23 | h2 {
24 | margin: 0;
25 | font-size: 1.25em;
26 | }
27 |
28 | h3 {
29 | margin: 0;
30 | font-size: 1.15em;
31 | }
32 |
33 | h4 {
34 | margin: 0;
35 | font-size: 1.1em;
36 | }
37 |
38 | h5 {
39 | margin: 0;
40 | font-size: 1.05em;
41 | }
42 |
43 | p {
44 | margin: 0;
45 | }
46 |
47 | *:focus {
48 | outline-offset: 1px;
49 | outline: 2px solid #6495ED;
50 | }
51 |
52 | button {
53 | font-family: app-font;
54 | border: none;
55 | padding: 0.2em 0.5em;
56 | background-color: rgba(0, 0, 0, 0.15);
57 | }
58 |
59 | button:hover {
60 | background-color: rgba(0, 0, 0, 0.10);
61 | }
62 |
63 | button:active {
64 | background-color: rgba(0, 0, 0, 0.2);
65 | }
66 |
67 | input[type=text],
68 | input[type=number],
69 | input[type=time],
70 | input[type=date],
71 | input[type=datetime],
72 | input[type=datetime-local],
73 | input[type=week],
74 | input[type=month],
75 | select {
76 | padding: 0.2em 0.2em;
77 | margin: 0;
78 | align-items: center;
79 | border: 1px solid #bbbbbb;
80 | box-shadow: inset 0px 0px 3px 0px rgba(0, 0, 0, 0.20);
81 | }
82 |
83 |
84 | /*hint component hack - can be removed when we get viewencaptulation.none working*/
85 | hint-renderer{
86 | font-family: app-font;
87 | pointer-events: none;
88 | position: absolute;
89 | top: 0;
90 | left: 0;
91 | width: 0;
92 | height: 0;
93 | overflow: hidden;
94 | }
95 |
96 | hint-renderer .box {
97 | position: fixed;
98 | padding: 0.5em;
99 | max-width: 20em;
100 | color: #444444;
101 | background-color: white;
102 | border: 1px solid #e0e0e0;
103 | box-shadow: rgba(0, 0, 0, 0.2) 4px 4px 0 0;
104 | }
105 |
106 |
--------------------------------------------------------------------------------
/experimental/whitebird/FileSaver.min.js:
--------------------------------------------------------------------------------
1 | /*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
2 | var saveAs=saveAs||function(e){"use strict";if(typeof e==="undefined"||typeof navigator!=="undefined"&&/MSIE [1-9]\./.test(navigator.userAgent)){return}var t=e.document,n=function(){return e.URL||e.webkitURL||e},r=t.createElementNS("http://www.w3.org/1999/xhtml","a"),o="download"in r,a=function(e){var t=new MouseEvent("click");e.dispatchEvent(t)},i=/constructor/i.test(e.HTMLElement)||e.safari,f=/CriOS\/[\d]+/.test(navigator.userAgent),u=function(t){(e.setImmediate||e.setTimeout)(function(){throw t},0)},s="application/octet-stream",d=1e3*40,c=function(e){var t=function(){if(typeof e==="string"){n().revokeObjectURL(e)}else{e.remove()}};setTimeout(t,d)},l=function(e,t,n){t=[].concat(t);var r=t.length;while(r--){var o=e["on"+t[r]];if(typeof o==="function"){try{o.call(e,n||e)}catch(a){u(a)}}}},p=function(e){if(/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)){return new Blob([String.fromCharCode(65279),e],{type:e.type})}return e},v=function(t,u,d){if(!d){t=p(t)}var v=this,w=t.type,m=w===s,y,h=function(){l(v,"writestart progress write writeend".split(" "))},S=function(){if((f||m&&i)&&e.FileReader){var r=new FileReader;r.onloadend=function(){var t=f?r.result:r.result.replace(/^data:[^;]*;/,"data:attachment/file;");var n=e.open(t,"_blank");if(!n)e.location.href=t;t=undefined;v.readyState=v.DONE;h()};r.readAsDataURL(t);v.readyState=v.INIT;return}if(!y){y=n().createObjectURL(t)}if(m){e.location.href=y}else{var o=e.open(y,"_blank");if(!o){e.location.href=y}}v.readyState=v.DONE;h();c(y)};v.readyState=v.INIT;if(o){y=n().createObjectURL(t);setTimeout(function(){r.href=y;r.download=u;a(r);h();c(y);v.readyState=v.DONE});return}S()},w=v.prototype,m=function(e,t,n){return new v(e,t||e.name||"download",n)};if(typeof navigator!=="undefined"&&navigator.msSaveOrOpenBlob){return function(e,t,n){t=t||e.name||"download";if(!n){e=p(e)}return navigator.msSaveOrOpenBlob(e,t)}}w.abort=function(){};w.readyState=w.INIT=0;w.WRITING=1;w.DONE=2;w.error=w.onwritestart=w.onprogress=w.onwrite=w.onabort=w.onerror=w.onwriteend=null;return m}(typeof self!=="undefined"&&self||typeof window!=="undefined"&&window||this.content);if(typeof module!=="undefined"&&module.exports){module.exports.saveAs=saveAs}else if(typeof define!=="undefined"&&define!==null&&define.amd!==null){define("FileSaver.js",function(){return saveAs})}
3 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/contextMenu/contextMenu.component.ts:
--------------------------------------------------------------------------------
1 | //our root app component
2 | import { Component, ViewChild, ElementRef, OnInit, Input, HostBinding } from '@angular/core';
3 | import { ContextMenuService } from "./contextMenu.service";
4 | import { IContextMenuOptions } from "./contextMenu.interface";
5 |
6 | @Component({
7 | selector: 'context-menu',
8 | templateUrl: './contextMenu.component.html',
9 | styleUrls: ['./contextMenu.component.css']
10 | })
11 | export class ContextMenuComponent implements OnInit {
12 |
13 | @Input() options: IContextMenuOptions;
14 |
15 | @HostBinding('style.left.px') x = 0;
16 | @HostBinding('style.top.px') y = 0;
17 | @HostBinding('style.width.px') width = 0;
18 | @HostBinding('style.height.px') height = 0;
19 |
20 | private openElement: IContextMenuOptions;
21 |
22 | constructor(private elementRef: ElementRef, private contextMenuService: ContextMenuService) {
23 | }
24 |
25 | ngOnInit(): void {
26 | if(!this.options){
27 | return;
28 | }
29 |
30 | this.x = this.options.x ? this.options.x : 0;
31 | this.y = this.options.y ? this.options.y : 0;
32 | this.width = this.options.width ? this.options.width : 50;
33 | this.height = this.options.height ? this.options.height : 50;
34 | }
35 |
36 | //template
37 | showSubMenu(menu: IContextMenuOptions): boolean {
38 | if(this.openElement === menu && this.openElement.menu && this.openElement.menu.length > 0){
39 | return true;
40 | }
41 |
42 | return false;
43 | }
44 |
45 | showSubMenuIcon(menu: IContextMenuOptions): boolean{
46 | if(!menu || !menu.menu || menu.menu.length <= 0){
47 | return false;
48 | }
49 |
50 | return true;
51 | }
52 |
53 | getIconClass(menu: IContextMenuOptions): string{
54 | if(menu.icon){
55 | return menu.icon;
56 | }
57 | return '';
58 | }
59 |
60 | onBlurMenu() {
61 | this.contextMenuService.closeContextMenu();
62 | }
63 |
64 | onClickMenu(menu: IContextMenuOptions) {
65 | if (!menu || !menu.callback) {
66 | return;
67 | }
68 |
69 | menu.callback();
70 |
71 | this.contextMenuService.closeContextMenu();
72 | }
73 |
74 | onMouseEnterElement(menu: IContextMenuOptions){
75 | this.openElement = menu;
76 | }
77 |
78 | }
--------------------------------------------------------------------------------
/experimental/musicboxeditor/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "musicboxeditor",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "postinstall": "typings install",
7 | "build": "webpack --progress",
8 | "build:dev": "webpack --progress --watch",
9 | "build:prod": "rimraf build && cross-env APP_ENVIRONMENT=production webpack -p --progress",
10 | "server": "lite-server -c lite-server.config.js",
11 | "server:gzip": "cross-env APP_ENVIRONMENT=gzip lite-server -c lite-server.config.js",
12 | "test:dev": "cross-env APP_ENVIRONMENT=test TEST_ENVIRONMENT=dev ./node_modules/karma/bin/karma start ./karma.config.js",
13 | "test:prod": "cross-env APP_ENVIRONMENT=test ./node_modules/karma/bin/karma start ./karma.config.js"
14 | },
15 | "dependencies": {
16 | "@angular/common": "2.2.3",
17 | "@angular/compiler": "2.2.3",
18 | "@angular/compiler-cli": "2.2.3",
19 | "@angular/core": "2.2.3",
20 | "@angular/forms": "2.2.3",
21 | "@angular/http": "2.2.3",
22 | "@angular/platform-browser": "2.2.3",
23 | "@angular/platform-browser-dynamic": "2.2.3",
24 | "@angular/platform-server": "2.2.3",
25 | "@angular/router": "3.2.3",
26 | "core-js": "2.4.1",
27 | "jszip": "^3.1.3",
28 | "midiconvert": "^0.4.1",
29 | "reflect-metadata": "^0.1.10",
30 | "rxjs": "5.0.0-beta.12",
31 | "zone.js": "0.6.26"
32 | },
33 | "devDependencies": {
34 | "@ngtools/webpack": "1.1.9",
35 | "@types/angular": "^1.6.10",
36 | "@types/node": "^7.0.12",
37 | "@types/webpack-env": "^1.13.0",
38 | "angular2-template-loader": "0.6.0",
39 | "compression": "^1.6.2",
40 | "copy-webpack-plugin": "^4.0.1",
41 | "cross-env": "3.1.3",
42 | "enhanced-resolve": "3.0.0",
43 | "extract-text-webpack-plugin": "1.0.1",
44 | "html-webpack-plugin": "2.24.1",
45 | "http-proxy-middleware": "^0.17.4",
46 | "jasmine-core": "^2.5.2",
47 | "karma": "^1.5.0",
48 | "karma-chrome-launcher": "^2.0.0",
49 | "karma-jasmine": "^1.1.0",
50 | "karma-sourcemap-loader": "^0.3.7",
51 | "karma-spec-reporter": "0.0.30",
52 | "karma-webpack": "^2.0.3",
53 | "lite-server": "^2.3.0",
54 | "raw-loader": "0.5.1",
55 | "rimraf": "2.5.4",
56 | "ts-loader": "1.3.0",
57 | "typescript": "2.0.10",
58 | "typings": "2.0.0",
59 | "webpack": "2.1.0-beta.27",
60 | "webpack-dev-server": "2.1.0-beta.12",
61 | "webpack-visualizer-plugin": "^0.1.11"
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/dev/UML/Application model.xml:
--------------------------------------------------------------------------------
1 | 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
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/dialog/dialog.component.ts:
--------------------------------------------------------------------------------
1 | //our root app component
2 | import { Component, ViewChild, ElementRef } from '@angular/core';
3 | import { DialogService } from './dialog.service';
4 | import { IDialog, IDialogButton } from './dialog.interface';
5 |
6 | @Component({
7 | selector: 'dialog-renderer',
8 | templateUrl: './dialog.component.html',
9 | styleUrls: ['./dialog.component.css']
10 | })
11 | export class DialogComponent {
12 |
13 | @ViewChild('buttons') public buttons: ElementRef;
14 | dialog: IDialog;
15 |
16 | constructor(private dialogService: DialogService) {
17 | this.dialogService.setRenderer(this);
18 | this.dialog;
19 | }
20 |
21 | public openDialog(dialog: IDialog): void{
22 | if(!dialog){
23 | return;
24 | }
25 |
26 |
27 | this.dialog = dialog;
28 |
29 | console.log(this);
30 | setTimeout(()=>{
31 | var buttonElements = this.buttons.nativeElement.getElementsByTagName('button');
32 | if(buttonElements && buttonElements.length > 0){
33 | buttonElements[0].focus();
34 | }
35 | }, 0)
36 | }
37 |
38 | public closeDialog(): void{
39 | this.dialog = null;
40 | }
41 |
42 |
43 | onBlurDialog(event: any){
44 | console.log(event);
45 | }
46 |
47 | public getDialogClass(): string{
48 | return this.dialog.level;
49 | }
50 |
51 | public showDialog(): boolean{
52 | if(!this.dialog){
53 | return false;
54 | }
55 | return true;
56 | }
57 |
58 | public showHeading(): boolean{
59 | if(!this.dialog || !this.dialog.heading){
60 | return false;
61 | }
62 | return true;
63 | }
64 |
65 | public showContent(): boolean{
66 | if(!this.dialog || !this.dialog.content){
67 | return false;
68 | }
69 | return true;
70 | }
71 |
72 | public showSelect(): boolean{
73 | if(!this.dialog || !this.dialog.select){
74 | return false;
75 | }
76 | return true;
77 | }
78 |
79 | public showButtons(): boolean{
80 | if(!this.dialog || !this.dialog.buttons){
81 | return false;
82 | }
83 |
84 | if(this.dialog.buttons.length <= 0){
85 | return false;
86 | }
87 |
88 | return true;
89 | }
90 |
91 | public onClickButton(button: IDialogButton): void{
92 | if(!button){
93 | return;
94 | }
95 |
96 | if(!button.disableClose){
97 | this.closeDialog();
98 | }
99 |
100 | if(button.callback){
101 | button.callback();
102 | }
103 | }
104 | }
--------------------------------------------------------------------------------
/experimental/sandbox/templates/strip_event_orientations:
--------------------------------------------------------------------------------
1 | 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
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/subMenu/subMenu.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, Input } from '@angular/core';
2 |
3 | import { ISubMenuComponentOptions, ISubMenuButton} from './subMenu.interface';
4 |
5 | @Component({
6 | selector: 'sub-menu',
7 | templateUrl: './subMenu.component.html',
8 | styleUrls: ['./subMenu.component.css']
9 | })
10 | export class SubMenuComponent implements OnInit {
11 | constructor() { }
12 |
13 | @Input() options: ISubMenuComponentOptions;
14 |
15 | ngOnInit(): void {
16 | if(this.options){
17 | this.options.component = this;
18 | if(this.options.onInit){
19 | this.options.onInit();
20 | }
21 | }
22 | }
23 |
24 | selectButton(indexOrButton: number | ISubMenuButton){
25 | let button: ISubMenuButton;
26 |
27 | if(typeof indexOrButton === 'number'){
28 | if(indexOrButton < 0 || indexOrButton >= this.options.buttons.length){
29 | return;
30 | }
31 | button = this.options.buttons[indexOrButton];
32 | }else{
33 | button = indexOrButton;
34 | }
35 |
36 | if(!button){ return; }
37 |
38 | if(button.callback){
39 | button.callback();
40 | }
41 | }
42 |
43 | onClickButton(button: ISubMenuButton) {
44 | this.selectButton(button);
45 | }
46 |
47 | getBackgroundClass(){
48 | return {
49 | disableBackground: this.options.disableBackground ? true : false
50 | };
51 | }
52 |
53 | getIconClass(button: ISubMenuButton){
54 | var iconClass = {};
55 | if(button.iconClass){
56 | iconClass[button.iconClass] = true;
57 | }
58 | if(this.options.iconSize){
59 | iconClass[this.options.iconSize] = true;
60 | }
61 | return iconClass;
62 | }
63 |
64 |
65 | showSubMenu():boolean {
66 | if(!this.options){
67 | return false;
68 | }
69 | return true;
70 | }
71 |
72 | showText(button: ISubMenuButton): boolean{
73 | if(this.options.disableText || !button || !button.text){
74 | return false;
75 | }
76 | return true;
77 | }
78 |
79 | showIcon(button: ISubMenuButton): boolean{
80 | if(this.options.disableIcons || !button || !button.iconClass){
81 | return false;
82 | }
83 | return true;
84 | }
85 |
86 | getHint(button: ISubMenuButton): string{
87 | if(this.options.disableText){
88 | return button.text;
89 | }
90 | return '';
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/directive/dragAndDrop/dragAndDrop.directive.ts:
--------------------------------------------------------------------------------
1 | import { Directive, ElementRef, HostListener, Input, HostBinding } from '@angular/core';
2 | import { DragAndDropService } from "./dragAndDrop.service";
3 |
4 | @Directive({
5 | selector: '[dragstart]'
6 | })
7 | export class DragStartDirective {
8 |
9 | @Input('dragstart') private dragStartCallback: (DragEvent, DragAndDropService)=>void;
10 |
11 | @HostBinding('draggable') hostDraggable = "true";
12 |
13 | constructor(private dragAndDropService: DragAndDropService) {}
14 |
15 | @HostListener('dragstart', ['$event'])
16 | onDragStart(event: DragEvent) {
17 | event.dataTransfer.effectAllowed = 'all';
18 |
19 | this.dragAndDropService.clear();
20 | this.dragStartCallback(event, this.dragAndDropService);
21 |
22 | }
23 | }
24 |
25 | @Directive({
26 | selector: '[drag-success][drag-error]'
27 | })
28 | export class DragSuccessDirective {
29 |
30 | @Input('drag-success') private dragSuccessCallback: (DragEvent, DragAndDropService)=>void;
31 | @Input('drag-error') private dragErrorCallback: (DragEvent, DragAndDropService)=>void;
32 |
33 | constructor(private dragAndDropService: DragAndDropService) {}
34 |
35 | @HostListener('dragend', ['$event'])
36 | onDropSuccess(event: DragEvent) {
37 |
38 | if(this.dragAndDropService.getSuccess() === true){
39 | this.dragSuccessCallback(event, this.dragAndDropService);
40 | }else{
41 | this.dragErrorCallback(event, this.dragAndDropService);
42 | }
43 |
44 | this.dragAndDropService.clear();
45 |
46 | }
47 | }
48 |
49 | @Directive({
50 | selector: '[dragover]'
51 | })
52 | export class DragOverDirective {
53 |
54 | @Input('dragover') private dragoverCallback: (DragEvent, DragAndDropService)=>boolean;
55 |
56 | constructor(private dragAndDropService: DragAndDropService) {}
57 |
58 | @HostListener('dragover', ['$event'])
59 | onDropOver(event: DragEvent) {
60 | event.dataTransfer.dropEffect = 'move';
61 |
62 | if(this.dragoverCallback){
63 | this.dragoverCallback(event, this.dragAndDropService);
64 | }
65 |
66 | event.preventDefault();
67 | }
68 | }
69 |
70 | @Directive({
71 | selector: '[drop]'
72 | })
73 | export class DropDirective {
74 |
75 | @Input('drop') private dropCallback: (DragEvent, DragAndDropService)=>boolean;
76 |
77 | constructor(private dragAndDropService: DragAndDropService) {}
78 |
79 | @HostListener('drop', ['$event'])
80 | onDrop(event: DragEvent) {
81 |
82 | if(this.dropCallback(event, this.dragAndDropService)){
83 | this.dragAndDropService.setSuccess(true);
84 | }
85 |
86 | event.preventDefault();
87 | }
88 | }
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/assets/icons/source/interactor-font-icons/demo-files/demo.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 0;
3 | margin: 0;
4 | font-family: sans-serif;
5 | font-size: 1em;
6 | line-height: 1.5;
7 | color: #555;
8 | background: #fff;
9 | }
10 | h1 {
11 | font-size: 1.5em;
12 | font-weight: normal;
13 | }
14 | small {
15 | font-size: .66666667em;
16 | }
17 | a {
18 | color: #e74c3c;
19 | text-decoration: none;
20 | }
21 | a:hover, a:focus {
22 | box-shadow: 0 1px #e74c3c;
23 | }
24 | .bshadow0, input {
25 | box-shadow: inset 0 -2px #e7e7e7;
26 | }
27 | input:hover {
28 | box-shadow: inset 0 -2px #ccc;
29 | }
30 | input, fieldset {
31 | font-family: sans-serif;
32 | font-size: 1em;
33 | margin: 0;
34 | padding: 0;
35 | border: 0;
36 | }
37 | input {
38 | color: inherit;
39 | line-height: 1.5;
40 | height: 1.5em;
41 | padding: .25em 0;
42 | }
43 | input:focus {
44 | outline: none;
45 | box-shadow: inset 0 -2px #449fdb;
46 | }
47 | .glyph {
48 | font-size: 16px;
49 | width: 15em;
50 | padding-bottom: 1em;
51 | margin-right: 4em;
52 | margin-bottom: 1em;
53 | float: left;
54 | overflow: hidden;
55 | }
56 | .liga {
57 | width: 80%;
58 | width: calc(100% - 2.5em);
59 | }
60 | .talign-right {
61 | text-align: right;
62 | }
63 | .talign-center {
64 | text-align: center;
65 | }
66 | .bgc1 {
67 | background: #f1f1f1;
68 | }
69 | .fgc1 {
70 | color: #999;
71 | }
72 | .fgc0 {
73 | color: #000;
74 | }
75 | p {
76 | margin-top: 1em;
77 | margin-bottom: 1em;
78 | }
79 | .mvm {
80 | margin-top: .75em;
81 | margin-bottom: .75em;
82 | }
83 | .mtn {
84 | margin-top: 0;
85 | }
86 | .mtl, .mal {
87 | margin-top: 1.5em;
88 | }
89 | .mbl, .mal {
90 | margin-bottom: 1.5em;
91 | }
92 | .mal, .mhl {
93 | margin-left: 1.5em;
94 | margin-right: 1.5em;
95 | }
96 | .mhmm {
97 | margin-left: 1em;
98 | margin-right: 1em;
99 | }
100 | .mls {
101 | margin-left: .25em;
102 | }
103 | .ptl {
104 | padding-top: 1.5em;
105 | }
106 | .pbs, .pvs {
107 | padding-bottom: .25em;
108 | }
109 | .pvs, .pts {
110 | padding-top: .25em;
111 | }
112 | .unit {
113 | float: left;
114 | }
115 | .unitRight {
116 | float: right;
117 | }
118 | .size1of2 {
119 | width: 50%;
120 | }
121 | .size1of1 {
122 | width: 100%;
123 | }
124 | .clearfix:before, .clearfix:after {
125 | content: " ";
126 | display: table;
127 | }
128 | .clearfix:after {
129 | clear: both;
130 | }
131 | .hidden-true {
132 | display: none;
133 | }
134 | .textbox0 {
135 | width: 3em;
136 | background: #f1f1f1;
137 | padding: .25em .5em;
138 | line-height: 1.5;
139 | height: 1.5em;
140 | }
141 | #testDrive {
142 | display: block;
143 | padding-top: 24px;
144 | line-height: 1.5;
145 | }
146 | .fs0 {
147 | font-size: 16px;
148 | }
149 | .fs1 {
150 | font-size: 32px;
151 | }
152 |
153 |
--------------------------------------------------------------------------------
/inc/processing.js:
--------------------------------------------------------------------------------
1 | function processData(midiData) {
2 | console.log(midiData);
3 |
4 | var musicBox = generateMusicBox({letter: "c", octave: 5}, generateScale("c", "major", "ionian"), 20);
5 |
6 | var events = [];
7 |
8 | for(var i=0; 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
--------------------------------------------------------------------------------
/inc/scaleandmusicbox.js:
--------------------------------------------------------------------------------
1 | var noteLetters = ["c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "b"]
2 | var notes = [];
3 |
4 | for (var num = 0; num < 128; num++) {
5 | notes.push({letter: noteLetters[num%12], octave: Math.floor(num/12)});
6 | }
7 |
8 | var makerjs = require('makerjs');
9 |
10 | var scaleModes = {
11 | major: {
12 | ionian: [2,2,1,2,2,2],
13 | dorian: [2,1,2,2,2,1],
14 | phyrigian: [1,2,2,2,1,2],
15 | lydian: [2,2,2,1,2,2],
16 | mixolydian: [2,2,1,2,2,1],
17 | aeolian: [2,1,2,2,1,2],
18 | locrian: [1,2,2,1,2,2]
19 | },
20 | harmonic_minor: {
21 | harmminor: [2,1,2,2,1,3],
22 | locriansharpsix:[1,2,2,1,3,1],
23 | ionianaug: [2,2,1,3,1,2],
24 | romanian: [2,1,3,1,2,1],
25 | phrygiandom: [1,3,1,2,1,2],
26 | lydiansharptwo: [3,1,2,1,2,2],
27 | ultralocrian: [1,2,1,2,2,1]
28 | },
29 | melodic_minor: {
30 | jazz_minor: [2,1,2,2,2,2],
31 | dorianflatnine: [1,2,2,2,2,1],
32 | lydianaug: [2,2,2,2,1,2],
33 | lydiandom: [2,2,2,1,2,1],
34 | mixolydianflatsix: [2,2,1,2,1,2],
35 | semilocrian: [2,1,2,1,2,2],
36 | superlocrian: [1,2,1,2,2,2]
37 | }
38 | }
39 |
40 | function generateScale(root, scale, mode) {
41 | var result = [];
42 | var gaps = scaleModes[scale][mode];
43 | if (gaps === undefined) return undefined;
44 | result.push(root);
45 | var lastNoteNum = noteLetters.indexOf(root);
46 | for (var i=0; i
11 | }
12 |
13 | interface JSZipConstructor {
14 | new (): JSZipInterface
15 | }
16 |
17 |
18 | const module: JSZipConstructor
19 | export = module
20 | }
21 |
22 | //jasmine subset
23 |
24 | //declare var require: any;
25 | declare function describe(description: string, specDefinitions: () => void): void;
26 | declare function fdescribe(description: string, specDefinitions: () => void): void;
27 | declare function xdescribe(description: string, specDefinitions: () => void): void;
28 |
29 | declare function it(expectation: string, assertion?: (done: DoneFn) => void, timeout?: number): void;
30 | declare function fit(expectation: string, assertion?: (done: DoneFn) => void, timeout?: number): void;
31 | declare function xit(expectation: string, assertion?: (done: DoneFn) => void, timeout?: number): void;
32 |
33 | /** If you call the function pending anywhere in the spec body, no matter the expectations, the spec will be marked pending. */
34 | declare function pending(reason?: string): void;
35 |
36 | declare function beforeEach(action: (done: DoneFn) => void, timeout?: number): void;
37 | declare function afterEach(action: (done: DoneFn) => void, timeout?: number): void;
38 |
39 | declare function beforeAll(action: (done: DoneFn) => void, timeout?: number): void;
40 | declare function afterAll(action: (done: DoneFn) => void, timeout?: number): void;
41 |
42 | declare function expect(spy: Function): Matchers;
43 | declare function expect(actual: T): Matchers;
44 |
45 | declare function fail(e?: any): void;
46 | /** Action method that should be called when the async work is complete */
47 | interface DoneFn extends Function {
48 | (): void;
49 |
50 | /** fails the spec and indicates that it has completed. If the message is an Error, Error.message is used */
51 | fail: (message?: Error|string) => void;
52 | }
53 |
54 | interface Matchers {
55 |
56 | new (env: any, actual: T, spec: any, isNot?: boolean): any;
57 |
58 | env: any;
59 | actual: T;
60 | spec: any;
61 | isNot?: boolean;
62 | message(): any;
63 |
64 | toBe(expected: any, expectationFailOutput?: any): boolean;
65 | toEqual(expected: any, expectationFailOutput?: any): boolean;
66 | toMatch(expected: string | RegExp, expectationFailOutput?: any): boolean;
67 | toBeDefined(expectationFailOutput?: any): boolean;
68 | toBeUndefined(expectationFailOutput?: any): boolean;
69 | toBeNull(expectationFailOutput?: any): boolean;
70 | toBeNaN(): boolean;
71 | toBeTruthy(expectationFailOutput?: any): boolean;
72 | toBeFalsy(expectationFailOutput?: any): boolean;
73 | toHaveBeenCalled(): boolean;
74 | toHaveBeenCalledWith(...params: any[]): boolean;
75 | toHaveBeenCalledTimes(expected: number): boolean;
76 | toContain(expected: any, expectationFailOutput?: any): boolean;
77 | toBeLessThan(expected: number, expectationFailOutput?: any): boolean;
78 | toBeLessThanOrEqual(expected: number, expectationFailOutput?: any): boolean;
79 | toBeGreaterThan(expected: number, expectationFailOutput?: any): boolean;
80 | toBeGreaterThanOrEqual(expected: number, expectationFailOutput?: any): boolean;
81 | toBeCloseTo(expected: number, precision?: any, expectationFailOutput?: any): boolean;
82 | toThrow(expected?: any): boolean;
83 | toThrowError(message?: string | RegExp): boolean;
84 | toThrowError(expected?: new (...args: any[]) => Error, message?: string | RegExp): boolean;
85 | not: Matchers;
86 |
87 | Any: any;
88 | }
--------------------------------------------------------------------------------
/inc/drawing.js:
--------------------------------------------------------------------------------
1 | var fileTexts = {
2 | "svg": null,
3 | "dxf": null,
4 | "txt": null
5 | };
6 |
7 | function downloadFile(fileName, fileText) {
8 | var dataType = "text/plain";
9 | console.log(fileName);
10 | if(fileName.includes("svg")) dataText="image/svg";
11 |
12 | var element = document.createElement('a');
13 | element.setAttribute('href', "data:" + dataType + ";charset=utf-8," + encodeURIComponent(fileText));
14 | element.setAttribute('download', fileName);
15 |
16 | element.style.display = 'none';
17 | document.body.appendChild(element);
18 |
19 | element.click();
20 |
21 | document.body.removeChild(element);
22 | }
23 |
24 | function generateModel(midiData, holeWidth, holeHeight, horizontalMargin, verticalMargin, stripHeight, units) {
25 | var notesAgainstTime = processData(midiData);
26 | var punchHoles = [];
27 | var origins = "";
28 | var model = { models: {}};
29 | var biggestY = 0;
30 | var biggestX = 0;
31 | var rectX = 0;
32 | var rectY = 0;
33 |
34 |
35 | if (document.getElementById("hole-shape").value == "Square"){
36 | for (var i=0; i biggestX) {
45 | biggestX = rectangle.origin[0];
46 | }
47 |
48 | if (rectangle.origin[1] > biggestY) {
49 | biggestY = rectangle.origin[1];
50 | }
51 | }
52 | } else {
53 | for (var i=0; i biggestX) {
62 | biggestX = oval.origin[0];
63 | }
64 |
65 | if (oval.origin[1] > biggestY) {
66 | biggestY = oval.origin[1];
67 | }
68 | }
69 | }
70 | rectX = (biggestX + horizontalMargin + holeWidth);
71 | rectY = stripHeight;
72 |
73 | var rectangle = new makerjs.models.Rectangle(rectX, rectY);
74 | rectangle.units = units;
75 |
76 | punchHoles.push(rectangle);
77 | model.models = punchHoles;
78 | return [model, origins];
79 | }
80 |
81 | function prepareFiles(midiData) {
82 | var units = makerjs.unitType.Millimeter;
83 | if (document.getElementById("units").value == "Inches"){
84 | units = makerjs.unitType.Inch;
85 | }
86 | var holeWidth = parseFloat(document.getElementById("hole-width").value);
87 | var holeHeight = parseFloat(document.getElementById("hole-height").value);
88 | var hMargin = parseFloat(document.getElementById("horizontal-margins").value);
89 | var vMargin = parseFloat(document.getElementById("vertical-margins").value);
90 | var stripHeight = parseFloat(document.getElementById("strip-height").value);
91 |
92 | var returnArray = generateModel(midiData, holeWidth, holeHeight, hMargin, vMargin, stripHeight, units);
93 | var model = returnArray[0];
94 | var origins = returnArray[1];
95 |
96 | fileTexts["svg"] = makerjs.exporter.toSVG(model, {units: units, useSvgPathOnly: false, svgAttrs: {xmlns: "http://www.w3.org/2000/svg"}});
97 | fileTexts["dxf"] = makerjs.exporter.toDXF(model, {units : units});
98 | fileTexts["txt"] = origins;
99 | document.getElementById("preview-box").innerHTML = fileTexts["svg"];
100 | }
101 |
--------------------------------------------------------------------------------
/experimental/sandbox/templates/layout_anchors_2.xml:
--------------------------------------------------------------------------------
1 | 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
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/contextMenu/contextMenu.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@angular/core';
2 | import { ContextMenuRendererComponent } from "./contextMenuRenderer.component";
3 | import { IContextMenuOptions } from "./contextMenu.interface";
4 |
5 | @Injectable()
6 | export class ContextMenuService {
7 | renderer: ContextMenuRendererComponent;
8 |
9 | elementHeight: number;
10 | halfPadding: number;
11 | padding: number;
12 |
13 | setRenderer(contextMenuComponent: ContextMenuRendererComponent) {
14 | if (contextMenuComponent) {
15 | this.renderer = contextMenuComponent;
16 | }
17 | }
18 |
19 | public openContextMenu(options: IContextMenuOptions) {
20 | if (!this.renderer) {
21 | return;
22 | }
23 | this.updatePositions(options);
24 | this.renderer.open(options);
25 | }
26 |
27 | public closeContextMenu() {
28 | this.renderer.close();
29 | }
30 |
31 | updatePositions(menu: IContextMenuOptions){
32 | var id = this.renderer.getEncapsulationId();
33 |
34 | var contextMenuElement = this.createElement('div', id, 'context-menu');
35 | var element = this.createElement('div', id, 'element');
36 | var text = this.createElement('div', id, null);
37 | text.innerText = 'Text'
38 |
39 | element.appendChild(text);
40 | contextMenuElement.appendChild(element);
41 |
42 | var appElement = document.getElementsByTagName('app')[0];
43 |
44 | appElement.appendChild(contextMenuElement);
45 |
46 | var a = contextMenuElement.getBoundingClientRect();
47 | var b = element.getBoundingClientRect();
48 |
49 | appElement.removeChild(contextMenuElement);
50 |
51 | var width = a.width;
52 | this.elementHeight = b.height;
53 | this.padding = (a.height - b.height);
54 | this.halfPadding = this.padding / 2;
55 |
56 | menu.width = menu.width ? menu.width : 100;
57 | menu.x = menu.x ? menu.x : 0;
58 | menu.y = menu.y ? menu.y : 0;
59 |
60 | if(menu.menu){
61 | menu.height = menu.menu.length * this.elementHeight + this.padding;
62 | }
63 |
64 | if(menu.height > window.innerHeight){
65 | menu.height = window.innerHeight;
66 | }
67 |
68 | if(menu.x + menu.width > window.innerWidth){
69 | menu.x = window.innerWidth - menu.width;
70 | }
71 |
72 | if(menu.y + menu.height > window.innerHeight){
73 | menu.y = window.innerHeight - menu.height;
74 | }
75 |
76 | if(menu.menu){
77 | for(var i = 0; i < menu.menu.length; i++){
78 | var m = menu.menu[i];
79 | if(!m){ continue; }
80 | this.calculateMenuSize(m, menu);
81 | }
82 | }
83 | }
84 |
85 | createElement(type: string, attribute: string, className: string){
86 | var tmp = document.createElement(type);
87 | tmp.setAttribute(attribute, '');
88 | if(className){
89 | tmp.classList.add(className);
90 | }
91 | return tmp;
92 | }
93 |
94 | calculateMenuSize(menu: IContextMenuOptions, parent: IContextMenuOptions){
95 | if(!menu || !parent){ return; }
96 |
97 | menu.width = parent.width;
98 | menu.x = parent.x + menu.width - 1;
99 |
100 | var index = parent.menu.indexOf(menu);
101 | if(index > -1){
102 | menu.y = parent.y + this.elementHeight * index;
103 | }
104 |
105 | if(menu.menu){
106 | menu.height = menu.menu.length * this.elementHeight;
107 | }else{
108 | menu.height = 0;
109 | }
110 |
111 | if(menu.height > window.innerHeight){
112 | menu.height = window.innerHeight;
113 | }
114 |
115 | //if outside of screen
116 | if(menu.x + menu.width > window.innerWidth){
117 | menu.x = parent.x - menu.width + 1;
118 | }
119 |
120 | if(menu.y + menu.height > window.innerHeight){
121 | menu.y = window.innerHeight - menu.height;
122 | }
123 |
124 | if(menu.menu){
125 | for(var i = 0; i < menu.menu.length; i++){
126 | var m = menu.menu[i];
127 | if(!m){ continue; }
128 | this.calculateMenuSize(m, menu);
129 | }
130 | }
131 | }
132 | }
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/tabMenu/tabMenu.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 | import { TabMenuModule, TabMenuComponent, ITabMenuComponentOptions } from "./tabMenu.module";
3 |
4 | describe('TabMenuComponent', () => {
5 |
6 | let fixture: ComponentFixture;
7 | let comp: TabMenuComponent;
8 | let el: HTMLElement;
9 |
10 | let options: ITabMenuComponentOptions;
11 |
12 | beforeEach(() => {
13 | TestBed.configureTestingModule({
14 | imports: [TabMenuModule]
15 | });
16 |
17 | fixture = TestBed.createComponent(TabMenuComponent);
18 | comp = fixture.componentInstance;
19 | el = fixture.debugElement.nativeElement;
20 |
21 | options = {
22 | onInit: () => { },
23 | buttons: [{
24 | text: 'First',
25 | callback: () => {
26 |
27 | return true;
28 | }
29 | }, {
30 | text: 'Secound',
31 | callback: () => {
32 | return false;
33 | }
34 | }]
35 | };
36 | });
37 |
38 | it('should create the TabMenuComponent', () => {
39 | expect(comp).toBeTruthy();
40 | });
41 |
42 | it('should have options.component', () => {
43 |
44 | expect(options.component).toBeFalsy();
45 |
46 | comp.options = options;
47 | fixture.detectChanges();
48 |
49 | expect(options.component).toBeTruthy();
50 | });
51 |
52 | it('should call onInit when options is defined', () => {
53 |
54 | let onInitCalled = false;
55 | options.buttons = [];
56 | options.onInit = () => {
57 | onInitCalled = true;
58 | }
59 |
60 | expect(onInitCalled).toBeFalsy();
61 |
62 | comp.options = options;
63 | fixture.detectChanges();
64 |
65 | expect(onInitCalled).toBeTruthy();
66 | });
67 |
68 | it('should be visible when options is defined', () => {
69 | options.buttons = [];
70 |
71 | var submenu = el.getElementsByClassName('tab-menu');
72 | var buttons = el.getElementsByClassName('button');
73 |
74 | expect(comp.showTabMenu()).toBeFalsy();
75 | expect(submenu.length).toBe(0);
76 | expect(buttons.length).toBe(0);
77 |
78 | comp.options = options;
79 | fixture.detectChanges();
80 |
81 | submenu = el.getElementsByClassName('tab-menu');
82 | buttons = el.getElementsByClassName('button');
83 |
84 | expect(comp.showTabMenu()).toBeTruthy();
85 | expect(submenu.length).toBe(1);
86 | expect(buttons.length).toBe(0);
87 | });
88 |
89 | it('should have buttons with text when options.buttons is defined', () => {
90 |
91 | var buttons = el.getElementsByClassName('button');
92 | expect(buttons.length).toBe(0);
93 |
94 | comp.options = options;
95 | fixture.detectChanges();
96 |
97 | buttons = el.getElementsByClassName('button');
98 | expect(buttons.length).toBe(2);
99 |
100 | expect(buttons[0].getElementsByTagName('h2')[0].textContent).toBe('First');
101 | expect(buttons[1].getElementsByTagName('h2')[0].textContent).toBe('Secound');
102 |
103 | });
104 |
105 | it('should call button callback when button is clicked', () => {
106 | let buttonCallback = false;
107 | options.buttons[0].callback = () => {
108 | buttonCallback = true;
109 | return true;
110 | }
111 |
112 | expect(buttonCallback).toBeFalsy();
113 |
114 | comp.options = options;
115 | fixture.detectChanges();
116 |
117 | expect(buttonCallback).toBeFalsy();
118 |
119 | let buttons = el.getElementsByTagName('button');
120 | buttons[0].click();
121 |
122 | expect(buttonCallback).toBeTruthy();
123 | });
124 |
125 | it('should set selected when button is selecable', () => {
126 | expect(comp.selected).toBeFalsy();
127 |
128 | comp.options = options;
129 | fixture.detectChanges();
130 |
131 | expect(comp.selected).toBeFalsy();
132 |
133 | comp.selectButton(0);
134 |
135 | expect(comp.selected.text).toBe('First');
136 | });
137 |
138 | it('should set selected when button is clicked', () => {
139 | expect(comp.selected).toBeFalsy();
140 |
141 | comp.options = options;
142 | fixture.detectChanges();
143 |
144 | expect(comp.selected).toBeFalsy();
145 |
146 | el.getElementsByTagName('button')[0].click();
147 |
148 | expect(comp.selected.text).toBe('First');
149 | });
150 |
151 | it('should not set selected when button is not selectable', () => {
152 | expect(comp.selected).toBeFalsy();
153 |
154 | comp.options = options;
155 | fixture.detectChanges();
156 |
157 | expect(comp.selected).toBeFalsy();
158 |
159 | comp.selectButton(1);
160 |
161 | expect(comp.selected).toBeFalsy();
162 | });
163 |
164 | });
--------------------------------------------------------------------------------
/experimental/sandbox/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Render Test
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
77 |
78 |
79 |
80 |
81 |
1: Load Track
82 |
83 |
84 |
85 |
2: Specify Device
86 |
94 |
95 |
96 |
3: Render View (click buttons)
97 |
99 |
101 |
102 |
103 |
104 |
105 |
Click on events
106 |
109 |
110 |
111 |
112 |
113 |
114 |
119 |
124 |
125 |
126 |
127 |
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/ui/subMenu/subMenu.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 | import { SubMenuModule, SubMenuComponent, ISubMenuComponentOptions } from './submenu.module';
3 | import { HintModule } from "../hint/hint.module";
4 |
5 | describe('SubMenuComponent', () => {
6 |
7 | let fixture: ComponentFixture;
8 | let comp: SubMenuComponent;
9 | let el: HTMLElement;
10 |
11 | let options: ISubMenuComponentOptions;
12 |
13 | beforeEach(() => {
14 | TestBed.configureTestingModule({
15 | imports: [ SubMenuModule, HintModule.forRoot() ]
16 | });
17 |
18 | fixture = TestBed.createComponent(SubMenuComponent);
19 | comp = fixture.componentInstance;
20 | el = fixture.debugElement.nativeElement;
21 |
22 | options = {
23 | onInit: ()=>{},
24 | buttons: [{
25 | text: 'First',
26 | iconClass: 'int-icon-first',
27 | callback: ()=>{
28 | this.logger.logDebug('MainMenu clicked: Save');
29 | }
30 | }, {
31 | text: 'Secound',
32 | iconClass: 'int-icon-secound',
33 | callback: ()=>{
34 | this.logger.logDebug('MainMenu clicked: Exit');
35 | }
36 | }]
37 | };
38 | });
39 |
40 | it('should create the SubMenuComponent', () => {
41 | expect(comp).toBeTruthy();
42 | });
43 |
44 | it('should have options.component', () => {
45 |
46 | expect(options.component).toBeFalsy();
47 |
48 | comp.options = options;
49 | fixture.detectChanges();
50 |
51 | expect(options.component).toBeTruthy();
52 | });
53 |
54 | it('should call onInit when options is defined', () => {
55 |
56 | let onInitCalled = false;
57 | options.buttons = [];
58 | options.onInit = ()=>{
59 | onInitCalled = true;
60 | }
61 |
62 | expect(onInitCalled).toBeFalsy();
63 |
64 | comp.options = options;
65 | fixture.detectChanges();
66 |
67 | expect(onInitCalled).toBeTruthy();
68 | });
69 |
70 | it('should be visible when options is defined', () => {
71 | options.buttons = [];
72 |
73 | var submenu = el.getElementsByClassName('sub-menu');
74 | var buttons = el.getElementsByClassName('button');
75 |
76 | expect(comp.showSubMenu()).toBeFalsy();
77 | expect(submenu.length).toBe(0);
78 | expect(buttons.length).toBe(0);
79 |
80 | comp.options = options;
81 | fixture.detectChanges();
82 |
83 | submenu = el.getElementsByClassName('sub-menu');
84 | buttons = el.getElementsByClassName('button');
85 |
86 | expect(comp.showSubMenu()).toBeTruthy();
87 | expect(submenu.length).toBe(1);
88 | expect(buttons.length).toBe(0);
89 | });
90 |
91 | it('should have buttons with text when options.buttons is defined', () => {
92 |
93 | var buttons = el.getElementsByClassName('button');
94 | expect(buttons.length).toBe(0);
95 |
96 | comp.options = options;
97 | fixture.detectChanges();
98 |
99 | buttons = el.getElementsByClassName('button');
100 | expect(buttons.length).toBe(2);
101 |
102 | expect(buttons[0].getElementsByTagName('h4')[0].textContent).toBe('First');
103 | expect(buttons[1].getElementsByTagName('h4')[0].textContent).toBe('Secound');
104 |
105 | });
106 |
107 | it('should have buttons with icons when options.buttons is defined', () => {
108 |
109 | var buttons = el.getElementsByClassName('button');
110 | expect(buttons.length).toBe(0);
111 |
112 | comp.options = options;
113 | fixture.detectChanges();
114 |
115 | buttons = el.getElementsByClassName('button');
116 | expect(buttons.length).toBe(2);
117 |
118 | expect(buttons[0].getElementsByTagName('i')[0].classList[0]).toBe('int-icon-first');
119 | expect(buttons[1].getElementsByTagName('i')[0].classList[0]).toBe('int-icon-secound');
120 |
121 | });
122 |
123 | it('should have buttons with no icons when options.disableIcons = true', () => {
124 | options.disableIcons = true;
125 | comp.options = options;
126 | fixture.detectChanges();
127 |
128 | var buttons = el.getElementsByClassName('button');
129 | expect(buttons.length).toBe(2);
130 |
131 | expect(el.getElementsByTagName('i').length).toBe(0);
132 | });
133 |
134 | it('should have buttons with no text when options.disableText = true', () => {
135 | options.disableText = true;
136 | comp.options = options;
137 | fixture.detectChanges();
138 |
139 | var buttons = el.getElementsByClassName('button');
140 | expect(buttons.length).toBe(2);
141 |
142 | expect(el.getElementsByTagName('h4').length).toBe(0);
143 | });
144 |
145 | it('should call button callback when button is clicked', () => {
146 | let buttonCallback = false;
147 | options.buttons[0].callback = ()=>{
148 | buttonCallback = true;
149 | }
150 |
151 | expect(buttonCallback).toBeFalsy();
152 |
153 | comp.options = options;
154 | fixture.detectChanges();
155 |
156 | expect(buttonCallback).toBeFalsy();
157 |
158 | let buttons = el.getElementsByTagName('button');
159 | buttons[0].click();
160 |
161 | expect(buttonCallback).toBeTruthy();
162 | });
163 | });
--------------------------------------------------------------------------------
/inc/user-interface.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function () {
2 |
3 | var fields = [
4 | { name: 'units', type: 'select', id: 'units' },
5 | { name: 'workpieceWidth', type: 'text', id: 'workpiece-width' },
6 | { name: 'workpieceHeight', type: 'text', id: 'workpiece-height' },
7 | { name: 'stripHeight', type: 'text', id: 'strip-height' },
8 | { name: 'scale', type: 'select', id: 'scale' },
9 | { name: 'scaleType', type: 'select', id: 'scale-type' },
10 |
11 | { name: 'startingEdge', type: 'select', id: 'starting-edge' },
12 | { name: 'jointEdge', type: 'select', id: 'joint-edge' },
13 | { name: 'endingEdge', type: 'select', id: 'ending-edge' },
14 | { name: 'amountOfPins', type: 'text', id: 'amount-of-pins' },
15 |
16 | { name: 'holeShape', type: 'select', id: 'hole-shape' },
17 | { name: 'holeWidth', type: 'text', id: 'hole-width' },
18 | { name: 'holeHeight', type: 'text', id: 'hole-height' },
19 | { name: 'horizontalMargins', type: 'text', id: 'horizontal-margins' },
20 | { name: 'verticalMargins', type: 'text', id: 'vertical-margins' },
21 |
22 | { name: 'exportFormat', type: 'select', id: 'export-format' },
23 | { name: 'lineColor', type: 'text', id: 'line-color' }
24 | ];
25 |
26 | $("#units").change(function () {
27 | if ($("#units option:selected").text() == "Inches") {
28 | $('.unit-suffix').text('in');
29 | } else {
30 | $('.unit-suffix').text('mm');
31 | }
32 |
33 | });
34 |
35 | $("#file-picker-midi").change(function () {
36 | var fileName = $(this).val();
37 | $("#midi-file").val(fileName.substring(fileName.lastIndexOf("\\") + 1, fileName.length));
38 | });
39 |
40 | $("#line-color").change(function () {
41 | var lineColor = $(this).val().toUpperCase();
42 | $("#color-suffix").text(lineColor);
43 | });
44 |
45 | $("#import-settings").click(function () {
46 | if (confirm('Are you sure you want to overwrite your current configuration?')) {
47 | $("#file-picker-import-settings").trigger('click');
48 | }
49 | });
50 |
51 | $("#file-picker-import-settings").change(function () {
52 | var file = $('#file-picker-import-settings')[0].files[0];
53 | importSettings(file);
54 | });
55 |
56 | $("#export-settings").click(function () {
57 | var settings = { };
58 | fields.forEach(function (field) {
59 | settings[field.name] = $('#' + field.id).val();
60 | });
61 |
62 | console.log(settings);
63 |
64 | json_export = JSON.stringify(settings);
65 | console.log(settings);
66 | console.log(json_export);
67 |
68 | var element = document.createElement('a');
69 | element.setAttribute('href', "data:application/json;charset=utf-8," + encodeURIComponent(json_export));
70 | element.setAttribute('download', 'settings.json');
71 |
72 | element.style.display = 'none';
73 | document.body.appendChild(element);
74 |
75 | element.click();
76 |
77 | document.body.removeChild(element);
78 |
79 | });
80 |
81 | //MIDIParser.addListener(document.getElementById('file-picker-midi'), function (data) { prepareFiles(data) });
82 | //console.log("listener added");
83 |
84 | $("#show-preview").click(function () {
85 | if (! validateForm()) {
86 | return;
87 | }
88 | var file = $('#file-picker-midi')[0].files[0];
89 | if (loadMidiFile(file)) {
90 | $("#download-btn").prop('disabled', false)
91 | }
92 | });
93 |
94 | $("#download-btn").click(function () {
95 | var value = document.getElementById('export-format').options[document.getElementById('export-format').selectedIndex].value;
96 | downloadFile('data.' + value, fileTexts[value]);
97 | });
98 |
99 | function importSettings (file) {
100 | if (!file) {
101 | console.log("No settings file selected")
102 | return false;
103 | }
104 | console.log('Attempting to load settings from ' + file.name);
105 | var reader = new FileReader();
106 | reader.readAsText(file);
107 | reader.onload = function (e) {
108 | var settings = JSON.parse(e.target.result);
109 | console.log(settings);
110 |
111 | fields.forEach(function (field) {
112 | if (settings[field.name]) {
113 | if (field.type === 'text') {
114 | $('#' + field.id).val(settings[field.name]);
115 | }
116 | else if (field.type === 'select') {
117 | $('#' + field.id).val(settings[field.name]).change();
118 | }
119 | else {
120 | console.log('Invalid field type: ' + field.type);
121 | }
122 | }
123 | });
124 | };
125 | }
126 |
127 | function loadMidiFile(file) {
128 | if (!file) {
129 | console.log("No Midi file selected")
130 | return false;
131 | }
132 | console.log('Uploading file detected in INPUT ELEMENT, processing data..');
133 | var reader = new FileReader();
134 | reader.readAsArrayBuffer(file);
135 | reader.onload = function (e) {
136 | console.log(e.target.result);
137 | prepareFiles(MIDIParser.Uint8(new Uint8Array(e.target.result)));
138 | };
139 | return true;
140 | }
141 |
142 | function validateForm() {
143 | // For now, simply verify the user has selected a MIDI file
144 | // Will add min/max, defaults, required/optional once those attributes are identified by the team
145 |
146 | var file = $('#file-picker-midi')[0].files[0];
147 | if (!file) {
148 | alert('Please select a valid MIDI file.')
149 | return;
150 | }
151 |
152 | return true;
153 | }
154 | });
--------------------------------------------------------------------------------
/experimental/sandbox/templates/layout_anchors:
--------------------------------------------------------------------------------
1 | 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
--------------------------------------------------------------------------------
/experimental/musicboxeditor/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 |
10 |
91 |
92 |
93 |
96 |
97 |
145 |
146 |
147 |
148 |
149 |
150 |
151 | >
152 |
153 |
--------------------------------------------------------------------------------
/experimental/sandbox/styles/device_concept.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: Arial, sans-serif;
3 | }
4 |
5 | #container {
6 | position: relative;
7 | width: 1200px;
8 | }
9 |
10 | #device {
11 | position: relative;
12 | float: left;
13 | width: 610px;
14 | min-height: 600px;
15 |
16 | }
17 |
18 | #info {
19 | position: relative;
20 | width: 400px;
21 | height: 600px;
22 | float: left;
23 | margin-left: 20px;
24 | }
25 |
26 | #info-text {
27 | width: 500px;
28 | height: 800px;
29 | }
30 |
31 | #device-controls {
32 | position: relative;
33 | border: 1px solid darkgray;
34 | padding-bottom: 10px;
35 | }
36 |
37 | #device-header {
38 | position: relative;
39 | height: 50px;
40 | border: 1px solid darkgray;
41 | border-radius: 10px;
42 | width: 580px;
43 | margin-top: 10px;
44 | margin-left: 10px;
45 | padding-top: 10px;
46 | font-size: 12px;
47 | padding-bottom: 50px;
48 | }
49 |
50 | #device-id-label {
51 | position: absolute;
52 | top: 10px;
53 | left: 200px;
54 | width: 50px;
55 | }
56 |
57 | #device-id-label input {
58 | width: 50px;
59 | }
60 |
61 | #device-deviceName-label {
62 | position: absolute;
63 | top: 10px;
64 | left: 10px;
65 | width: 100px;
66 | }
67 |
68 | #device-description-label {
69 | position: absolute;
70 | top: 55px;
71 | left: 10px;
72 | width: 450px;
73 | }
74 |
75 | #device-description-label input {
76 | width: 450px;
77 | }
78 |
79 | #device-select-label {
80 | position: absolute;
81 | top: 10px;
82 | left: 300px;
83 | width: 160px;
84 | }
85 |
86 | #device-select-label select {
87 | margin-top: 2px;
88 | width: 160px;
89 | }
90 |
91 | #device-channels-header {
92 | position: relative;
93 | height: 20px;
94 | margin-left: 5px;
95 | font-size: 14px;
96 | padding-bottom: 5px;
97 | }
98 |
99 | #device-channels-header p {
100 | margin: 0;
101 | padding: 0;
102 | }
103 |
104 | #device-channels {
105 | position: relative;
106 | border: 1px solid darkgray;
107 | border-radius: 10px;
108 | width: 590px;
109 | margin-top: 10px;
110 | margin-left: 10px;
111 | padding-top: 10px;
112 | font-size: 12px;
113 | padding-bottom: 10px;
114 | }
115 |
116 | #channel-columns {
117 | position: relative;
118 | padding-left: 10px;
119 | width: 520px;
120 | height: 20px;
121 | }
122 |
123 | .device-channel {
124 | width: 590px;
125 | height: 20px;
126 | padding-left: 5px;
127 | padding-bottom: 5px;
128 | padding-top: 0;
129 |
130 | }
131 |
132 | #channels-footer {
133 | margin-top: 20px;
134 | padding-top: 10px;
135 | height: 60px;
136 | padding-left: 5px;
137 | border-top: 1px solid darkgray;
138 | }
139 |
140 | #channel-add {
141 | margin-bottom: 5px;
142 | }
143 |
144 | .channel-noteNumber, .channel-name, .channel-description, .channel-offset, .channel-height, .channel-shape {
145 | margin-top: 0;
146 | margin-bottom: 0;
147 | display: inline-block;
148 | }
149 |
150 | .channel-noteNumber {
151 | width: 80px;
152 | }
153 |
154 | .channel-name {
155 | width: 100px;
156 | }
157 |
158 | .channel-description {
159 | width: 200px;
160 | }
161 |
162 | .channel-offset {
163 | width: 50px;
164 | }
165 |
166 | .channel-height {
167 | width: 50px;
168 | }
169 |
170 | .channel-shape {
171 | width: 50px;
172 | }
173 |
174 | .channel-delete {
175 | font-size: 10px;
176 | line-height: 10px;
177 | padding: 0;
178 | width: 22px;
179 | height: 20px;
180 |
181 | }
182 |
183 | .channel-shape-select {
184 | width: 50px;
185 | }
186 |
187 | .channel-move-btns {
188 | position: relative;
189 | display: inline-block;
190 | margin: 0;
191 | margin-left: 2px;
192 | width: 22px;
193 | height: 20px;
194 |
195 | }
196 |
197 | .channel-up, .channel-down {
198 | font-size: 10px;
199 | line-height: 10px;
200 | margin: 0;
201 | padding: 0;
202 | height: 12px;
203 | }
204 |
205 | .channel-up {
206 | position: absolute;
207 | top: 2px;
208 | left: 0;
209 | width: 22px;
210 |
211 | }
212 |
213 | .channel-down {
214 | position: absolute;
215 | top: 13px;
216 | left: 0;
217 | width: 22px;
218 |
219 | }
220 |
221 | #device-dimensions {
222 | position: relative;
223 | border: 1px solid darkgray;
224 | border-radius: 10px;
225 | width: 580px;
226 | margin-top: 10px;
227 | margin-left: 10px;
228 | padding-top: 10px;
229 | font-size: 12px;
230 | padding-bottom: 10px;
231 | }
232 |
233 | .margin-label {
234 | width: 50px;
235 | }
236 |
237 | .margin-label input {
238 | width: 50px;
239 | }
240 |
241 | #strip-preview {
242 | position: relative;
243 | padding: 3px;
244 | width: 520px;
245 | height: 255px;
246 | margin-left: 20px;
247 | margin-bottom: 15px;
248 |
249 | }
250 |
251 | #strip-rect {
252 | position: absolute;
253 | top: 30px;
254 | left: 70px;
255 | border: 1px solid black;
256 | width: 400px;
257 | height: 200px;
258 | }
259 |
260 | #device-topPadding-label {
261 | position: absolute;
262 | top: 5px;
263 | left: 140px;
264 | width: 200px;
265 | height: 50px;
266 | }
267 |
268 | #device-rightPadding-label {
269 | position: absolute;
270 | top: 100px;
271 | left: 480px;
272 | width: 60px;
273 | height: 50px;
274 | }
275 |
276 | #device-bottomPadding-label {
277 | position: absolute;
278 | top: 235px;
279 | left: 140px;
280 | width: 200px;
281 | height: 50px;
282 | }
283 |
284 | #device-leftPadding-label {
285 | position: absolute;
286 | top: 100px;
287 | left: 5px;
288 | width: 60px;
289 | height: 50px;
290 | }
291 |
292 | #show-rounded-label {
293 | position: absolute;
294 | top: 2px;
295 | left: 430px;
296 | width: 120px;
297 | height: 20px;
298 | }
299 |
300 | #hole-settings {
301 | position: relative;
302 | width: 580px;
303 | margin-top: 0;
304 | margin-left: 10px;
305 | padding-top: 0;
306 | padding-left: 30px;
307 | }
308 |
309 | #hole-settings label {
310 | display: inline-block;
311 | width: 110px;
312 | margin-bottom: 10px;
313 | margin-left: 10px;
314 | height: 40px;
315 | }
316 |
317 | #hole-settings label input {
318 | width: 80px;
319 | }
320 |
321 | input[readonly] {
322 | background-color: lightgray;
323 | border: 1px solid darkgray;
324 | padding: 2px;
325 | }
326 |
327 | #new-device {
328 | position: relative;
329 | float: left;
330 | margin-left: 20px;
331 | width: 500px;
332 | height: 220px;
333 | }
334 |
335 | #new-device-controls {
336 | position: relative;
337 | border: 1px solid darkgray;
338 | border-radius: 10px;
339 | min-height: 220px;
340 |
341 | }
342 |
343 | #new-device-id-label {
344 | position: absolute;
345 | top: 10px;
346 | left: 10px;
347 | width: 110px;
348 | height: 20px;
349 | }
350 |
351 | #new-device-id {
352 | width: 100px;
353 | }
354 |
355 | #new-device-channel-count-label {
356 | position: absolute;
357 | top: 10px;
358 | left: 150px;
359 | width: 150px;
360 | height: 20px;
361 | }
362 |
363 | #new-device-channel-count {
364 | width: 60px;
365 | }
366 |
367 | #new-device-start-note-label {
368 | position: absolute;
369 | top: 60px;
370 | left: 10px;
371 | width: 100px;
372 | height: 20px;
373 | }
374 |
375 | #new-device-start-note {
376 | width: 60px;
377 | }
378 |
379 | #new-device-key-label {
380 | position: absolute;
381 | top: 110px;
382 | left: 10px;
383 | width: 40px;
384 | height: 20px;
385 | }
386 |
387 | #new-device-key {
388 | width: 60px;
389 | }
390 |
391 | #new-device-scale-label {
392 | position: absolute;
393 | top: 110px;
394 | left: 80px;
395 | width: 40px;
396 | height: 20px;
397 | }
398 |
399 | #new-device-scale {
400 | width: 130px;
401 | }
402 |
403 | #new-device-mode-label {
404 | position: absolute;
405 | top: 110px;
406 | left: 220px;
407 | width: 40px;
408 | height: 20px;
409 | }
410 |
411 | #new-device-mode {
412 | width: 130px;
413 | }
414 |
415 | #new-device-add-btn-label {
416 | position: absolute;
417 | bottom: 10px;
418 | left: 10px;
419 | width: 40px;
420 | height: 20px;
421 | }
422 |
423 |
--------------------------------------------------------------------------------