├── .gitignore ├── README.md ├── app.js ├── build ├── Gruntfile.js ├── installer │ └── installer.js └── package.json ├── client ├── .jshintrc ├── Gruntfile.js ├── app │ ├── index.html │ ├── modules │ │ ├── app.js │ │ ├── commands │ │ │ ├── !module-commands.js │ │ │ ├── commands.html │ │ │ ├── controller-commands.js │ │ │ ├── directive-command-item.js │ │ │ ├── factory-renderer-service.js │ │ │ ├── route-commands.js │ │ │ └── template-command-item.html │ │ └── common │ │ │ ├── !module-commands.js │ │ │ └── services │ │ │ ├── factory-ramda.js │ │ │ ├── factory-socket-service.js │ │ │ └── factory-uuid-service.js │ └── styles │ │ ├── _commands.scss │ │ ├── _typeahead.scss │ │ └── main.scss ├── bower.json └── package.json └── server ├── Gruntfile.js ├── app-cluster.js ├── app.js ├── config.json ├── package.json ├── routes.js ├── setup.js ├── vizmock.js └── websockets ├── index.js └── renderers.js /.gitignore: -------------------------------------------------------------------------------- 1 | build/node_modules 2 | build/server 3 | client/.tmp 4 | client/.sass-cache 5 | client/bower_components 6 | client/node_modules 7 | client/dist 8 | server/node_modules 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vizrt-command-sender 2 | Sending Commands To Vizrt's Viz Engine with Open Source Tools 3 | 4 | Future plans: 5 | 6 | Dropdowns populated by sending COMMAND_INFO to Viz Engine for each property and command on the fly 7 | Drag and drop stack items to re-order 8 | 9 | 10 | # Try it out 11 | 12 | You will need NodeJS installed from https://nodejs.org/ 13 | 14 | Download the dist.zip file from http://www.andyleggett.co.uk/viz/dist.zip 15 | 16 | Unzip into a folder and then run node app from the command line in that folder. You'll see "App listening on 11000". 17 | 18 | Then point a browser at http://localhost:11000 19 | 20 | 21 | # Instructions for development 22 | 23 | You will need NodeJS and Bower installed 24 | 25 | Clone the repo 26 | cd [project folder] 27 | 28 | ## To run in dev: 29 | 30 | In one terminal window: 31 | 32 | cd [client folder] 33 | npm install 34 | bower install 35 | grunt server 36 | 37 | In another: 38 | 39 | cd [server folder] 40 | npm install 41 | grunt 42 | 43 | Open browser and navigate to http://localhost:9000 for dev version 44 | 45 | ## To build (after running in dev mode): 46 | 47 | In one terminal window: 48 | 49 | cd [client folder] 50 | grunt build 51 | 52 | In another: 53 | 54 | cd [build folder] 55 | npm install 56 | grunt 57 | node .server/app 58 | 59 | Open browser and navigate to http://localhost:7000 for built version 60 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | var properties = /\[(.*)[\s\S]*?(?=[\[C])/g; 2 | var propName = /\[(.+)\]/g; 3 | var stripPropName = /[\[\s\]]/g; 4 | var propDesc = /Desc[\s\S]*/g; 5 | var stripPropDesc1 = /Description:/g; 6 | var stripPropDesc2 = /------------/g; 7 | var stripNewLines = /\n/g; 8 | 9 | var log = function(obj){ 10 | console.log(obj); 11 | return obj; 12 | }; 13 | 14 | var projectProp = function(prop){ 15 | 16 | var desc = R.compose(R.head, R.match(propDesc))(prop); 17 | 18 | return { 19 | name: R.compose(R.replace(stripPropName, ''), R.head, R.match(propName))(prop), 20 | description: desc ? R.compose(R.trim, R.replace(stripPropDesc2, ''), R.replace(stripPropDesc1, ''), R.replace(stripNewLines, ''))(desc) : '' 21 | }; 22 | }; 23 | 24 | var parseText = R.compose(log, R.map(projectProp), R.tail, R.match(properties)); 25 | 26 | $.get('raw_commands/MAIN.txt', parseText); -------------------------------------------------------------------------------- /build/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 3 | // configure the tasks 4 | grunt.initConfig({ 5 | 6 | copy: { 7 | main: { 8 | files: [{ 9 | expand: true, 10 | cwd: '../client/dist/', 11 | src: '**/*.*', 12 | dest: 'server/public/' 13 | }, { 14 | expand: true, 15 | cwd: '../server/', 16 | src: 'package.json', 17 | dest: 'server/' 18 | }, { 19 | expand: true, 20 | cwd: '../server/', 21 | src: 'setup.js', 22 | dest: 'server/' 23 | }, { 24 | expand: true, 25 | cwd: '../server/', 26 | src: 'routes.js', 27 | dest: 'server/' 28 | }, { 29 | expand: true, 30 | cwd: '../server/', 31 | src: 'errorhandler.js', 32 | dest: 'server/' 33 | }, { 34 | expand: true, 35 | cwd: '../server/', 36 | src: 'app.js', 37 | dest: 'server/' 38 | }, { 39 | expand: true, 40 | cwd: '../server/', 41 | src: 'app-cluster.js', 42 | dest: 'server/' 43 | }, { 44 | expand: true, 45 | cwd: '../server/', 46 | src: 'config.json', 47 | dest: 'server/' 48 | }, { 49 | expand: true, 50 | cwd: '../server/controllers/', 51 | src: '**/*.js', 52 | dest: 'server/controllers/' 53 | },{ 54 | expand: true, 55 | cwd: '../server/node_modules/', 56 | src: '**/*', 57 | dest: 'server/node_modules/' 58 | }, { 59 | expand: true, 60 | cwd: '../server/websockets/', 61 | src: '**/*.js', 62 | dest: 'server/websockets/' 63 | }] 64 | } 65 | }, 66 | clean: { 67 | dist: { 68 | files: [{ 69 | dot: true, 70 | src: [ 71 | 'server', 72 | ] 73 | }] 74 | } 75 | }, 76 | }); 77 | 78 | grunt.loadNpmTasks('grunt-contrib-copy'); 79 | grunt.loadNpmTasks('grunt-contrib-clean'); 80 | 81 | grunt.registerTask('default', ['clean:dist', 'copy']); 82 | }; 83 | -------------------------------------------------------------------------------- /build/installer/installer.js: -------------------------------------------------------------------------------- 1 | var Service = require('node-windows').Service; 2 | 3 | // Create a new service object 4 | var svc = new Service({ 5 | name:'CommandSender', 6 | description: 'The Viz Command Sender App.', 7 | script: 'C:\\Dev\\CommandSender_Files\\app.js' 8 | }); 9 | 10 | // Listen for the "install" event, which indicates the 11 | // process is available as a service. 12 | svc.on('install',function(){ 13 | svc.start(); 14 | }); 15 | 16 | svc.install(); -------------------------------------------------------------------------------- /build/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BBC_VizRT_Command_Sender_Build", 3 | "version": "0.1.0", 4 | "description": "Build service for VCS", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "" 9 | }, 10 | "repository": "", 11 | "author": "", 12 | "license": "BSD", 13 | "dependencies": {}, 14 | "devDependencies": { 15 | "grunt": "~0.4.2", 16 | "grunt-contrib-clean": "^0.6.0", 17 | "grunt-contrib-copy": "~0.5.x" 18 | }, 19 | "engines": { 20 | "node": "0.10.x", 21 | "npm": "1.2.x" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /client/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "browser": true, 4 | "esnext": true, 5 | "bitwise": true, 6 | "camelcase": true, 7 | "curly": true, 8 | "eqeqeq": true, 9 | "immed": true, 10 | "indent": 2, 11 | "latedef": true, 12 | "newcap": false, 13 | "noarg": true, 14 | "quotmark": "single", 15 | "undef": true, 16 | "unused": true, 17 | "strict": true, 18 | "trailing": true, 19 | "smarttabs": true, 20 | "globals": { 21 | "angular": false, 22 | "$": false, 23 | "app": true 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /client/Gruntfile.js: -------------------------------------------------------------------------------- 1 | // Generated on 2014-12-16 using generator-angular 0.10.0 2 | 'use strict'; 3 | 4 | // # Globbing 5 | // for performance reasons we're only matching one level down: 6 | // 'test/spec/{,*/}*.js' 7 | // use this if you want to recursively match all subfolders: 8 | // 'test/spec/**/*.js' 9 | 10 | module.exports = function(grunt) { 11 | 12 | // Load grunt tasks automatically 13 | require('load-grunt-tasks')(grunt); 14 | 15 | // Time how long tasks take. Can help when optimizing build times 16 | require('time-grunt')(grunt); 17 | 18 | // Configurable paths for the application 19 | var appConfig = { 20 | app: require('./bower.json').appPath || 'app', 21 | dist: 'dist' 22 | }; 23 | 24 | // Define the configuration for all the tasks 25 | grunt.initConfig({ 26 | 27 | // Project settings 28 | yeoman: appConfig, 29 | 30 | // Watches files for changes and runs tasks based on the changed files 31 | watch: { 32 | bower: { 33 | files: ['bower.json'], 34 | tasks: ['wiredep'] 35 | }, 36 | includeSource: { 37 | files: ['<%= yeoman.app %>/index.html'], 38 | tasks: ['includeSource:server'] 39 | }, 40 | js: { 41 | files: ['<%= yeoman.app %>/modules/**/*.js'], 42 | tasks: ['newer:jshint:all', 'includeSource:server'], 43 | options: { 44 | livereload: '<%= connect.options.livereload %>' 45 | } 46 | }, 47 | html: { 48 | files: ['<%= yeoman.app %>/modules/**/*.html'], 49 | tasks: ['copy:views'], 50 | options: { 51 | livereload: '<%= connect.options.livereload %>' 52 | } 53 | }, 54 | templates: { 55 | files: ['<%= yeoman.app %>/templates/{,*/}*.*'], 56 | tasks: ['copy:templates'], 57 | options: { 58 | livereload: '<%= connect.options.livereload %>' 59 | } 60 | }, 61 | jsTest: { 62 | files: ['test/spec/{,*/}*.js'], 63 | tasks: ['newer:jshint:test', 'karma'] 64 | }, 65 | compass: { 66 | files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'], 67 | tasks: ['compass:server', 'autoprefixer'] 68 | }, 69 | gruntfile: { 70 | files: ['Gruntfile.js'] 71 | }, 72 | livereload: { 73 | options: { 74 | livereload: '<%= connect.options.livereload %>' 75 | }, 76 | files: [ 77 | '<%= yeoman.app %>/{,*/}*.html', 78 | '.tmp/styles/{,*/}*.css', 79 | '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}' 80 | ] 81 | } 82 | }, 83 | includeSource: { 84 | options: { 85 | basePath: 'app', 86 | baseUrl: '/', 87 | ordering: 'top-down' 88 | }, 89 | server: { 90 | files: { 91 | '.tmp/index.html': '<%= yeoman.app %>/index.html' 92 | } 93 | }, 94 | dist: { 95 | files: { 96 | '<%= yeoman.dist %>/index.html': '<%= yeoman.app %>/index.html' 97 | } 98 | } 99 | }, 100 | // The actual grunt server settings 101 | connect: { 102 | options: { 103 | port: 9000, 104 | // Change this to '0.0.0.0' to access the server from outside. 105 | hostname: 'localhost', 106 | livereload: 35729 107 | }, 108 | livereload: { 109 | options: { 110 | open: true, 111 | middleware: function(connect) { 112 | return [ 113 | connect.static('.tmp'), 114 | connect().use( 115 | '/bower_components', 116 | connect.static('./bower_components') 117 | ), 118 | connect.static(appConfig.app) 119 | ]; 120 | } 121 | } 122 | }, 123 | test: { 124 | options: { 125 | port: 9001, 126 | middleware: function(connect) { 127 | return [ 128 | connect.static('.tmp'), 129 | connect.static('test'), 130 | connect().use( 131 | '/bower_components', 132 | connect.static('./bower_components') 133 | ), 134 | connect.static(appConfig.app) 135 | ]; 136 | } 137 | } 138 | }, 139 | dist: { 140 | options: { 141 | open: true, 142 | base: '<%= yeoman.dist %>' 143 | } 144 | } 145 | }, 146 | 147 | // Make sure code styles are up to par and there are no obvious mistakes 148 | jshint: { 149 | options: { 150 | jshintrc: '.jshintrc', 151 | reporter: require('jshint-stylish') 152 | }, 153 | all: { 154 | src: [ 155 | 'Gruntfile.js', 156 | '<%= yeoman.app %>/modules/{,*/}*.js' 157 | ] 158 | }, 159 | test: { 160 | options: { 161 | jshintrc: 'test/.jshintrc' 162 | }, 163 | src: ['test/spec/{,*/}*.js'] 164 | } 165 | }, 166 | 167 | // Empties folders to start fresh 168 | clean: { 169 | dist: { 170 | files: [{ 171 | dot: true, 172 | src: [ 173 | '.tmp', 174 | '<%= yeoman.dist %>/{,*/}*', 175 | '!<%= yeoman.dist %>/.git{,*/}*' 176 | ] 177 | }] 178 | }, 179 | server: '.tmp' 180 | }, 181 | 182 | // Add vendor prefixed styles 183 | autoprefixer: { 184 | options: { 185 | browsers: ['last 1 version'] 186 | }, 187 | dist: { 188 | files: [{ 189 | expand: true, 190 | cwd: '.tmp/styles/', 191 | src: '{,*/}*.css', 192 | dest: '.tmp/styles/' 193 | }] 194 | } 195 | }, 196 | 197 | // Automatically inject Bower components into the app 198 | wiredep: { 199 | app: { 200 | src: ['<%= yeoman.app %>/index.html'], 201 | ignorePath: /\.\.\//, 202 | overrides: { 203 | 'socket.io-client': { 204 | main: 'socket.io.js' 205 | }, 206 | 'angular-ng-sortablejs': { 207 | main: [ 208 | 'Sortable.js', 209 | 'ng-sortable.js' 210 | ] 211 | }, 212 | 'bootstrap': { 213 | main: [ 214 | 'dist/css/bootstrap.css', 215 | 'dist/js/bootstrap.js' 216 | ] 217 | }, 218 | 'ngToast': { 219 | main: [ 220 | 'dist/ngToast.js', 221 | 'dist/ngToast.css' 222 | ] 223 | } 224 | } 225 | }, 226 | sass: { 227 | src: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'], 228 | ignorePath: /(\.\.\/){1,2}bower_components\// 229 | } 230 | }, 231 | 232 | // Compiles Sass to CSS and generates necessary files if requested 233 | compass: { 234 | options: { 235 | sassDir: '<%= yeoman.app %>/styles', 236 | cssDir: '.tmp/styles', 237 | generatedImagesDir: '.tmp/images/generated', 238 | imagesDir: '<%= yeoman.app %>/images', 239 | javascriptsDir: '<%= yeoman.app %>/modules', 240 | fontsDir: '<%= yeoman.app %>/fonts', 241 | importPath: './bower_components', 242 | httpImagesPath: '/images', 243 | httpGeneratedImagesPath: '/images/generated', 244 | httpFontsPath: '/fonts', 245 | relativeAssets: false, 246 | assetCacheBuster: false, 247 | raw: 'Sass::Script::Number.precision = 10\n' 248 | }, 249 | dist: { 250 | options: { 251 | generatedImagesDir: '<%= yeoman.dist %>/images/generated' 252 | } 253 | }, 254 | server: { 255 | options: { 256 | debugInfo: true 257 | } 258 | } 259 | }, 260 | 261 | // Renames files for browser caching purposes 262 | filerev: { 263 | dist: { 264 | src: [ 265 | '<%= yeoman.dist %>/scripts/{,*/}*.js', 266 | '<%= yeoman.dist %>/styles/{,*/}*.css', 267 | //'<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}', 268 | // '<%= yeoman.dist %>/fonts/*' 269 | ] 270 | } 271 | }, 272 | 273 | // Reads HTML for usemin blocks to enable smart builds that automatically 274 | // concat, minify and revision files. Creates configurations in memory so 275 | // additional tasks can operate on them 276 | useminPrepare: { 277 | html: '<%= yeoman.dist %>/index.html', 278 | options: { 279 | dest: '<%= yeoman.dist %>', 280 | flow: { 281 | html: { 282 | steps: { 283 | js: ['concat'],//, 'uglifyjs' 284 | css: ['cssmin'] 285 | }, 286 | post: {} 287 | } 288 | } 289 | } 290 | }, 291 | 292 | // Performs rewrites based on filerev and the useminPrepare configuration 293 | usemin: { 294 | html: ['<%= yeoman.dist %>/{,*/}*.html'], 295 | css: ['<%= yeoman.dist %>/styles/{,*/}*.css'], 296 | options: { 297 | assetsDirs: ['<%= yeoman.dist %>', '<%= yeoman.dist %>/images'] 298 | } 299 | }, 300 | 301 | // The following *-min tasks will produce minified files in the dist folder 302 | // By default, your `index.html`'s will take care of 303 | // minification. These next options are pre-configured if you do not wish 304 | // to use the Usemin blocks. 305 | // cssmin: { 306 | // dist: { 307 | // files: { 308 | // '<%= yeoman.dist %>/styles/main.css': [ 309 | // '.tmp/styles/{,*/}*.css' 310 | // ] 311 | // } 312 | // } 313 | // }, 314 | // uglify: { 315 | // dist: { 316 | // files: { 317 | // '<%= yeoman.dist %>/scripts/scripts.js': [ 318 | // '<%= yeoman.dist %>/scripts/scripts.js' 319 | // ] 320 | // } 321 | // } 322 | // }, 323 | // concat: { 324 | // dist: {} 325 | // }, 326 | 327 | imagemin: { 328 | dist: { 329 | files: [{ 330 | expand: true, 331 | cwd: '<%= yeoman.app %>/images', 332 | src: '{,*/}*.{png,jpg,jpeg,gif}', 333 | dest: '<%= yeoman.dist %>/images' 334 | }] 335 | } 336 | }, 337 | 338 | svgmin: { 339 | dist: { 340 | files: [{ 341 | expand: true, 342 | cwd: '<%= yeoman.app %>/images', 343 | src: '{,*/}*.svg', 344 | dest: '<%= yeoman.dist %>/images' 345 | }] 346 | } 347 | }, 348 | 349 | htmlmin: { 350 | dist: { 351 | options: { 352 | collapseWhitespace: true, 353 | conservativeCollapse: true, 354 | collapseBooleanAttributes: true, 355 | removeCommentsFromCDATA: true, 356 | removeOptionalTags: true 357 | }, 358 | files: [{ 359 | expand: true, 360 | cwd: '<%= yeoman.dist %>', 361 | src: ['*.html'], 362 | dest: '<%= yeoman.dist %>' 363 | }, { 364 | expand: true, 365 | cwd: '<%= yeoman.dist %>', 366 | src: ['views/**/*.html'], 367 | dest: '<%= yeoman.dist %>' 368 | }] 369 | } 370 | }, 371 | 372 | // ng-annotate tries to make the code safe for minification automatically 373 | // by using the Angular long form for dependency injection. 374 | ngAnnotate: { 375 | dist: { 376 | files: [{ 377 | expand: true, 378 | cwd: '.tmp/concat/scripts', 379 | src: ['*.js', '!oldieshim.js'], 380 | dest: '.tmp/concat/scripts' 381 | }] 382 | } 383 | }, 384 | // Copies remaining files to places other tasks can use 385 | copy: { 386 | dist: { 387 | files: [{ 388 | expand: true, 389 | dot: true, 390 | cwd: '<%= yeoman.app %>', 391 | dest: '<%= yeoman.dist %>', 392 | src: [ 393 | '*.{ico,png,txt}', 394 | '.htaccess', 395 | '*.html', 396 | 'images/{,*/}*.{webp}', 397 | 'fonts/{,*/}*.*', 398 | 'templates/**/**/*.*' 399 | ] 400 | }, { 401 | expand: true, 402 | cwd: '<%= yeoman.app %>/modules', 403 | dest: '<%= yeoman.dist %>/views', 404 | src: [ 405 | '**/*.html', 406 | ] 407 | }, { 408 | expand: true, 409 | cwd: '.tmp/images', 410 | dest: '<%= yeoman.dist %>/images', 411 | src: ['generated/*'] 412 | }, { 413 | expand: true, 414 | cwd: 'bower_components/components-font-awesome/fonts/', 415 | src: '*', 416 | dest: '<%= yeoman.dist %>/fonts' 417 | }] 418 | }, 419 | styles: { 420 | expand: true, 421 | cwd: '<%= yeoman.app %>/styles', 422 | dest: '.tmp/styles/', 423 | src: '{,*/}*.css' 424 | }, 425 | fonts: { 426 | expand: true, 427 | cwd: '<%= yeoman.app %>/fonts', 428 | dest: '.tmp/fonts/', 429 | src: ['**/*.*'] 430 | }, 431 | fontsawesome: { 432 | expand: true, 433 | cwd: 'bower_components/components-font-awesome/fonts/', 434 | dest: '.tmp/fonts/', 435 | src: ['**/*.*'] 436 | }, 437 | views: { 438 | expand: true, 439 | cwd: '<%= yeoman.app %>/modules', 440 | dest: '.tmp/views/', 441 | src: [ 442 | '**/*.html' 443 | ] 444 | }, 445 | templates: { 446 | expand: true, 447 | cwd: '<%= yeoman.app %>/templates', 448 | dest: '.tmp/templates/', 449 | src: [ 450 | '**/*.*' 451 | ] 452 | } 453 | }, 454 | 455 | // Run some tasks in parallel to speed up the build process 456 | concurrent: { 457 | server: [ 458 | 'compass:server' 459 | ], 460 | test: [ 461 | 'compass' 462 | ], 463 | dist: [ 464 | 'compass:dist', 465 | 'imagemin', 466 | 'svgmin' 467 | ] 468 | }, 469 | 470 | // Test settings 471 | karma: { 472 | unit: { 473 | configFile: 'test/karma.conf.js', 474 | singleRun: true 475 | } 476 | } 477 | }); 478 | 479 | 480 | grunt.registerTask('serve', 'Compile then start a connect web server', function(target) { 481 | if (target === 'dist') { 482 | return grunt.task.run(['build', 'connect:dist:keepalive']); 483 | } 484 | 485 | grunt.task.run([ 486 | 'clean:server', 487 | 'wiredep', 488 | 'copy:views', 489 | 'copy:fonts', 490 | 'copy:fontsawesome', 491 | 'copy:templates', 492 | 'includeSource:server', 493 | 'concurrent:server', 494 | 'autoprefixer', 495 | 'connect:livereload', 496 | 'watch' 497 | ]); 498 | }); 499 | 500 | grunt.registerTask('test', [ 501 | 'clean:server', 502 | 'concurrent:test', 503 | 'autoprefixer', 504 | 'connect:test', 505 | 'karma' 506 | ]); 507 | 508 | grunt.registerTask('build', [ 509 | 'clean:dist', 510 | 'wiredep', 511 | 'includeSource:dist', 512 | 'useminPrepare', 513 | 'concurrent:dist', 514 | 'autoprefixer', 515 | 'concat', 516 | 'copy:dist', 517 | 'cssmin', 518 | 'ngAnnotate', 519 | //'uglify', 520 | 'filerev', 521 | 'usemin', 522 | 'htmlmin' 523 | ]); 524 | 525 | grunt.registerTask('default', [ 526 | 'newer:jshint', 527 | 'test', 528 | 'build' 529 | ]); 530 | }; 531 | -------------------------------------------------------------------------------- /client/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Vizrt Command Sender 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 |
24 |
25 |
26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /client/app/modules/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('commandsender', [ 4 | 'ui.bootstrap', 5 | 'ui.router', 6 | 'btford.socket-io', 7 | 'ng-sortable', 8 | 'ngStorage', 9 | 'ngToast', 10 | 'ngFileSaver', 11 | 'commandsender.common', 12 | 'commandsender.commands' 13 | ]); 14 | 15 | angular.module('commandsender').config(['$stateProvider', '$urlRouterProvider', 16 | function($stateProvider, $urlRouterProvider) { 17 | 18 | $urlRouterProvider 19 | .otherwise('/'); 20 | } 21 | ]); 22 | -------------------------------------------------------------------------------- /client/app/modules/commands/!module-commands.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('commandsender.commands', []); -------------------------------------------------------------------------------- /client/app/modules/commands/commands.html: -------------------------------------------------------------------------------- 1 | 8 | 9 | 17 | 18 |

Vizrt Command Sender

19 |
20 |
21 |
22 |
23 |
24 |

Viz Engine IP

25 |
26 | 27 |
28 |
29 |

Archive

30 |
31 |
32 |
33 | 34 |  |  35 | 36 | 37 |
38 |
39 |
40 |
41 |

Documentation

42 |
43 |
44 |
45 | 46 | 47 |
48 |
49 |
50 |
51 |
52 |
53 |

Command Builder

54 |
55 |
56 |
57 |
58 |
59 | 60 |
61 |
62 |
63 |
64 |
65 |
66 | 68 |
69 |
70 | * 71 |
72 |
73 |
74 |
75 |
76 |
77 | 79 |
80 |
81 | * 82 |
83 |
84 |
85 |
86 |
87 |
88 | 90 |
91 |
92 |   93 |
94 |
95 |
96 |
97 |   99 |
100 |
101 |
102 |
103 | 104 |
105 |
106 |
107 |
108 | 109 | 110 |
111 |
112 | 113 | 114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |

Commands

123 |
124 |
125 | 126 |
127 |
128 |
129 |
130 | 131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |

Console

141 |
142 |
143 | 144 |
145 |
146 |
147 | 148 |
149 |
150 |
151 | -------------------------------------------------------------------------------- /client/app/modules/commands/controller-commands.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('commandsender.commands') 4 | .controller('Commands', ['$scope', 'rendererService', 'uuidService', 'R', '$localStorage', 'FileSaver', 'Blob', 'ngToast', 5 | function($scope, rendererService, uuidService, R, $localStorage, FileSaver, Blob, ngToast) { 6 | 7 | var vm = { 8 | stack: [], 9 | archiveName: '', 10 | documentationName: '', 11 | newCommand: { 12 | commandId: uuidService.newUuid(), 13 | order: 0, 14 | description: '', 15 | properties: ['', '', ''], 16 | command: '', 17 | attributes: '' 18 | }, 19 | ip: '127.0.0.1', 20 | consoleLog: '', 21 | editingCommand: false, 22 | editCommandId: undefined 23 | }; 24 | 25 | vm.sortableConfig = { 26 | group: 'commands', 27 | animation: 500, 28 | onStart: function() {}, 29 | onEnd: function(name) { 30 | vm.reIndex(name.models); 31 | } 32 | }; 33 | 34 | var scrollToBuilder = function() { 35 | $('html, body').animate({ 36 | scrollTop: $('#builder').offset().top 37 | }, 1000); 38 | }; 39 | 40 | var scrollToEditSite = function() { 41 | if (!vm.editCommandId){ 42 | return; 43 | } 44 | 45 | $('html, body').animate({ 46 | scrollTop: $('#command-' + vm.editCommandId).offset().top 47 | }, 1000); 48 | }; 49 | 50 | var updateOrder = R.curry(function(positions, command) { 51 | command.order = R.findIndex(R.propEq('commandId', command.commandId))(positions); 52 | return command; 53 | }); 54 | 55 | vm.reIndex = function(newpositions) { 56 | vm.stack = R.map(updateOrder(newpositions))(vm.stack); 57 | }; 58 | 59 | vm.resetCommand = function() { 60 | vm.newCommand = { 61 | commandId: uuidService.newUuid(), 62 | order: vm.stack.length, 63 | properties: ['', '', ''], 64 | command: '', 65 | attributes: '' 66 | }; 67 | }; 68 | 69 | vm.addToStack = function() { 70 | vm.stack = R.append(vm.newCommand, vm.stack); 71 | vm.resetCommand(); 72 | }; 73 | 74 | vm.editCommand = function(command) { 75 | vm.newCommand = R.clone(command); 76 | vm.editingCommand = true; 77 | vm.editCommandId = command.commandId; 78 | scrollToBuilder(); 79 | }; 80 | 81 | vm.copyCommand = function(command) { 82 | vm.newCommand = R.merge(R.clone(command), { 83 | commandId: uuidService.newUuid() 84 | }); 85 | scrollToBuilder(); 86 | }; 87 | 88 | vm.resetEdit = function() { 89 | scrollToEditSite(); 90 | 91 | vm.resetCommand(); 92 | vm.editingCommand = false; 93 | vm.editCommandId = undefined; 94 | }; 95 | 96 | vm.confirmEdit = function() { 97 | vm.stack = R.compose(R.update(R.__, vm.newCommand, vm.stack), R.findIndex(R.propEq('commandId', vm.newCommand.commandId)))(vm.stack); 98 | 99 | vm.resetEdit(); 100 | }; 101 | 102 | var reindexStackItem = function(item, index) { 103 | return R.merge(item, { 104 | order: index 105 | }); 106 | }; 107 | 108 | vm.removeCommand = function(command) { 109 | vm.stack = R.compose(R.addIndex(R.map)(reindexStackItem), R.reject(R.propEq('commandId', command.commandId)))(vm.stack); 110 | }; 111 | 112 | vm.clearStack = function() { 113 | vm.stack = []; 114 | }; 115 | 116 | vm.clearConsole = function() { 117 | vm.consoleLog = ''; 118 | }; 119 | 120 | vm.saveToLocal = function() { 121 | $localStorage.commands = JSON.stringify(vm.stack); 122 | $localStorage.ip = vm.ip; 123 | }; 124 | 125 | vm.loadFromLocal = function() { 126 | vm.stack = $localStorage.commands ? JSON.parse($localStorage.commands) : []; 127 | vm.ip = $localStorage.ip ? $localStorage.ip : '127.0.0.1'; 128 | }; 129 | 130 | vm.saveArchive = function() { 131 | if (vm.archiveName === '') { 132 | return; 133 | } 134 | 135 | var data = new Blob([JSON.stringify(vm.stack)], { 136 | type: 'application/json;charset=utf-8' 137 | }); 138 | FileSaver.saveAs(data, vm.archiveName + '.json'); 139 | vm.archiveName = ''; 140 | }; 141 | 142 | var projectCommand = function(docs, command) { 143 | var commandText = R.compose(R.join('*'), R.reject(R.isEmpty))(command.properties) + ' ' + command.command + ' ' + command.attributes; 144 | var split = R.compose(R.join(''), R.repeat('-'))(80); 145 | 146 | return docs + '\n\r' + command.description + '\n\r' + commandText + '\n\r' + split + '\n\r'; 147 | }; 148 | 149 | vm.saveDocumentation = function() { 150 | if (vm.documentationName === '') { 151 | return; 152 | } 153 | 154 | var data = new Blob([R.reduce(projectCommand, '')(vm.stack)], { 155 | type: 'application/text;charset=utf-8' 156 | }); 157 | FileSaver.saveAs(data, vm.documentationName + '.txt'); 158 | vm.documentationName = ''; 159 | }; 160 | 161 | var handleFileLoad = function(e) { 162 | var file = e.target.files && e.target.files[0]; 163 | 164 | var reader = new FileReader(); 165 | 166 | reader.onloadend = function(e) { 167 | if (e.target.readyState === FileReader.DONE) { 168 | vm.stack = JSON.parse(e.target.result); 169 | $scope.$apply(); 170 | } 171 | }; 172 | 173 | reader.readAsText(file); 174 | }; 175 | 176 | vm.loadArchive = function() { 177 | $('#load-archive').trigger('click').on('change', handleFileLoad); 178 | }; 179 | 180 | vm.createSendCommand = function(command) { 181 | var send = '1 ' + R.compose(R.join('*'), R.reject(R.isEmpty))(command.properties) + ' ' + command.command + ' ' + command.attributes; 182 | 183 | console.log(send); 184 | 185 | return send; 186 | }; 187 | 188 | vm.sendCommand = function(command) { 189 | if (vm.ip !== '') { 190 | 191 | var sendCommand = vm.createSendCommand(command); 192 | 193 | rendererService.render({ 194 | ip: vm.ip, 195 | command: sendCommand 196 | }).then(function(response) { 197 | ngToast.create({ 198 | className: 'warning', 199 | content: '
Sent command to ' + vm.ip + '
' + response + '
', 200 | timeout: 6000 201 | }); 202 | vm.consoleLog += command.description + '\n' + '-----------------------------------------------' + '\n' + sendCommand + '\n\n' + response + '\n' + '-----------------------------------------------' + '\n\n'; 203 | }); 204 | } 205 | }; 206 | 207 | $scope.$watch('vm.stack', function() { 208 | vm.saveToLocal(); 209 | }); 210 | 211 | $scope.$watch('vm.ip', function() { 212 | vm.saveToLocal(); 213 | }); 214 | 215 | //init 216 | vm.loadFromLocal(); 217 | 218 | /* Slots are hard coded with commands for RENDERER*MAIN_LAYER*SCRIPT INVOKE WhateverCommand for an example. Future versions should send COMMAND_INFO on the fly to populate the dropdowns */ 219 | 220 | vm.slots = [ 221 | [{ 222 | value: '#OBJECTID', 223 | type: 'property', 224 | description: '', 225 | arguments: '' 226 | }, { 227 | value: 'ALL_TABLE', 228 | type: 'property', 229 | description: '', 230 | arguments: '' 231 | }, { 232 | value: 'ANIMATION*KEY*$', 233 | type: 'property', 234 | description: 'access keyframe by name (a director name/path may be specified as $director_path$key_name)', 235 | arguments: '' 236 | }, { 237 | value: 'ARCHIVE', 238 | type: 'property', 239 | description: '', 240 | arguments: '' 241 | }, { 242 | value: 'AUDIO', 243 | type: 'property', 244 | description: '', 245 | arguments: '' 246 | }, { 247 | value: 'AUDIO_CLIP', 248 | type: 'property', 249 | description: '', 250 | arguments: '' 251 | }, { 252 | value: 'AUTOKEYWORD', 253 | type: 'property', 254 | description: '', 255 | arguments: '' 256 | }, { 257 | value: 'BACK_SCENE', 258 | type: 'property', 259 | description: '', 260 | arguments: '' 261 | }, { 262 | value: 'BASE_FONT', 263 | type: 'property', 264 | description: '', 265 | arguments: '' 266 | }, { 267 | value: 'BGL_COMPATIBILITY', 268 | type: 'property', 269 | description: '', 270 | arguments: '' 271 | }, { 272 | value: 'BUILT_IN', 273 | type: 'property', 274 | description: '', 275 | arguments: '' 276 | }, { 277 | value: 'CHAR_STYLE', 278 | type: 'property', 279 | description: '', 280 | arguments: '' 281 | }, { 282 | value: 'CLOCK', 283 | type: 'property', 284 | description: '', 285 | arguments: '' 286 | }, { 287 | value: 'CLOCK%1', 288 | type: 'property', 289 | description: '', 290 | arguments: '' 291 | }, { 292 | value: 'CLOCK*DATA', 293 | type: 'property', 294 | description: '', 295 | arguments: '' 296 | }, { 297 | value: 'CLR', 298 | type: 'property', 299 | description: '', 300 | arguments: '' 301 | }, { 302 | value: 'CMD_RECORD', 303 | type: 'property', 304 | description: '', 305 | arguments: '' 306 | }, { 307 | value: 'COMMANDS_XML', 308 | type: 'property', 309 | description: 'Describes the command interface of this object', 310 | arguments: '' 311 | }, { 312 | value: 'CONFIGURATION', 313 | type: 'property', 314 | description: '', 315 | arguments: '' 316 | }, { 317 | value: 'CONSOLE', 318 | type: 'property', 319 | description: '', 320 | arguments: '' 321 | }, { 322 | value: 'CONTAINER', 323 | type: 'property', 324 | description: '', 325 | arguments: '' 326 | }, { 327 | value: 'DATABASE', 328 | type: 'property', 329 | description: '', 330 | arguments: '' 331 | }, { 332 | value: 'DEBUG_CONTROL', 333 | type: 'property', 334 | description: '', 335 | arguments: '' 336 | }, { 337 | value: 'DEBUG_PUSH', 338 | type: 'property', 339 | description: '', 340 | arguments: '' 341 | }, { 342 | value: 'DEVICE', 343 | type: 'property', 344 | description: '', 345 | arguments: '' 346 | }, { 347 | value: 'DIRECTORY', 348 | type: 'property', 349 | description: '', 350 | arguments: '' 351 | }, { 352 | value: 'EDITOR', 353 | type: 'property', 354 | description: '', 355 | arguments: '' 356 | }, { 357 | value: 'EVS', 358 | type: 'property', 359 | description: '', 360 | arguments: '' 361 | }, { 362 | value: 'FEEDBACK', 363 | type: 'property', 364 | description: '', 365 | arguments: '' 366 | }, { 367 | value: 'FEEDBACKUNICAST', 368 | type: 'property', 369 | description: '', 370 | arguments: '' 371 | }, { 372 | value: 'FONT', 373 | type: 'property', 374 | description: '', 375 | arguments: '' 376 | }, { 377 | value: 'FRONT_SCENE', 378 | type: 'property', 379 | description: '', 380 | arguments: '' 381 | }, { 382 | value: 'FUNCTION', 383 | type: 'property', 384 | description: '', 385 | arguments: '' 386 | }, { 387 | value: 'GEOM', 388 | type: 'property', 389 | description: '', 390 | arguments: '' 391 | }, { 392 | value: 'GLOBAL', 393 | type: 'property', 394 | description: '', 395 | arguments: '' 396 | }, { 397 | value: 'GUI*PID', 398 | type: 'property', 399 | description: '', 400 | arguments: '' 401 | }, { 402 | value: 'HARDWARE*GRAPHICS', 403 | type: 'property', 404 | description: '', 405 | arguments: '' 406 | }, { 407 | value: 'HARDWARE*NUMBER_CLIPIN_CHANNELS', 408 | type: 'property', 409 | description: '', 410 | arguments: '' 411 | }, { 412 | value: 'HARDWARE*NUMBER_CLIPOUT_CHANNELS', 413 | type: 'property', 414 | description: '', 415 | arguments: '' 416 | }, { 417 | value: 'HARDWARE*NUMBER_GFX_CHANNELS', 418 | type: 'property', 419 | description: '', 420 | arguments: '' 421 | }, { 422 | value: 'HARDWARE*NUMBER_GPUS', 423 | type: 'property', 424 | description: '', 425 | arguments: '' 426 | }, { 427 | value: 'HARDWARE*NUMBER_STREAMIN_CHANNELS', 428 | type: 'property', 429 | description: '', 430 | arguments: '' 431 | }, { 432 | value: 'HARDWARE*NUMBER_VIDEO_INPUTS', 433 | type: 'property', 434 | description: '', 435 | arguments: '' 436 | }, { 437 | value: 'HARDWARE*NUMBER_VIDEOIN_CHANNELS', 438 | type: 'property', 439 | description: '', 440 | arguments: '' 441 | }, { 442 | value: 'HARDWARE*SYSTEM', 443 | type: 'property', 444 | description: '', 445 | arguments: '' 446 | }, { 447 | value: 'HARDWARE*VIDEO_OUTPUT', 448 | type: 'property', 449 | description: '', 450 | arguments: '' 451 | }, { 452 | value: 'IMAGE', 453 | type: 'property', 454 | description: '', 455 | arguments: '' 456 | }, { 457 | value: 'LOCATION', 458 | type: 'property', 459 | description: '', 460 | arguments: '' 461 | }, { 462 | value: 'LOG', 463 | type: 'property', 464 | description: '', 465 | arguments: '' 466 | }, { 467 | value: 'MAGIC', 468 | type: 'property', 469 | description: '', 470 | arguments: '' 471 | }, { 472 | value: 'MAIN', 473 | type: 'property', 474 | description: '', 475 | arguments: '' 476 | }, { 477 | value: 'MAIN_SCENE', 478 | type: 'property', 479 | description: '', 480 | arguments: '' 481 | }, { 482 | value: 'MATERIAL', 483 | type: 'property', 484 | description: '', 485 | arguments: '' 486 | }, { 487 | value: 'MATERIAL_ADVANCED', 488 | type: 'property', 489 | description: '', 490 | arguments: '' 491 | }, { 492 | value: 'MEDIA_PREVIEW', 493 | type: 'property', 494 | description: '', 495 | arguments: '' 496 | }, { 497 | value: 'MEMORY', 498 | type: 'property', 499 | description: '', 500 | arguments: '' 501 | }, { 502 | value: 'MODIFIER', 503 | type: 'property', 504 | description: '', 505 | arguments: '' 506 | }, { 507 | value: 'MUX', 508 | type: 'property', 509 | description: '', 510 | arguments: '' 511 | }, { 512 | value: 'OBJECT_ID', 513 | type: 'property', 514 | description: '', 515 | arguments: '' 516 | }, { 517 | value: 'OBJECT_TYPE', 518 | type: 'property', 519 | description: 'What type of object is this', 520 | arguments: '' 521 | }, { 522 | value: 'ONAIR', 523 | type: 'property', 524 | description: '', 525 | arguments: '' 526 | }, { 527 | value: 'PLATFORM', 528 | type: 'property', 529 | description: '', 530 | arguments: '' 531 | }, { 532 | value: 'PLAY', 533 | type: 'property', 534 | description: '', 535 | arguments: '' 536 | }, { 537 | value: 'PLUGIN_MANAGER', 538 | type: 'property', 539 | description: '', 540 | arguments: '' 541 | }, { 542 | value: 'POOLS', 543 | type: 'property', 544 | description: '', 545 | arguments: '' 546 | }, { 547 | value: 'POSTRENDERER', 548 | type: 'property', 549 | description: '', 550 | arguments: '' 551 | }, { 552 | value: 'PROCESS*MEMORY', 553 | type: 'property', 554 | description: '', 555 | arguments: '' 556 | }, { 557 | value: 'REND', 558 | type: 'property', 559 | description: '', 560 | arguments: '' 561 | }, { 562 | value: 'RENDER_TO_DISK', 563 | type: 'property', 564 | description: '', 565 | arguments: '' 566 | }, { 567 | value: 'RENDERER', 568 | type: 'property', 569 | description: '', 570 | arguments: '' 571 | }, { 572 | value: 'SCENE', 573 | type: 'property', 574 | description: '', 575 | arguments: '' 576 | }, { 577 | value: 'SCENE_EDITOR', 578 | type: 'property', 579 | description: '', 580 | arguments: '' 581 | }, { 582 | value: 'SCENE_RENDERER', 583 | type: 'property', 584 | description: '', 585 | arguments: '' 586 | }, { 587 | value: 'SHADER', 588 | type: 'property', 589 | description: '', 590 | arguments: '' 591 | }, { 592 | value: 'STAGE_EVENTS', 593 | type: 'property', 594 | description: 'Access to the stage events.', 595 | arguments: '' 596 | }, { 597 | value: 'SUBSTANCE', 598 | type: 'property', 599 | description: '', 600 | arguments: '' 601 | }, { 602 | value: 'SUGGESTION', 603 | type: 'property', 604 | description: '', 605 | arguments: '' 606 | }, { 607 | value: 'SYSTEM*CHANNEL*%1', 608 | type: 'property', 609 | description: '', 610 | arguments: '' 611 | }, { 612 | value: 'SYSTEM*FLICKER_FILTER_SUPPORTED', 613 | type: 'property', 614 | description: '', 615 | arguments: '' 616 | }, { 617 | value: 'SYSTEM*HARDWARE_TYPE', 618 | type: 'property', 619 | description: '', 620 | arguments: '' 621 | }, { 622 | value: 'SYSTEM*MEMORY', 623 | type: 'property', 624 | description: '', 625 | arguments: '' 626 | }, { 627 | value: 'SYSTEM*MEMORY_ADVANCED', 628 | type: 'property', 629 | description: '', 630 | arguments: '' 631 | }, { 632 | value: 'SYSTEM_GLOBALS*EDITOR_SIZE', 633 | type: 'property', 634 | description: '', 635 | arguments: '' 636 | }, { 637 | value: 'SYSTEM_GLOBALS*OUTPUT_POS', 638 | type: 'property', 639 | description: '', 640 | arguments: '' 641 | }, { 642 | value: 'SYSTEM_GLOBALS*OUTPUT_SIZE', 643 | type: 'property', 644 | description: '', 645 | arguments: '' 646 | }, { 647 | value: 'SYSTEM_GLOBALS*SHOW_MOUSE_CURSOR', 648 | type: 'property', 649 | description: 'Shows/Hides the mouse cursor in the on-air output window.', 650 | arguments: '' 651 | }, { 652 | value: 'TC', 653 | type: 'property', 654 | description: '', 655 | arguments: '' 656 | }, { 657 | value: 'TEST_SIGNALS', 658 | type: 'property', 659 | description: '', 660 | arguments: '' 661 | }, { 662 | value: 'TEXTURE*MEMORY', 663 | type: 'property', 664 | description: '', 665 | arguments: '' 666 | }, { 667 | value: 'TRIO', 668 | type: 'property', 669 | description: '', 670 | arguments: '' 671 | }, { 672 | value: 'UNDOREDO', 673 | type: 'property', 674 | description: '', 675 | arguments: '' 676 | }, { 677 | value: 'VERSIONS', 678 | type: 'property', 679 | description: '', 680 | arguments: '' 681 | }, { 682 | value: 'VIDEO_CLIP', 683 | type: 'property', 684 | description: '', 685 | arguments: '' 686 | }, { 687 | value: 'VIZ2POINTX_MODE', 688 | type: 'property', 689 | description: '', 690 | arguments: '' 691 | }, { 692 | value: 'VIZ_COMMUNICATION', 693 | type: 'property', 694 | description: '', 695 | arguments: '' 696 | }, { 697 | value: 'VIZ_PROGRAMDATA_FOLDER', 698 | type: 'property', 699 | description: 'Folder where VizArtist/Engine stores its machine specific data', 700 | arguments: '' 701 | }, { 702 | value: 'VIZ_PUBLICDOCUMENTS_FOLDER', 703 | type: 'property', 704 | description: '', 705 | arguments: '' 706 | }, { 707 | value: 'VIZONE', 708 | type: 'property', 709 | description: '', 710 | arguments: '' 711 | }, { 712 | value: 'VTS', 713 | type: 'property', 714 | description: '', 715 | arguments: '' 716 | }, { 717 | value: '{UUID}', 718 | type: 'property', 719 | description: '', 720 | arguments: '' 721 | }], 722 | [{ 723 | value: '#OBJECTID', 724 | type: 'property', 725 | description: '', 726 | arguments: '' 727 | }, { 728 | value: 'ANIMATION', 729 | type: 'property', 730 | description: '', 731 | arguments: '' 732 | }, { 733 | value: 'ANIMATION*', 734 | type: 'property', 735 | description: 'Accesses a channel by name.', 736 | arguments: '' 737 | }, { 738 | value: 'ANIMATION*CHANNEL*$', 739 | type: 'property', 740 | description: 'access channel by name (a director name/path may be specified as $director_path$channel_name)', 741 | arguments: '' 742 | }, { 743 | value: 'ANIMATION*CHANNEL_FORCED*$', 744 | type: 'property', 745 | description: 'access channel by name (a director name/path may be specified as $director_path$channel_name)', 746 | arguments: '' 747 | }, { 748 | value: 'ANIMATION*KEY', 749 | type: 'property', 750 | description: '', 751 | arguments: '' 752 | }, { 753 | value: 'ANIMATION*KEY*', 754 | type: 'property', 755 | description: 'Accesses a keyframe by name. A director name/path may be specified as $director_path$key_name.', 756 | arguments: '' 757 | }, { 758 | value: 'ANIMATION*KEY*$', 759 | type: 'property', 760 | description: 'access keyframe by name (a director name/path may be specified as $director_path$key_name)', 761 | arguments: '' 762 | }, { 763 | value: 'ANIMATION*OFFSET', 764 | type: 'property', 765 | description: '', 766 | arguments: '' 767 | }, { 768 | value: 'AUTO_KEY_POS', 769 | type: 'property', 770 | description: 'This object controls the auto key function', 771 | arguments: '' 772 | }, { 773 | value: 'BACK_LAYER', 774 | type: 'property', 775 | description: 'Controls the scene in the back layer', 776 | arguments: '' 777 | }, { 778 | value: 'BACK_LAYER*EYE_SEPARATION', 779 | type: 'property', 780 | description: '', 781 | arguments: '' 782 | }, { 783 | value: 'BACK_LAYER*LAYER_VISIBLE', 784 | type: 'property', 785 | description: '', 786 | arguments: '' 787 | }, { 788 | value: 'BACK_LAYER*OVERWRITE_STEREO', 789 | type: 'property', 790 | description: '', 791 | arguments: '' 792 | }, { 793 | value: 'BACK_LAYER*ZERO_PARALLAX_DIST', 794 | type: 'property', 795 | description: '', 796 | arguments: '' 797 | }, { 798 | value: 'BACKGROUND*ALPHA', 799 | type: 'property', 800 | description: 'What is the default alpha value after clear screen', 801 | arguments: '' 802 | }, { 803 | value: 'BACKGROUND*COLOR', 804 | type: 'property', 805 | description: 'Color of the background', 806 | arguments: '' 807 | }, { 808 | value: 'BACKGROUND*IMAGE', 809 | type: 'property', 810 | description: 'Clear the background image', 811 | arguments: '' 812 | }, { 813 | value: 'BACKGROUND*IMAGE*ACTIVE', 814 | type: 'property', 815 | description: 'Is the background image active', 816 | arguments: '' 817 | }, { 818 | value: 'CAMERA%1', 819 | type: 'property', 820 | description: 'Cameras in the scene', 821 | arguments: '' 822 | }, { 823 | value: 'CAMERA*DATA', 824 | type: 'property', 825 | description: 'Get the data of all cameras of the scene with a single command', 826 | arguments: '' 827 | }, { 828 | value: 'CAMERA_ASPECT', 829 | type: 'property', 830 | description: 'The camera aspect', 831 | arguments: '' 832 | }, { 833 | value: 'CAMERA_FAR', 834 | type: 'property', 835 | description: 'The far value of the camera space. No object in behind the far value will be visible.', 836 | arguments: '' 837 | }, { 838 | value: 'CAMERA_NEAR', 839 | type: 'property', 840 | description: 'The near value of the camera space. No object in front of the near value will be visible.', 841 | arguments: '' 842 | }, { 843 | value: 'CLIPPER%1', 844 | type: 'property', 845 | description: 'Clipper', 846 | arguments: '' 847 | }, { 848 | value: 'CLIPPER*DATA', 849 | type: 'property', 850 | description: 'Get data of all clipper objects.', 851 | arguments: '' 852 | }, { 853 | value: 'COLOR_CORRECTION_BIAS', 854 | type: 'property', 855 | description: 'color correction bias', 856 | arguments: '' 857 | }, { 858 | value: 'COLOR_CORRECTION_SCALE', 859 | type: 'property', 860 | description: 'color correction scale', 861 | arguments: '' 862 | }, { 863 | value: 'COMMANDS_XML', 864 | type: 'property', 865 | description: 'Describes the command interface of this object', 866 | arguments: '' 867 | }, { 868 | value: 'CONTAINERSCRIPTS', 869 | type: 'property', 870 | description: '', 871 | arguments: '' 872 | }, { 873 | value: 'CONTENTS_VISIBLE', 874 | type: 'property', 875 | description: '', 876 | arguments: '' 877 | }, { 878 | value: 'CONTROL', 879 | type: 'property', 880 | description: 'Access sub-location by a previously defined control name', 881 | arguments: '' 882 | }, { 883 | value: 'COORDINATE_SYSTEM', 884 | type: 'property', 885 | description: '', 886 | arguments: '' 887 | }, { 888 | value: 'CSC', 889 | type: 'property', 890 | description: 'The Center Shift Calibration Marker', 891 | arguments: '' 892 | }, { 893 | value: 'CULLING', 894 | type: 'property', 895 | description: '', 896 | arguments: '' 897 | }, { 898 | value: 'CURRENT_CAMERA', 899 | type: 'property', 900 | description: 'This current camera', 901 | arguments: '' 902 | }, { 903 | value: 'CURRENT_CAMERA*EYE_SEPARATION', 904 | type: 'property', 905 | description: '', 906 | arguments: '' 907 | }, { 908 | value: 'CURRENT_CAMERA*STEREO_METHOD', 909 | type: 'property', 910 | description: '', 911 | arguments: '' 912 | }, { 913 | value: 'CURRENT_CAMERA*ZERO_PARALLAX_DIST', 914 | type: 'property', 915 | description: '', 916 | arguments: '' 917 | }, { 918 | value: 'DEFAULT_CAMERA', 919 | type: 'property', 920 | description: 'This camera is active when the scene is loaded', 921 | arguments: '' 922 | }, { 923 | value: 'DEFOCUS_BLUR', 924 | type: 'property', 925 | description: 'the blur factor applied to bg scenes when defocus is active', 926 | arguments: '' 927 | }, { 928 | value: 'DEFOCUS_MODE', 929 | type: 'property', 930 | description: 'Setting the defocus mode', 931 | arguments: '' 932 | }, { 933 | value: 'DEPTH_BUFFER', 934 | type: 'property', 935 | description: 'Obsolete: use DEPTH_BUFFER_STATE instead', 936 | arguments: '' 937 | }, { 938 | value: 'DEPTH_BUFFER_STATE', 939 | type: 'property', 940 | description: 'Should we use the depth buffer for rendering', 941 | arguments: '' 942 | }, { 943 | value: 'EDITED_OBJECT', 944 | type: 'property', 945 | description: '', 946 | arguments: '' 947 | }, { 948 | value: 'EDITED_OBJECTS', 949 | type: 'property', 950 | description: '', 951 | arguments: '' 952 | }, { 953 | value: 'EDITED_PATH_HANDLE', 954 | type: 'property', 955 | description: '', 956 | arguments: '' 957 | }, { 958 | value: 'ENABLE_SHADOWS', 959 | type: 'property', 960 | description: 'Are we allowed to render shadows in the scene', 961 | arguments: '' 962 | }, { 963 | value: 'EXTRA_INFO', 964 | type: 'property', 965 | description: '', 966 | arguments: '' 967 | }, { 968 | value: 'EYE_SEPARATION', 969 | type: 'property', 970 | description: '', 971 | arguments: '' 972 | }, { 973 | value: 'FILE_LINKS', 974 | type: 'property', 975 | description: '', 976 | arguments: '' 977 | }, { 978 | value: 'FLICKER_FILTER', 979 | type: 'property', 980 | description: 'Flicker filter value', 981 | arguments: '' 982 | }, { 983 | value: 'FORCE_DRAW_OUTLINE', 984 | type: 'property', 985 | description: '', 986 | arguments: '' 987 | }, { 988 | value: 'FOREGROUND*IMAGE', 989 | type: 'property', 990 | description: 'Clear the foreground image', 991 | arguments: '' 992 | }, { 993 | value: 'FOREGROUND*IMAGE*ACTIVE', 994 | type: 'property', 995 | description: 'Is the foreground image active', 996 | arguments: '' 997 | }, { 998 | value: 'FRAME_RATE', 999 | type: 'property', 1000 | description: '', 1001 | arguments: '' 1002 | }, { 1003 | value: 'FRONT_LAYER', 1004 | type: 'property', 1005 | description: 'Controls the scene in the front layer', 1006 | arguments: '' 1007 | }, { 1008 | value: 'FRONT_LAYER*EYE_SEPARATION', 1009 | type: 'property', 1010 | description: '', 1011 | arguments: '' 1012 | }, { 1013 | value: 'FRONT_LAYER*LAYER_VISIBLE', 1014 | type: 'property', 1015 | description: '', 1016 | arguments: '' 1017 | }, { 1018 | value: 'FRONT_LAYER*OVERWRITE_STEREO', 1019 | type: 'property', 1020 | description: '', 1021 | arguments: '' 1022 | }, { 1023 | value: 'FRONT_LAYER*ZERO_PARALLAX_DIST', 1024 | type: 'property', 1025 | description: '', 1026 | arguments: '' 1027 | }, { 1028 | value: 'FUNCTION', 1029 | type: 'property', 1030 | description: 'Functionplugins that are assigned to the scene', 1031 | arguments: '' 1032 | }, { 1033 | value: 'GAMMA', 1034 | type: 'property', 1035 | description: 'gamma value', 1036 | arguments: '' 1037 | }, { 1038 | value: 'GFX*%1', 1039 | type: 'property', 1040 | description: 'Graphics channels available', 1041 | arguments: '' 1042 | }, { 1043 | value: 'GLOBALS', 1044 | type: 'property', 1045 | description: 'Global scene data.', 1046 | arguments: '' 1047 | }, { 1048 | value: 'GRID', 1049 | type: 'property', 1050 | description: '', 1051 | arguments: '' 1052 | }, { 1053 | value: 'GRID*SELECT', 1054 | type: 'property', 1055 | description: '', 1056 | arguments: '' 1057 | }, { 1058 | value: 'HUD', 1059 | type: 'property', 1060 | description: 'The Head Up Display', 1061 | arguments: '' 1062 | }, { 1063 | value: 'IGNORE_GUI_REBUILD', 1064 | type: 'property', 1065 | description: '', 1066 | arguments: '' 1067 | }, { 1068 | value: 'INFOTEXT', 1069 | type: 'property', 1070 | description: '', 1071 | arguments: '' 1072 | }, { 1073 | value: 'INITIALIZE', 1074 | type: 'property', 1075 | description: '', 1076 | arguments: '' 1077 | }, { 1078 | value: 'INITIALIZE*COMMAND', 1079 | type: 'property', 1080 | description: '', 1081 | arguments: '' 1082 | }, { 1083 | value: 'INITIALIZE*DIRECTOR', 1084 | type: 'property', 1085 | description: 'Director Name To Initialize', 1086 | arguments: '' 1087 | }, { 1088 | value: 'INITIALIZE*FREQUENCY', 1089 | type: 'property', 1090 | description: '', 1091 | arguments: '' 1092 | }, { 1093 | value: 'INITIALIZE*LOAD', 1094 | type: 'property', 1095 | description: 'initialize the scene on load', 1096 | arguments: '' 1097 | }, { 1098 | value: 'INITIALIZE*TYPE', 1099 | type: 'property', 1100 | description: 'Defines the what to init, Stage or Director', 1101 | arguments: '' 1102 | }, { 1103 | value: 'KEEP_STORED_ORTHO_FRUSTUM', 1104 | type: 'property', 1105 | description: 'Keeps the orthogonal frustum stored in the scene', 1106 | arguments: '' 1107 | }, { 1108 | value: 'KEY_INTERNAL', 1109 | type: 'property', 1110 | description: '', 1111 | arguments: '' 1112 | }, { 1113 | value: 'KEY_INTERNAL*ACTIVE', 1114 | type: 'property', 1115 | description: '', 1116 | arguments: '' 1117 | }, { 1118 | value: 'KEY_RENDERMODE', 1119 | type: 'property', 1120 | description: '', 1121 | arguments: '' 1122 | }, { 1123 | value: 'LAYOUT*NUMBER', 1124 | type: 'property', 1125 | description: 'The number of the render layout of the scene. This is used in Viz Engine multi pipe render mode', 1126 | arguments: '' 1127 | }, { 1128 | value: 'LAYOUT*TYPE', 1129 | type: 'property', 1130 | description: 'The type of the render layout of the scene. This is used in Viz Engine multi pipe render mode', 1131 | arguments: '' 1132 | }, { 1133 | value: 'LIGHT%1', 1134 | type: 'property', 1135 | description: 'Lights in the scene', 1136 | arguments: '' 1137 | }, { 1138 | value: 'LIGHT*DATA', 1139 | type: 'property', 1140 | description: 'Get the data of all lights of the scene with a single command', 1141 | arguments: '' 1142 | }, { 1143 | value: 'LOCATION_PATH', 1144 | type: 'property', 1145 | description: '', 1146 | arguments: '' 1147 | }, { 1148 | value: 'MAIN_LAYER', 1149 | type: 'property', 1150 | description: 'Controls the scene in the main layer', 1151 | arguments: '' 1152 | }, { 1153 | value: 'MAIN_LAYER*EYE_SEPARATION', 1154 | type: 'property', 1155 | description: '', 1156 | arguments: '' 1157 | }, { 1158 | value: 'MAIN_LAYER*LAYER_VISIBLE', 1159 | type: 'property', 1160 | description: '', 1161 | arguments: '' 1162 | }, { 1163 | value: 'MAIN_LAYER*OVERWRITE_STEREO', 1164 | type: 'property', 1165 | description: '', 1166 | arguments: '' 1167 | }, { 1168 | value: 'MAIN_LAYER*ZERO_PARALLAX_DIST', 1169 | type: 'property', 1170 | description: '', 1171 | arguments: '' 1172 | }, { 1173 | value: 'MAP', 1174 | type: 'property', 1175 | description: 'Accesses the scenes shared memory map (used by scripts and plugins).', 1176 | arguments: '' 1177 | }, { 1178 | value: 'MASK_INVERT', 1179 | type: 'property', 1180 | description: 'Should a layer of the mask be inverted', 1181 | arguments: '' 1182 | }, { 1183 | value: 'MEDIA_ASSETS', 1184 | type: 'property', 1185 | description: 'Manager for all media sources', 1186 | arguments: '' 1187 | }, { 1188 | value: 'MERGE_STYLE', 1189 | type: 'property', 1190 | description: '', 1191 | arguments: '' 1192 | }, { 1193 | value: 'MIDDLE_LAYER', 1194 | type: 'property', 1195 | description: 'for Trio', 1196 | arguments: '' 1197 | }, { 1198 | value: 'NAME', 1199 | type: 'property', 1200 | description: '', 1201 | arguments: '' 1202 | }, { 1203 | value: 'NO_GFX_CHANNELS', 1204 | type: 'property', 1205 | description: '', 1206 | arguments: '' 1207 | }, { 1208 | value: 'NUMBER_OF_MASK_BITS', 1209 | type: 'property', 1210 | description: 'How many mask layers do we have available', 1211 | arguments: '' 1212 | }, { 1213 | value: 'OBJECT_ID', 1214 | type: 'property', 1215 | description: '', 1216 | arguments: '' 1217 | }, { 1218 | value: 'OBJECT_TYPE', 1219 | type: 'property', 1220 | description: 'What type of object is this', 1221 | arguments: '' 1222 | }, { 1223 | value: 'OUTPUT_REGION', 1224 | type: 'property', 1225 | description: 'Output Region', 1226 | arguments: '' 1227 | }, { 1228 | value: 'OVERWRITE_STEREO', 1229 | type: 'property', 1230 | description: '', 1231 | arguments: '' 1232 | }, { 1233 | value: 'PICK_LAYER', 1234 | type: 'property', 1235 | description: '', 1236 | arguments: '' 1237 | }, { 1238 | value: 'PICK_QUAD', 1239 | type: 'property', 1240 | description: 'Set the Pick Quad for chroma key active or inactive', 1241 | arguments: '' 1242 | }, { 1243 | value: 'PICK_QUAD_DATA', 1244 | type: 'property', 1245 | description: 'Set the Pick Quad Positiion and Size', 1246 | arguments: '' 1247 | }, { 1248 | value: 'POST', 1249 | type: 'property', 1250 | description: '', 1251 | arguments: '' 1252 | }, { 1253 | value: 'POST*STATUS', 1254 | type: 'property', 1255 | description: '', 1256 | arguments: '' 1257 | }, { 1258 | value: 'POST_MODE', 1259 | type: 'property', 1260 | description: '', 1261 | arguments: '' 1262 | }, { 1263 | value: 'RAMPLER*ACTIVE', 1264 | type: 'property', 1265 | description: 'Is the Rampler active in that scene', 1266 | arguments: '' 1267 | }, { 1268 | value: 'RAMPLER*BEGIN', 1269 | type: 'property', 1270 | description: 'Define the begin time the Rampler will record', 1271 | arguments: '' 1272 | }, { 1273 | value: 'RAMPLER*BOTTOM', 1274 | type: 'property', 1275 | description: 'Define the bottom side of the Rampler Area', 1276 | arguments: '' 1277 | }, { 1278 | value: 'RAMPLER*END', 1279 | type: 'property', 1280 | description: 'Define the end time the Rampler will record', 1281 | arguments: '' 1282 | }, { 1283 | value: 'RAMPLER*LEFT', 1284 | type: 'property', 1285 | description: 'Define the left side of the Rampler Area', 1286 | arguments: '' 1287 | }, { 1288 | value: 'RAMPLER*RIGHT', 1289 | type: 'property', 1290 | description: 'Define the right side of the Rampler Area', 1291 | arguments: '' 1292 | }, { 1293 | value: 'RAMPLER*TOP', 1294 | type: 'property', 1295 | description: 'Define the top side of the Rampler Area', 1296 | arguments: '' 1297 | }, { 1298 | value: 'RESET_CLIP_CHANNELS_ON_SET_SCENE', 1299 | type: 'property', 1300 | description: '', 1301 | arguments: '' 1302 | }, { 1303 | value: 'RINGING_FILTER', 1304 | type: 'property', 1305 | description: 'ringing filter', 1306 | arguments: '' 1307 | }, { 1308 | value: 'S2V*%1', 1309 | type: 'property', 1310 | description: 'Define the studio to virtual settings', 1311 | arguments: '' 1312 | }, { 1313 | value: 'S2V*INDEX', 1314 | type: 'property', 1315 | description: 'Define the index of the studio to virtual settings', 1316 | arguments: '' 1317 | }, { 1318 | value: 'SAA', 1319 | type: 'property', 1320 | description: 'Are we able to render software', 1321 | arguments: '' 1322 | }, { 1323 | value: 'SAA*ACTIVE', 1324 | type: 'property', 1325 | description: 'Do we render with software scene antialiasing', 1326 | arguments: '' 1327 | }, { 1328 | value: 'SAA*SAMPLES', 1329 | type: 'property', 1330 | description: 'How many samples do we want to use', 1331 | arguments: '' 1332 | }, { 1333 | value: 'SCENE_DATA', 1334 | type: 'property', 1335 | description: '', 1336 | arguments: '' 1337 | }, { 1338 | value: 'SCRIPT', 1339 | type: 'property', 1340 | description: 'The scene script', 1341 | arguments: '' 1342 | }, { 1343 | value: 'SCRIPT_COLOR_OLD', 1344 | type: 'property', 1345 | description: '', 1346 | arguments: '' 1347 | }, { 1348 | value: 'SELF_LAYER', 1349 | type: 'property', 1350 | description: '', 1351 | arguments: '' 1352 | }, { 1353 | value: 'SELF_LAYER_CAMERA', 1354 | type: 'property', 1355 | description: '', 1356 | arguments: '' 1357 | }, { 1358 | value: 'SHADOW_TYPE', 1359 | type: 'property', 1360 | description: 'Stencil based flat shadows or shadow mapping', 1361 | arguments: '' 1362 | }, { 1363 | value: 'SHORTCUTS', 1364 | type: 'property', 1365 | description: '', 1366 | arguments: '' 1367 | }, { 1368 | value: 'STAGE', 1369 | type: 'property', 1370 | description: 'Animation control of the scene', 1371 | arguments: '' 1372 | }, { 1373 | value: 'STEREO_PARAMETERS', 1374 | type: 'property', 1375 | description: '', 1376 | arguments: '' 1377 | }, { 1378 | value: 'TARGA3200', 1379 | type: 'property', 1380 | description: 'Targa3200', 1381 | arguments: '' 1382 | }, { 1383 | value: 'TEXT_EDITOR', 1384 | type: 'property', 1385 | description: '', 1386 | arguments: '' 1387 | }, { 1388 | value: 'TREE', 1389 | type: 'property', 1390 | description: 'Container tree of the scene', 1391 | arguments: '' 1392 | }, { 1393 | value: 'UPDATE', 1394 | type: 'property', 1395 | description: '', 1396 | arguments: '' 1397 | }, { 1398 | value: 'USE_AUTO_KEY', 1399 | type: 'property', 1400 | description: 'Should the auto key rendering method be used', 1401 | arguments: '' 1402 | }, { 1403 | value: 'USER_ASPECT', 1404 | type: 'property', 1405 | description: 'The camera aspect set by the user', 1406 | arguments: '' 1407 | }, { 1408 | value: 'UUID', 1409 | type: 'property', 1410 | description: '', 1411 | arguments: '' 1412 | }, { 1413 | value: 'VERSION', 1414 | type: 'property', 1415 | description: '', 1416 | arguments: '' 1417 | }, { 1418 | value: 'VGA_PREVIEW', 1419 | type: 'property', 1420 | description: '', 1421 | arguments: '' 1422 | }, { 1423 | value: 'VIDEO', 1424 | type: 'property', 1425 | description: 'Video', 1426 | arguments: '' 1427 | }, { 1428 | value: 'VIDEO*%1*FORMAT', 1429 | type: 'property', 1430 | description: 'What video format should be used in this scene for a certain input', 1431 | arguments: '' 1432 | }, { 1433 | value: 'VIDEO*%1*MODE', 1434 | type: 'property', 1435 | description: 'What video mode should be used in this scene for a certain input', 1436 | arguments: '' 1437 | }, { 1438 | value: 'VIEW', 1439 | type: 'property', 1440 | description: '', 1441 | arguments: '' 1442 | }, { 1443 | value: 'ZERO_PARALLAX_DIST', 1444 | type: 'property', 1445 | description: '', 1446 | arguments: '' 1447 | }, { 1448 | value: '{UUID}', 1449 | type: 'property', 1450 | description: '', 1451 | arguments: '' 1452 | }], 1453 | [{ 1454 | value: '#OBJECTID', 1455 | type: 'property', 1456 | description: '', 1457 | arguments: '' 1458 | }, { 1459 | value: 'ANIMATION', 1460 | type: 'property', 1461 | description: '', 1462 | arguments: '' 1463 | }, { 1464 | value: 'ANIMATION*', 1465 | type: 'property', 1466 | description: 'Accesses a channel by name.', 1467 | arguments: '' 1468 | }, { 1469 | value: 'ANIMATION*CHANNEL*$', 1470 | type: 'property', 1471 | description: 'access channel by name (a director name/path may be specified as $director_path$channel_name)', 1472 | arguments: '' 1473 | }, { 1474 | value: 'ANIMATION*CHANNEL_FORCED*$', 1475 | type: 'property', 1476 | description: 'access channel by name (a director name/path may be specified as $director_path$channel_name)', 1477 | arguments: '' 1478 | }, { 1479 | value: 'ANIMATION*KEY', 1480 | type: 'property', 1481 | description: '', 1482 | arguments: '' 1483 | }, { 1484 | value: 'ANIMATION*KEY*', 1485 | type: 'property', 1486 | description: 'Accesses a keyframe by name. A director name/path may be specified as $director_path$key_name.', 1487 | arguments: '' 1488 | }, { 1489 | value: 'ANIMATION*KEY*$', 1490 | type: 'property', 1491 | description: 'access keyframe by name (a director name/path may be specified as $director_path$key_name)', 1492 | arguments: '' 1493 | }, { 1494 | value: 'ANIMATION*OFFSET', 1495 | type: 'property', 1496 | description: '', 1497 | arguments: '' 1498 | }, { 1499 | value: 'AUTO_KEY_POS', 1500 | type: 'property', 1501 | description: 'This object controls the auto key function', 1502 | arguments: '' 1503 | }, { 1504 | value: 'BACKGROUND*ALPHA', 1505 | type: 'property', 1506 | description: 'What is the default alpha value after clear screen', 1507 | arguments: '' 1508 | }, { 1509 | value: 'BACKGROUND*COLOR', 1510 | type: 'property', 1511 | description: 'Color of the background', 1512 | arguments: '' 1513 | }, { 1514 | value: 'BACKGROUND*IMAGE', 1515 | type: 'property', 1516 | description: 'Clear the background image', 1517 | arguments: '' 1518 | }, { 1519 | value: 'BACKGROUND*IMAGE*ACTIVE', 1520 | type: 'property', 1521 | description: 'Is the background image active', 1522 | arguments: '' 1523 | }, { 1524 | value: 'CAMERA%1', 1525 | type: 'property', 1526 | description: 'Cameras in the scene', 1527 | arguments: '' 1528 | }, { 1529 | value: 'CAMERA*DATA', 1530 | type: 'property', 1531 | description: 'Get the data of all cameras of the scene with a single command', 1532 | arguments: '' 1533 | }, { 1534 | value: 'CAMERA_ASPECT', 1535 | type: 'property', 1536 | description: 'The camera aspect', 1537 | arguments: '' 1538 | }, { 1539 | value: 'CAMERA_FAR', 1540 | type: 'property', 1541 | description: 'The far value of the camera space. No object in behind the far value will be visible.', 1542 | arguments: '' 1543 | }, { 1544 | value: 'CAMERA_NEAR', 1545 | type: 'property', 1546 | description: 'The near value of the camera space. No object in front of the near value will be visible.', 1547 | arguments: '' 1548 | }, { 1549 | value: 'CLIPPER%1', 1550 | type: 'property', 1551 | description: 'Clipper', 1552 | arguments: '' 1553 | }, { 1554 | value: 'CLIPPER*DATA', 1555 | type: 'property', 1556 | description: 'Get data of all clipper objects.', 1557 | arguments: '' 1558 | }, { 1559 | value: 'COLOR_CORRECTION_BIAS', 1560 | type: 'property', 1561 | description: 'color correction bias', 1562 | arguments: '' 1563 | }, { 1564 | value: 'COLOR_CORRECTION_SCALE', 1565 | type: 'property', 1566 | description: 'color correction scale', 1567 | arguments: '' 1568 | }, { 1569 | value: 'COMMANDS_XML', 1570 | type: 'property', 1571 | description: 'Describes the command interface of this object', 1572 | arguments: '' 1573 | }, { 1574 | value: 'CONTAINERSCRIPTS', 1575 | type: 'property', 1576 | description: '', 1577 | arguments: '' 1578 | }, { 1579 | value: 'CONTROL', 1580 | type: 'property', 1581 | description: 'Access sub-location by a previously defined control name', 1582 | arguments: '' 1583 | }, { 1584 | value: 'CULLING', 1585 | type: 'property', 1586 | description: '', 1587 | arguments: '' 1588 | }, { 1589 | value: 'CURRENT_CAMERA', 1590 | type: 'property', 1591 | description: 'This current camera', 1592 | arguments: '' 1593 | }, { 1594 | value: 'DEFAULT_CAMERA', 1595 | type: 'property', 1596 | description: 'This camera is active when the scene is loaded', 1597 | arguments: '' 1598 | }, { 1599 | value: 'DEFOCUS_BLUR', 1600 | type: 'property', 1601 | description: 'the blur factor applied to bg scenes when defocus is active', 1602 | arguments: '' 1603 | }, { 1604 | value: 'DEFOCUS_MODE', 1605 | type: 'property', 1606 | description: 'Setting the defocus mode', 1607 | arguments: '' 1608 | }, { 1609 | value: 'DEPTH_BUFFER', 1610 | type: 'property', 1611 | description: 'Obsolete: use DEPTH_BUFFER_STATE instead', 1612 | arguments: '' 1613 | }, { 1614 | value: 'DEPTH_BUFFER_STATE', 1615 | type: 'property', 1616 | description: 'Should we use the depth buffer for rendering', 1617 | arguments: '' 1618 | }, { 1619 | value: 'EDITED_OBJECT', 1620 | type: 'property', 1621 | description: '', 1622 | arguments: '' 1623 | }, { 1624 | value: 'EDITED_OBJECTS', 1625 | type: 'property', 1626 | description: '', 1627 | arguments: '' 1628 | }, { 1629 | value: 'EDITED_PATH_HANDLE', 1630 | type: 'property', 1631 | description: '', 1632 | arguments: '' 1633 | }, { 1634 | value: 'ENABLE_SHADOWS', 1635 | type: 'property', 1636 | description: 'Are we allowed to render shadows in the scene', 1637 | arguments: '' 1638 | }, { 1639 | value: 'EXTRA_INFO', 1640 | type: 'property', 1641 | description: '', 1642 | arguments: '' 1643 | }, { 1644 | value: 'FILE_LINKS', 1645 | type: 'property', 1646 | description: '', 1647 | arguments: '' 1648 | }, { 1649 | value: 'FLICKER_FILTER', 1650 | type: 'property', 1651 | description: 'Flicker filter value', 1652 | arguments: '' 1653 | }, { 1654 | value: 'FORCE_DRAW_OUTLINE', 1655 | type: 'property', 1656 | description: '', 1657 | arguments: '' 1658 | }, { 1659 | value: 'FOREGROUND*IMAGE', 1660 | type: 'property', 1661 | description: 'Clear the foreground image', 1662 | arguments: '' 1663 | }, { 1664 | value: 'FOREGROUND*IMAGE*ACTIVE', 1665 | type: 'property', 1666 | description: 'Is the foreground image active', 1667 | arguments: '' 1668 | }, { 1669 | value: 'FRAME_RATE', 1670 | type: 'property', 1671 | description: '', 1672 | arguments: '' 1673 | }, { 1674 | value: 'FUNCTION', 1675 | type: 'property', 1676 | description: 'Functionplugins that are assigned to the scene', 1677 | arguments: '' 1678 | }, { 1679 | value: 'GAMMA', 1680 | type: 'property', 1681 | description: 'gamma value', 1682 | arguments: '' 1683 | }, { 1684 | value: 'GFX*%1', 1685 | type: 'property', 1686 | description: 'Graphics channels available', 1687 | arguments: '' 1688 | }, { 1689 | value: 'GLOBALS', 1690 | type: 'property', 1691 | description: 'Global scene data.', 1692 | arguments: '' 1693 | }, { 1694 | value: 'GRID', 1695 | type: 'property', 1696 | description: '', 1697 | arguments: '' 1698 | }, { 1699 | value: 'GRID*SELECT', 1700 | type: 'property', 1701 | description: '', 1702 | arguments: '' 1703 | }, { 1704 | value: 'IGNORE_GUI_REBUILD', 1705 | type: 'property', 1706 | description: '', 1707 | arguments: '' 1708 | }, { 1709 | value: 'INFOTEXT', 1710 | type: 'property', 1711 | description: '', 1712 | arguments: '' 1713 | }, { 1714 | value: 'INITIALIZE', 1715 | type: 'property', 1716 | description: '', 1717 | arguments: '' 1718 | }, { 1719 | value: 'INITIALIZE*COMMAND', 1720 | type: 'property', 1721 | description: '', 1722 | arguments: '' 1723 | }, { 1724 | value: 'INITIALIZE*DIRECTOR', 1725 | type: 'property', 1726 | description: 'Director Name To Initialize', 1727 | arguments: '' 1728 | }, { 1729 | value: 'INITIALIZE*FREQUENCY', 1730 | type: 'property', 1731 | description: '', 1732 | arguments: '' 1733 | }, { 1734 | value: 'INITIALIZE*LOAD', 1735 | type: 'property', 1736 | description: 'initialize the scene on load', 1737 | arguments: '' 1738 | }, { 1739 | value: 'INITIALIZE*TYPE', 1740 | type: 'property', 1741 | description: 'Defines the what to init, Stage or Director', 1742 | arguments: '' 1743 | }, { 1744 | value: 'KEEP_STORED_ORTHO_FRUSTUM', 1745 | type: 'property', 1746 | description: 'Keeps the orthogonal frustum stored in the scene', 1747 | arguments: '' 1748 | }, { 1749 | value: 'KEY_RENDERMODE', 1750 | type: 'property', 1751 | description: '', 1752 | arguments: '' 1753 | }, { 1754 | value: 'LAYOUT*NUMBER', 1755 | type: 'property', 1756 | description: 'The number of the render layout of the scene. This is used in Viz Engine multi pipe render mode', 1757 | arguments: '' 1758 | }, { 1759 | value: 'LAYOUT*TYPE', 1760 | type: 'property', 1761 | description: 'The type of the render layout of the scene. This is used in Viz Engine multi pipe render mode', 1762 | arguments: '' 1763 | }, { 1764 | value: 'LIGHT%1', 1765 | type: 'property', 1766 | description: 'Lights in the scene', 1767 | arguments: '' 1768 | }, { 1769 | value: 'LIGHT*DATA', 1770 | type: 'property', 1771 | description: 'Get the data of all lights of the scene with a single command', 1772 | arguments: '' 1773 | }, { 1774 | value: 'LOCATION_PATH', 1775 | type: 'property', 1776 | description: '', 1777 | arguments: '' 1778 | }, { 1779 | value: 'MAP', 1780 | type: 'property', 1781 | description: 'Accesses the scenes shared memory map (used by scripts and plugins).', 1782 | arguments: '' 1783 | }, { 1784 | value: 'MASK_INVERT', 1785 | type: 'property', 1786 | description: 'Should a layer of the mask be inverted', 1787 | arguments: '' 1788 | }, { 1789 | value: 'MEDIA_ASSETS', 1790 | type: 'property', 1791 | description: 'Manager for all media sources', 1792 | arguments: '' 1793 | }, { 1794 | value: 'MERGE_STYLE', 1795 | type: 'property', 1796 | description: '', 1797 | arguments: '' 1798 | }, { 1799 | value: 'NAME', 1800 | type: 'property', 1801 | description: '', 1802 | arguments: '' 1803 | }, { 1804 | value: 'NO_GFX_CHANNELS', 1805 | type: 'property', 1806 | description: '', 1807 | arguments: '' 1808 | }, { 1809 | value: 'NUMBER_OF_MASK_BITS', 1810 | type: 'property', 1811 | description: 'How many mask layers do we have available', 1812 | arguments: '' 1813 | }, { 1814 | value: 'OBJECT_ID', 1815 | type: 'property', 1816 | description: '', 1817 | arguments: '' 1818 | }, { 1819 | value: 'OBJECT_TYPE', 1820 | type: 'property', 1821 | description: 'What type of object is this', 1822 | arguments: '' 1823 | }, { 1824 | value: 'OUTPUT_REGION', 1825 | type: 'property', 1826 | description: 'Output Region', 1827 | arguments: '' 1828 | }, { 1829 | value: 'RAMPLER*ACTIVE', 1830 | type: 'property', 1831 | description: 'Is the Rampler active in that scene', 1832 | arguments: '' 1833 | }, { 1834 | value: 'RAMPLER*BEGIN', 1835 | type: 'property', 1836 | description: 'Define the begin time the Rampler will record', 1837 | arguments: '' 1838 | }, { 1839 | value: 'RAMPLER*BOTTOM', 1840 | type: 'property', 1841 | description: 'Define the bottom side of the Rampler Area', 1842 | arguments: '' 1843 | }, { 1844 | value: 'RAMPLER*END', 1845 | type: 'property', 1846 | description: 'Define the end time the Rampler will record', 1847 | arguments: '' 1848 | }, { 1849 | value: 'RAMPLER*LEFT', 1850 | type: 'property', 1851 | description: 'Define the left side of the Rampler Area', 1852 | arguments: '' 1853 | }, { 1854 | value: 'RAMPLER*RIGHT', 1855 | type: 'property', 1856 | description: 'Define the right side of the Rampler Area', 1857 | arguments: '' 1858 | }, { 1859 | value: 'RAMPLER*TOP', 1860 | type: 'property', 1861 | description: 'Define the top side of the Rampler Area', 1862 | arguments: '' 1863 | }, { 1864 | value: 'RESET_CLIP_CHANNELS_ON_SET_SCENE', 1865 | type: 'property', 1866 | description: '', 1867 | arguments: '' 1868 | }, { 1869 | value: 'RINGING_FILTER', 1870 | type: 'property', 1871 | description: 'ringing filter', 1872 | arguments: '' 1873 | }, { 1874 | value: 'S2V*%1', 1875 | type: 'property', 1876 | description: 'Define the studio to virtual settings', 1877 | arguments: '' 1878 | }, { 1879 | value: 'S2V*INDEX', 1880 | type: 'property', 1881 | description: 'Define the index of the studio to virtual settings', 1882 | arguments: '' 1883 | }, { 1884 | value: 'SCENE_DATA', 1885 | type: 'property', 1886 | description: '', 1887 | arguments: '' 1888 | }, { 1889 | value: 'SCRIPT', 1890 | type: 'property', 1891 | description: 'The scene script', 1892 | arguments: '' 1893 | }, { 1894 | value: 'SCRIPT_COLOR_OLD', 1895 | type: 'property', 1896 | description: '', 1897 | arguments: '' 1898 | }, { 1899 | value: 'SELF_LAYER', 1900 | type: 'property', 1901 | description: '', 1902 | arguments: '' 1903 | }, { 1904 | value: 'SELF_LAYER_CAMERA', 1905 | type: 'property', 1906 | description: '', 1907 | arguments: '' 1908 | }, { 1909 | value: 'SHADOW_TYPE', 1910 | type: 'property', 1911 | description: 'Stencil based flat shadows or shadow mapping', 1912 | arguments: '' 1913 | }, { 1914 | value: 'STAGE', 1915 | type: 'property', 1916 | description: 'Animation control of the scene', 1917 | arguments: '' 1918 | }, { 1919 | value: 'TARGA3200', 1920 | type: 'property', 1921 | description: 'Targa3200', 1922 | arguments: '' 1923 | }, { 1924 | value: 'TREE', 1925 | type: 'property', 1926 | description: 'Container tree of the scene', 1927 | arguments: '' 1928 | }, { 1929 | value: 'USE_AUTO_KEY', 1930 | type: 'property', 1931 | description: 'Should the auto key rendering method be used', 1932 | arguments: '' 1933 | }, { 1934 | value: 'USER_ASPECT', 1935 | type: 'property', 1936 | description: 'The camera aspect set by the user', 1937 | arguments: '' 1938 | }, { 1939 | value: 'UUID', 1940 | type: 'property', 1941 | description: '', 1942 | arguments: '' 1943 | }, { 1944 | value: 'VERSION', 1945 | type: 'property', 1946 | description: '', 1947 | arguments: '' 1948 | }, { 1949 | value: 'VIDEO', 1950 | type: 'property', 1951 | description: '', 1952 | arguments: '' 1953 | }, { 1954 | value: 'VIDEO*%1*FORMAT', 1955 | type: 'property', 1956 | description: 'What video format should be used in this scene for a certain input', 1957 | arguments: '' 1958 | }, { 1959 | value: 'VIDEO*%1*MODE', 1960 | type: 'property', 1961 | description: 'What video mode should be used in this scene for a certain input', 1962 | arguments: '' 1963 | }, { 1964 | value: '{UUID}', 1965 | type: 'property', 1966 | description: '', 1967 | arguments: '' 1968 | }], 1969 | [{ 1970 | value: 'COMMAND_INFO', 1971 | type: 'command', 1972 | description: 'Returns help on a command or location.', 1973 | arguments: '{STRING} default=NULL, {ENUM} {ALL | ANIMATABLE | COMMANDS | ONE_LEVEL | PROPERTIES} default="ALL",{line_width as UINT}(min=40;max=254) default=80,{ENUM} {DEFAULT | NO_SPACING | SIMPLE | SPACING-%d | TAB-%d} default="DEFAULT"' 1974 | }, { 1975 | value: 'INVOKE', 1976 | type: 'command', 1977 | description: 'call a script procedure', 1978 | arguments: '{function-name as STRING},{argument-string as ARGUMENT-LIST}' 1979 | }, { 1980 | value: 'LOAD_PLUGIN_SOURCE', 1981 | type: 'command', 1982 | description: 'load the source from the specified script plugin', 1983 | arguments: '{plugin_name as STRING},{ENUM} {ADD | REPLACE} default="REPLACE"' 1984 | }, { 1985 | value: 'MAKE_PLUGIN', 1986 | type: 'command', 1987 | description: 'transform this script into a plugin', 1988 | arguments: '{folder/name as STRING}' 1989 | }, { 1990 | value: 'SET_CHANGED', 1991 | type: 'command', 1992 | description: 'calls set_changed()', 1993 | arguments: '' 1994 | }] 1995 | ]; 1996 | 1997 | $scope.vm = vm; 1998 | } 1999 | ]); 2000 | -------------------------------------------------------------------------------- /client/app/modules/commands/directive-command-item.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('commandsender.commands') 4 | .directive('commandItem', ['R', function(R) { 5 | return { 6 | restrict: 'E', 7 | replace: true, 8 | scope: { 9 | command: '=', 10 | send: '&', 11 | copy: '&', 12 | edit: '&', 13 | remove: '&' 14 | }, 15 | templateUrl: 'views/commands/template-command-item.html', 16 | link: function(scope) { 17 | 18 | scope.needsMultiline = function(text){ 19 | return (text.length > 100) || R.test(/\r/, text) || R.test(/\n/, text); 20 | }; 21 | 22 | } 23 | }; 24 | }]); 25 | -------------------------------------------------------------------------------- /client/app/modules/commands/factory-renderer-service.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('commandsender.commands') 4 | .factory('rendererService', ['socketService', function(socketService) { 5 | 6 | var render = function(options) { 7 | return socketService.send('render', { 8 | type: 'send-to-renderer', 9 | options: options 10 | }); 11 | }; 12 | 13 | return { 14 | render: render 15 | }; 16 | }]); 17 | -------------------------------------------------------------------------------- /client/app/modules/commands/route-commands.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('commandsender.commands').config(['$stateProvider', function($stateProvider) { 4 | 5 | $stateProvider 6 | .state('commands', { 7 | url: '/', 8 | templateUrl: 'views/commands/commands.html', 9 | controller: 'Commands' 10 | }); 11 | }]); 12 | -------------------------------------------------------------------------------- /client/app/modules/commands/template-command-item.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | {{command.description}} 4 |
5 |
6 |
7 |
8 |
9 | {{command.properties[0]}} 10 | {{command.properties[1]}} 11 | {{command.properties[2]}} 12 | {{command.command}} 13 | {{command.attributes}} 14 |
15 |
16 |
{{command.attributes}}
17 |
18 |
19 |
20 |
21 | 22 | 23 | 24 | 25 |
26 |
27 |
28 | -------------------------------------------------------------------------------- /client/app/modules/common/!module-commands.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('commandsender.common', []); 4 | -------------------------------------------------------------------------------- /client/app/modules/common/services/factory-ramda.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('commandsender.common') 4 | .factory('R', ['$window', function($window) { 5 | return $window.R; 6 | }]); -------------------------------------------------------------------------------- /client/app/modules/common/services/factory-socket-service.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('commandsender.common') 4 | .factory('socketService', ['socketFactory', '$q', function(socketFactory, $q) { 5 | 6 | var socket = io('localhost:11000', {transports: ['websocket', 'polling-xhr', 'polling']}); 7 | 8 | var socketService = socketFactory({ioSocket: socket}); 9 | 10 | socketService.once('getid', function(id){ 11 | //console.log(id); 12 | socketService.clientId = id; 13 | }); 14 | 15 | socketService.send = function(name, options){ 16 | 17 | var deferred = $q.defer(); 18 | 19 | socketService.emit(name, options, function(data){ 20 | console.log(data); 21 | deferred.resolve(data); 22 | }); 23 | 24 | return deferred.promise; 25 | }; 26 | 27 | socketService.connect(); 28 | 29 | return socketService; 30 | }]); 31 | 32 | /*angular.module('commandsender') 33 | .run(['socketService', function(socketService) { 34 | return socketService; 35 | }]);*/ 36 | -------------------------------------------------------------------------------- /client/app/modules/common/services/factory-uuid-service.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('commandsender.common') 4 | .factory('uuidService', function() { 5 | 6 | var newUuid = function() { 7 | 8 | // http://www.ietf.org/rfc/rfc4122.txt 9 | var s = []; 10 | var hexDigits = "0123456789abcdef"; 11 | for (var i = 0; i < 36; i++) { 12 | s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1); 13 | } 14 | s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010 15 | s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01 16 | s[8] = s[13] = s[18] = s[23] = "-"; 17 | return s.join(""); 18 | }; 19 | 20 | return { 21 | newUuid: newUuid 22 | } 23 | }); 24 | -------------------------------------------------------------------------------- /client/app/styles/_commands.scss: -------------------------------------------------------------------------------- 1 | .margin-6 { 2 | margin: 6px; 3 | } 4 | 5 | .margin-3 { 6 | margin: 3px; 7 | } 8 | 9 | .margin-bottom-12 { 10 | margin-bottom: 12px; 11 | } 12 | 13 | .align-right { 14 | text-align: right; 15 | } 16 | 17 | .align-centre { 18 | text-align: center; 19 | } 20 | 21 | .centre { 22 | display: block; 23 | margin: 0 auto; 24 | } 25 | 26 | .input-blue { 27 | background-color: #006dcc; 28 | color: #fff; 29 | 30 | &::-webkit-input-placeholder { 31 | color: white; 32 | } 33 | 34 | &:-moz-placeholder { 35 | color: white; 36 | } 37 | 38 | &::-moz-placeholder { 39 | color: white; 40 | } 41 | 42 | &:-ms-input-placeholder { 43 | color: white; 44 | } 45 | } 46 | 47 | .input-yellow { 48 | background-color: #eb9316; 49 | color: #fff; 50 | 51 | &::-webkit-input-placeholder { 52 | color: white; 53 | } 54 | 55 | &:-moz-placeholder { 56 | color: white; 57 | } 58 | 59 | &::-moz-placeholder { 60 | color: white; 61 | } 62 | 63 | &:-ms-input-placeholder { 64 | color: white; 65 | } 66 | } 67 | 68 | hr { 69 | display: block; 70 | height: 1px; 71 | border: 0; 72 | border-top: 1px solid #ddd; 73 | padding: 0; 74 | margin: 12px 0; 75 | } 76 | 77 | .stack-container { 78 | margin: 0; 79 | } 80 | 81 | .stack-item { 82 | position: relative; 83 | background-color: #ddd; 84 | border-radius: 4px; 85 | padding: 12px 3px; 86 | margin: 16px 0; 87 | 88 | .stack-item-description { 89 | position: absolute; 90 | top: -6px; 91 | right: 0; 92 | width: 100%; 93 | text-align: right; 94 | 95 | span { 96 | border-radius: 4px; 97 | border: 4px solid #ddd; 98 | background-color: #ddd; 99 | color: #666; 100 | padding: 2px 20px 8px 20px; 101 | font-size: 14px; 102 | font-weight: 500; 103 | text-align: center; 104 | } 105 | } 106 | 107 | .stack-item-command { 108 | padding: 0 3px; 109 | margin-top: 12px; 110 | 111 | .stack-item-command-item { 112 | color: #fff; 113 | border-radius: 4px; 114 | padding: 6px; 115 | 116 | &.stack-item-command-item-blue { 117 | background-color: #006dcc; 118 | } 119 | 120 | &.stack-item-command-item-yellow { 121 | background-color: #eb9316; 122 | } 123 | 124 | &.stack-item-command-item-white { 125 | color: #444; 126 | background-color: #fff; 127 | } 128 | } 129 | } 130 | } 131 | 132 | .stack-item-buttons { 133 | padding-top: 4px; 134 | } 135 | 136 | .large-star { 137 | font-size: 32px; 138 | margin: 0; 139 | padding: 0; 140 | } 141 | 142 | .command-params { 143 | min-height: 10em; 144 | } 145 | 146 | .command-button{ 147 | margin: 3px; 148 | width: 80px; 149 | } 150 | 151 | .console{ 152 | min-height: 50em; 153 | max-width: 100%; 154 | } 155 | 156 | .send-toast{ 157 | text-align: left; 158 | font-weight: 700; 159 | font-size: 16px; 160 | } 161 | 162 | .main-title{ 163 | text-align: center; 164 | color: #666; 165 | } 166 | 167 | .title{ 168 | color: #666; 169 | } -------------------------------------------------------------------------------- /client/app/styles/_typeahead.scss: -------------------------------------------------------------------------------- 1 | .nav, 2 | .pagination, 3 | .carousel, 4 | .panel-title a { 5 | cursor: pointer; 6 | } 7 | 8 | .typeahead-demo .custom-popup-wrapper { 9 | position: absolute; 10 | top: 100%; 11 | left: 0; 12 | z-index: 1000; 13 | display: none; 14 | background-color: #f9f9f9; 15 | 16 | & > .message { 17 | padding: 10px 20px; 18 | border-bottom: 1px solid #ddd; 19 | color: #868686; 20 | } 21 | 22 | & > .dropdown-menu { 23 | position: static; 24 | float: none; 25 | display: block; 26 | min-width: 160px; 27 | background-color: transparent; 28 | border: none; 29 | border-radius: 0; 30 | box-shadow: none; 31 | } 32 | } -------------------------------------------------------------------------------- /client/app/styles/main.scss: -------------------------------------------------------------------------------- 1 | @import "commands.scss"; 2 | @import "typeahead.scss"; 3 | -------------------------------------------------------------------------------- /client/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BBC_VizRT_Command_Sender_Client", 3 | "version": "0.1.0", 4 | "dependencies": { 5 | "angular": "^1.3.0", 6 | "angular-animate": "^1.3.0", 7 | "angular-aria": "^1.3.0", 8 | "angular-bootstrap": "^1.0.0", 9 | "angular-resource": "^1.3.0", 10 | "angular-sanitize": "^1.3.0", 11 | "angular-socket-io": "~0.7.0", 12 | "socket.io-client": "^1.3.3", 13 | "angular-touch": "^1.3.0", 14 | "angular-ui-router": "~0.2.13", 15 | "components-font-awesome": "^4.3.0", 16 | "es5-shim": "^4.0.0", 17 | "jquery": "~2.1.4", 18 | "json3": "^3.3.0", 19 | "bootstrap": "~3.3.5", 20 | "angular-ng-sortablejs": "~1.4.2", 21 | "ramda": "~0.19.1", 22 | "ngstorage": "^0.3.0", 23 | "angular-file-saver": "~1.1.0", 24 | "ngToast": "ngtoast#^1.5.6" 25 | }, 26 | "devDependencies": {}, 27 | "appPath": "app" 28 | } 29 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BBC_VizRT_Command_Sender_Client", 3 | "version": "0.1.0", 4 | "dependencies": {}, 5 | "devDependencies": { 6 | "grunt": "^0.4.1", 7 | "grunt-autoprefixer": "^0.7.3", 8 | "grunt-concurrent": "^0.5.0", 9 | "grunt-contrib-clean": "^0.5.0", 10 | "grunt-contrib-compass": "^0.7.2", 11 | "grunt-contrib-concat": "^0.4.0", 12 | "grunt-contrib-connect": "^0.7.1", 13 | "grunt-contrib-copy": "^0.5.0", 14 | "grunt-contrib-cssmin": "^0.9.0", 15 | "grunt-contrib-htmlmin": "^0.3.0", 16 | "grunt-contrib-imagemin": "^0.8.1", 17 | "grunt-contrib-jshint": "^0.10.0", 18 | "grunt-contrib-uglify": "^0.4.0", 19 | "grunt-contrib-watch": "^0.6.1", 20 | "grunt-filerev": "^0.2.1", 21 | "grunt-include-source": "^0.4.5", 22 | "grunt-karma": "^0.9.0", 23 | "grunt-newer": "^0.7.0", 24 | "grunt-ng-annotate": "^0.4.0", 25 | "grunt-svgmin": "^0.4.0", 26 | "grunt-usemin": "^2.1.1", 27 | "grunt-wiredep": "^1.7.0", 28 | "jasmine-core": "^2.1.3", 29 | "jshint-stylish": "^0.2.0", 30 | "karma": "^0.12.28", 31 | "karma-jasmine": "^0.3.2", 32 | "karma-phantomjs-launcher": "^0.1.4", 33 | "load-grunt-tasks": "^0.4.0", 34 | "time-grunt": "^0.3.1" 35 | }, 36 | "engines": { 37 | "node": ">=0.10.0" 38 | }, 39 | "scripts": { 40 | "test": "grunt test" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /server/Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 3 | // configure the tasks 4 | grunt.initConfig({ 5 | 6 | pkg: require('./package.json'), 7 | 8 | watch: { 9 | scripts: { 10 | files: [ 11 | 'server.js', 12 | '**/**/*.js' 13 | ], 14 | tasks: ['jshint', 'nodemon'], 15 | options: { 16 | nospawn: true 17 | } 18 | } 19 | }, 20 | nodemon: { 21 | dev: { 22 | script: 'app.js', 23 | options: { 24 | nodeArgs: ['--debug'] 25 | } 26 | } 27 | }, 28 | jshint: { 29 | all: ['app.js', 'api/**/*.js'] 30 | } 31 | }); 32 | 33 | 34 | grunt.loadNpmTasks('grunt-contrib-watch'); 35 | grunt.loadNpmTasks('grunt-contrib-jshint'); 36 | grunt.loadNpmTasks('grunt-nodemon'); 37 | 38 | grunt.registerTask('default', ['nodemon', 'watch']); 39 | 40 | }; 41 | -------------------------------------------------------------------------------- /server/app-cluster.js: -------------------------------------------------------------------------------- 1 | var cluster = require('cluster'), 2 | express = require('express'), 3 | app = express(), 4 | http = require('http'), 5 | server = http.createServer(app) 6 | port = Number(process.env.PORT || 7000), 7 | redis = require('redis'), 8 | redisAdapter = require('socket.io-redis'), 9 | renderClient = redis.createClient(6379, 'localhost', { 10 | detect_buffers: true 11 | }), 12 | pub = redis.createClient(6379, 'localhost', { 13 | detect_buffers: true 14 | }), 15 | sub = redis.createClient(6379, 'localhost', { 16 | detect_buffers: true 17 | }); 18 | 19 | //Catch any exceptions we might have missed 20 | process.on('uncaughtException', function(err) { 21 | process.exit(1); 22 | }); 23 | 24 | cluster.schedulingPolicy = cluster.SCHED_RR; 25 | 26 | if (cluster.isMaster) { 27 | var cpuCount = require('os').cpus().length; 28 | 29 | // Create a worker for each CPU 30 | for (var i = 0; i < cpuCount; i += 1) { 31 | cluster.fork(); 32 | } 33 | 34 | // Listen for dying workers 35 | cluster.on('exit', function(worker) { 36 | // Replace the dead worker, we're not sentimental 37 | console.log('Worker ' + worker.id + ' died :('); 38 | cluster.fork(); 39 | }); 40 | 41 | } else { 42 | 43 | //console.log('Worker ' + cluster.worker.id + ' running... :)'); 44 | 45 | //set up CORS headers (dev only) and express rendering 46 | require('./setup')(app, express); 47 | 48 | //init Socket.IO and link to http server 49 | var io = require('socket.io')(server, { 50 | transports: ['websocket', 'polling-xhr', 'polling'] 51 | }); 52 | 53 | //connect redis service 54 | io.adapter(redisAdapter({ 55 | pubClient: pub, 56 | subClient: sub 57 | })); 58 | 59 | //init routes for servering initial command sender page 60 | require('./routes')(app, io, express); 61 | 62 | //set up web socket handler to receive Viz commands 63 | require('./websockets')(io, renderClient); 64 | 65 | //start http server listening 66 | server.listen(port, function() { 67 | console.log('App listening on ' + port); 68 | }); 69 | } 70 | -------------------------------------------------------------------------------- /server/app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'), 2 | app = express(), 3 | errorHandler, 4 | http = require('http'), 5 | server = http.createServer(app), 6 | port = Number(process.env.PORT || 11000); 7 | 8 | //Catch any exceptions we might have missed 9 | process.on('uncaughtException', function(err) { 10 | console.log(err); 11 | process.exit(1); 12 | }); 13 | 14 | //set up CORS headers (dev only) and express rendering 15 | require('./setup')(app, express); 16 | 17 | //init Socket.IO and link to http server 18 | var io = require('socket.io')(server, { 19 | transports: ['websocket', 'polling-xhr', 'polling'] 20 | }); 21 | 22 | //init routes for servering initial command sender page 23 | require('./routes')(app, io, express); 24 | 25 | //set up web socket handler to receive Viz commands 26 | require('./websockets')(io); 27 | 28 | //start http server listening 29 | server.listen(port, function() { 30 | console.log('App listening on ' + port); 31 | }); 32 | -------------------------------------------------------------------------------- /server/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "proxy": "" 3 | } -------------------------------------------------------------------------------- /server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BBC_VizRT_Command_Sender_Client", 3 | "version": "0.1.0", 4 | "description": "Node.js server for BBC_VizRT_Command_Sender_Build using express and socket.io", 5 | "main": "server.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "start": "node server.js" 9 | }, 10 | "repository": "", 11 | "author": "", 12 | "license": "BSD", 13 | "dependencies": { 14 | "ejs": "~0.8.6", 15 | "express": "~3.5.0", 16 | "guid": "0.0.12", 17 | "redis": "^0.12.1", 18 | "socket.io": "^1.3.5", 19 | "socket.io-redis": "^0.1.4" 20 | }, 21 | "devDependencies": { 22 | "grunt": "~0.4.4", 23 | "grunt-contrib-jshint": "~0.10.0", 24 | "grunt-contrib-watch": "~0.6.1", 25 | "grunt-nodemon": "~0.2.1", 26 | "grunt-shell-spawn": "~0.3.0", 27 | "underscore": "^1.7.0" 28 | }, 29 | "engines": { 30 | "node": "0.12.x", 31 | "npm": "2.7.x" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /server/routes.js: -------------------------------------------------------------------------------- 1 | module.exports = function(app) { 2 | 3 | //CLIENT pages 4 | app.get('/', function(req, res) { 5 | res.render('index.html'); 6 | }); 7 | } 8 | -------------------------------------------------------------------------------- /server/setup.js: -------------------------------------------------------------------------------- 1 | module.exports = function(app, express) { 2 | 3 | //CORS - cross domain access to PUT and DELETE, send headers and respond to initial OPTIONS request with a 200 return 4 | app.use(function(req, res, next) { 5 | 6 | res.setHeader('Access-Control-Allow-Origin', '*'); 7 | res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS'); 8 | 9 | // Website you wish to allow to connect 10 | if (req.method === 'OPTIONS') { 11 | res.setHeader('Access-Control-Allow-Headers', 'Content-Type'); 12 | res.setHeader('Access-Control-Expose-Headers', 'Content-Length'); 13 | return res.send(200); 14 | } 15 | 16 | return next(); 17 | }); 18 | 19 | app.use(express.compress()); 20 | app.use(app.router); 21 | app.use(express.static(__dirname + '/public')); 22 | app.set('views', __dirname + '/public'); 23 | app.engine('html', require('ejs').renderFile); 24 | app.set('view engine', 'html'); 25 | }; 26 | -------------------------------------------------------------------------------- /server/vizmock.js: -------------------------------------------------------------------------------- 1 | var net = require("net"), 2 | port = Number(process.env.PORT || 6100); 3 | 4 | process.on('uncaughtException', function(err) { 5 | console.log(err); 6 | }); 7 | 8 | var clock; 9 | 10 | var time = 0; 11 | 12 | var relay = net.createServer(function(socket) { 13 | 14 | console.log("connected"); 15 | 16 | socket.on("data", function(data) { 17 | console.log("rendering:" + data.toString() + ":"); 18 | console.log('++++++++++++++++++++++++++++'); 19 | socket.write('1 returnvalue' + '\0'); 20 | }); 21 | 22 | socket.on("error", function(error) { 23 | 24 | console.log("error - " + error); 25 | }); 26 | 27 | socket.on("close", function(data) { 28 | 29 | console.log("closed"); 30 | socket.removeAllListeners(); 31 | }); 32 | 33 | }).listen(port, function() { 34 | console.log("Fake TCP Renderer listening on " + port); 35 | }); -------------------------------------------------------------------------------- /server/websockets/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function(io, client) { 2 | 3 | var renderers = require('./renderers')(io, client); 4 | 5 | var camelCased = function(string) { 6 | return string.replace(/-([a-z])/g, function(s) { 7 | return s[1].toUpperCase(); 8 | }); 9 | }; 10 | 11 | io.sockets.on('connection', function(socket) { 12 | socket.on('render', function(data, callback) { 13 | renderers[camelCased(data.type)](data.options, callback); 14 | }); 15 | }); 16 | }; 17 | -------------------------------------------------------------------------------- /server/websockets/renderers.js: -------------------------------------------------------------------------------- 1 | var net = require('net'); 2 | 3 | module.exports = function(io, client) { 4 | 5 | return { 6 | sendToRenderer: function(options, callback) { 7 | // console.log(options); 8 | 9 | var newSocket = net.Socket(); 10 | var returnData = ''; 11 | 12 | //console.log('RENDERING... ' + template.command + ' to ' + template.ip); 13 | 14 | newSocket.on('error', function(err) { 15 | //console.log('error... ' + err.toString()); 16 | 17 | newSocket.destroy(); 18 | newSocket = null; 19 | 20 | if (callback) { 21 | callback(new Error('render failure for ' + options.command + ' on ip ' + options.ip)); 22 | } 23 | }); 24 | 25 | newSocket.on('close', function() { 26 | //console.log('closed...'); 27 | }); 28 | 29 | newSocket.on('data', function(data) { 30 | //console.log('returning... ' + data.toString()); 31 | returnData += data.toString(); 32 | 33 | //flush any remaining data 34 | newSocket.end(); 35 | }); 36 | 37 | newSocket.on('end', function(data) { 38 | //console.log('returning... ' + returnData); 39 | //console.log('----------'); 40 | newSocket.destroy(); 41 | newSocket = null; 42 | 43 | if (callback) { 44 | callback(returnData); 45 | } 46 | }); 47 | 48 | newSocket.on('connect', function(e) { 49 | //console.log('writing...'); 50 | newSocket.write(new Buffer(options.command + '\0')); 51 | }); 52 | 53 | //console.log('connecting... ' + template.ip); 54 | newSocket.connect(6100, options.ip); 55 | } 56 | }; 57 | } 58 | --------------------------------------------------------------------------------