├── .gitignore ├── index.js ├── binding.gyp ├── package.json ├── LICENSE ├── README.md ├── examples ├── generate_noise.js ├── forwarding_capture_to_playback.js ├── generate_sine.js └── stairway_of_freq.js └── src └── jack_connector.cc /.gitignore: -------------------------------------------------------------------------------- 1 | build/* 2 | *.swp 3 | npm-debug.log 4 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./build/Release/jack_connector.node') 2 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "target_name": "jack_connector", 5 | "sources": [ "src/jack_connector.cc" ], 6 | "libraries": [ "-ljack" ] 7 | } 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jack-connector", 3 | "description": "Bindings JACK-Audio-Connection-Kit for Node.JS", 4 | "version": "0.1.4", 5 | "keywords": [ 6 | "jack", 7 | "jackd", 8 | "jack audio", 9 | "bindings", 10 | "jack audio connection kit" 11 | ], 12 | "authors": [ 13 | { 14 | "name": "Viacheslav Lotsmanov", 15 | "nickname": "unclechu", 16 | "email": "lotsmanov89@gmail.com", 17 | "url": "http://unclechumind.blogspot.com" 18 | } 19 | ], 20 | "email": "lotsmanov89@gmail.com", 21 | "license": "MIT", 22 | "main": "build/Release/jack_connector.node", 23 | "homepage": "http://github.com/unclechu/node-jack-connector", 24 | "engines": { 25 | "node": ">=0.9.0" 26 | }, 27 | "scripts": { 28 | "preinstall": "node-gyp rebuild" 29 | }, 30 | "repository": { 31 | "type": "git", 32 | "url": "http://github.com/unclechu/node-jack-connector.git" 33 | }, 34 | "bugs": { 35 | "url": "http://github.com/unclechu/node-jack-connector/issues" 36 | }, 37 | "directories": { 38 | "src": "./src" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Viacheslav Lotsmanov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Node.JS JACK-connector 2 | ====================== 3 | 4 | Bindings JACK-Audio-Connection-Kit for Node.JS 5 | 6 | Install 7 | ======= 8 | ```bash 9 | npm install jack-connector 10 | ``` 11 | 12 | Build requirements 13 | ================== 14 | libjack2, libjack2-devel 15 | 16 | How to use 17 | ========== 18 | ```javascript 19 | var jackConnector = require('jack-connector'); 20 | jackConnector.openClientSync('Noize Generator'); 21 | jackConnector.registerOutPortSync('output'); 22 | 23 | function audioProcess(err, nframes) { 24 | if (err) { 25 | console.error(err); 26 | process.exit(1); 27 | return; 28 | } 29 | 30 | var ret = []; 31 | for (var i=0; i relMax) relSrc = relMax; 27 | return ((relSrc - relMin) * (max-min) / (relMax - relMin)) + min; 28 | } 29 | 30 | function audioProcess(err, nframes) { 31 | if (err) { 32 | console.error(err); 33 | process.exit(1); 34 | return; 35 | } 36 | 37 | var ret = [], deg = 0; 38 | for (var i=0; i= step) last = 0; 40 | deg = relativeVal(last, 0, step, 0, 360); 41 | ret.push(Math.sin( deg * (Math.PI / 180) )); 42 | } 43 | return { out: ret }; 44 | } 45 | 46 | console.log('Binding audio-process callback...'); 47 | jackConnector.bindProcessSync(audioProcess); 48 | 49 | console.log('Activating JACK client...'); 50 | jackConnector.activateSync(); 51 | 52 | console.log('Auto-connecting to hardware ports...'); 53 | jackConnector.connectPortSync(jackClientName + ':out', 'system:playback_1'); 54 | jackConnector.connectPortSync(jackClientName + ':out', 'system:playback_2'); 55 | 56 | (function mainLoop() { 57 | console.log('Main loop is started.'); 58 | setTimeout(mainLoop, 1000000000); 59 | })(); 60 | 61 | process.on('SIGTERM', function () { 62 | console.log('Deactivating JACK client...'); 63 | jackConnector.deactivateSync(); 64 | console.log('Closing JACK client...'); 65 | jackConnector.closeClient(function (err) { 66 | if (err) { 67 | console.error(err); 68 | process.exit(1); 69 | return; 70 | } 71 | 72 | console.log('Exiting...'); 73 | process.exit(0); 74 | }); 75 | }); 76 | -------------------------------------------------------------------------------- /examples/stairway_of_freq.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Stairway of frequencies 5 | * 6 | * @author Viacheslav Lotsmanov 7 | */ 8 | 9 | var jackConnector = require('../index.js'); 10 | var jackClientName = 'JACK connector - stairway of frequencies'; 11 | 12 | console.log('Opening JACK client...'); 13 | jackConnector.openClientSync(jackClientName); 14 | 15 | console.log('Registering JACK ports...'); 16 | jackConnector.registerOutPortSync('out'); 17 | 18 | var sampleRate = jackConnector.getSampleRateSync(); 19 | 20 | // from 20Hz to 20kHz 21 | var freqMin = 20; 22 | var freqMax = 20000; 23 | var freqCur; 24 | var freqStep = 8; 25 | 26 | var phaseInc; // phase increment 27 | var phase = 0; 28 | 29 | if (process.argv.length < 3) { 30 | console.error( 31 | 'Please, choose OSC type by first argument:\n'+ 32 | ' 1 - sine\n'+ 33 | ' 2 - saw\n'+ 34 | ' 3 - square\n'+ 35 | ' 4 - triangle' 36 | ); 37 | process.exit(1); 38 | } 39 | 40 | var oscType; 41 | switch (process.argv[2]) { 42 | case '1': case '2': case '3': case '4': 43 | oscType = parseInt(process.argv[2], 10) - 1; 44 | break; 45 | default: 46 | throw new Error('Incorrect OSC type by first argument ("'+ 47 | process.argv[2] +'")'); 48 | } 49 | 50 | var twoPI = Math.PI * 2; 51 | 52 | var upFreqCount = 0; 53 | 54 | var upFreqSpeed = 5; // ms 55 | // transform to samples 56 | upFreqSpeed *= sampleRate; 57 | upFreqSpeed /= 1000; 58 | 59 | function updateIncrement() { 60 | phaseInc = ((freqCur * 2) * Math.PI) / sampleRate; 61 | } 62 | 63 | function setFrequency(freqVal) { 64 | freqCur = freqVal; 65 | updateIncrement(); 66 | } 67 | 68 | function incFrequency() { 69 | if (freqCur + freqStep > freqMax) freqCur = freqMin; 70 | else setFrequency(freqCur + freqStep); 71 | } 72 | 73 | function osc(nframes, upFreqAt) { // {{{1 74 | var type = oscType % 4; 75 | var buf = new Array(nframes); 76 | switch (type) { 77 | case 0: // sine 78 | for (var i=0; i -1 && i == upFreqAt) incFrequency(); 80 | buf[i] = Math.sin(phase); 81 | phase += phaseInc; 82 | while (phase >= twoPI) phase -= twoPI; 83 | } 84 | break; 85 | case 1: // saw 86 | for (var i=0; i -1 && i == upFreqAt) incFrequency(); 88 | buf[i] = 1.0 - ((2.0 * phase) / twoPI); 89 | phase += phaseInc; 90 | while (phase >= twoPI) phase -= twoPI; 91 | } 92 | break; 93 | case 2: // square 94 | for (var i=0; i -1 && i == upFreqAt) incFrequency(); 96 | if (phase <= Math.PI) buf[i] = 1.0; 97 | else buf[i] = -1.0; 98 | phase += phaseInc; 99 | while (phase >= twoPI) phase -= twoPI; 100 | } 101 | break; 102 | case 3: // triangle 103 | var val; 104 | for (var i=0; i -1 && i == upFreqAt) incFrequency(); 106 | val = -1.0 + ((2.0 * phase) / twoPI); 107 | buf[i] = 2.0 * (Math.abs(val) - 0.5); 108 | phase += phaseInc; 109 | while (phase >= twoPI) phase -= twoPI; 110 | } 111 | break; 112 | } 113 | return buf; 114 | } // osc() }}}1 115 | 116 | setFrequency(freqMin); 117 | 118 | function audioProcess(err, nframes) { 119 | if (err) { 120 | console.error(err); 121 | process.exit(1); 122 | return; 123 | } 124 | 125 | var upFreqAt = -1; 126 | upFreqCount += nframes; 127 | if (upFreqCount >= upFreqSpeed) 128 | upFreqAt = upFreqCount -= upFreqSpeed; 129 | return { out: osc(nframes, upFreqAt) }; // port name: buffer array 130 | } 131 | 132 | console.log('Binding audio-process callback...'); 133 | jackConnector.bindProcessSync(audioProcess); 134 | 135 | console.log('Activating JACK client...'); 136 | jackConnector.activateSync(); 137 | 138 | console.log('Auto-connecting to hardware ports...'); 139 | jackConnector.connectPortSync(jackClientName + ':out', 'system:playback_1'); 140 | jackConnector.connectPortSync(jackClientName + ':out', 'system:playback_2'); 141 | 142 | (function mainLoop() { 143 | console.log('Main loop is started.'); 144 | setTimeout(mainLoop, 1000000000); 145 | })(); 146 | 147 | process.on('SIGTERM', function () { 148 | console.log('Deactivating JACK client...'); 149 | jackConnector.deactivateSync(); 150 | console.log('Closing JACK client...'); 151 | jackConnector.closeClient(function (err) { 152 | if (err) { 153 | console.error(err); 154 | process.exit(1); 155 | return; 156 | } 157 | 158 | console.log('Exiting...'); 159 | process.exit(0); 160 | }); 161 | }); 162 | -------------------------------------------------------------------------------- /src/jack_connector.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * JACK Connector 3 | * Bindings JACK-Audio-Connection-Kit for Node.JS 4 | * 5 | * @author Viacheslav Lotsmanov (unclechu) 6 | * @license MIT 7 | * 8 | * The MIT License (MIT) 9 | * 10 | * Copyright (c) 2013-2014 Viacheslav Lotsmanov 11 | * 12 | * Permission is hereby granted, free of charge, to any person obtaining a copy 13 | * of this software and associated documentation files (the "Software"), to deal 14 | * in the Software without restriction, including without limitation the rights 15 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | * copies of the Software, and to permit persons to whom the Software is 17 | * furnished to do so, subject to the following conditions: 18 | * 19 | * The above copyright notice and this permission notice shall be included in 20 | * all copies or substantial portions of the Software. 21 | * 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | * THE SOFTWARE. 29 | */ 30 | 31 | #define VERSION "0.1.4" 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #define ERR_MSG_NEED_TO_OPEN_JACK_CLIENT "JACK-client is not opened, need to open JACK-client" 39 | #define THROW_ERR(Message) \ 40 | { \ 41 | ThrowException(Exception::Error(String::New(Message))); \ 42 | return scope.Close(Undefined()); \ 43 | } 44 | #define STR_SIZE 256 45 | #define MAX_PORTS 64 46 | #define NEED_JACK_CLIENT_OPENED() \ 47 | { \ 48 | if (client == 0 && !closing) \ 49 | THROW_ERR(ERR_MSG_NEED_TO_OPEN_JACK_CLIENT); \ 50 | } 51 | 52 | using namespace v8; 53 | 54 | jack_client_t *client = 0; 55 | short client_active = 0; 56 | char client_name[STR_SIZE]; 57 | 58 | char **own_in_ports; 59 | char **own_in_ports_short_names; 60 | uint8_t own_in_ports_size = 0; 61 | char **own_out_ports; 62 | char **own_out_ports_short_names; 63 | uint8_t own_out_ports_size = 0; 64 | 65 | jack_port_t *capture_ports[MAX_PORTS]; 66 | jack_port_t *playback_ports[MAX_PORTS]; 67 | jack_default_audio_sample_t *capture_buf[MAX_PORTS]; 68 | jack_default_audio_sample_t *playback_buf[MAX_PORTS]; 69 | 70 | Handle get_ports(bool withOwn, unsigned long flags); 71 | int check_port_connection(const char *src_port_name, const char *dst_port_name); 72 | bool check_port_exists(char *check_port_name, unsigned long flags); 73 | void get_own_ports(); 74 | void reset_own_ports_list(); 75 | int jack_process(jack_nframes_t nframes, void *arg); 76 | 77 | Persistent processCallback; 78 | Persistent closeCallback; 79 | bool hasProcessCallback = false; // TODO unbind process callback and check for memory leak 80 | bool hasCloseCallback = false; 81 | bool process = false; 82 | bool closing = false; 83 | uv_work_t *baton; 84 | uv_work_t *close_baton; 85 | static uv_sem_t semaphore; 86 | 87 | Handle deactivateSync(const Arguments &args); 88 | void uv_work_plug(uv_work_t* task) {} 89 | 90 | /** 91 | * Get version of this module 92 | * 93 | * @public 94 | * @returns {v8::String} version 95 | * @example 96 | * var jackConnector = require('jack-connector'); 97 | * console.log(jackConnector.getVersion()); 98 | * // string of version, see VERSION macros 99 | */ 100 | Handle getVersion(const Arguments &args) // {{{1 101 | { 102 | HandleScope scope; 103 | return scope.Close(String::New(VERSION)); 104 | } // getVersion() }}}1 105 | 106 | /** 107 | * Check JACK-client for opened status 108 | * 109 | * @public 110 | * @returns {v8::Boolean} result True - JACK-client is opened, false - JACK-client is closed 111 | * @example 112 | * var jackConnector = require('jack-connector'); 113 | * console.log(jackConnector.checkClientOpenedSync()); 114 | * // true if client opened or false if closed 115 | */ 116 | Handle checkClientOpenedSync(const Arguments &args) // {{{1 117 | { 118 | HandleScope scope; 119 | return scope.Close(Boolean::New(client != 0 && !closing)); 120 | } // checkClientOpenedSync() }}}1 121 | 122 | /** 123 | * Open JACK-client 124 | * 125 | * @public 126 | * @param {v8::String} client_name JACK-client name 127 | * @example 128 | * var jackConnector = require('jack-connector'); 129 | * jackConnector.openClientSync('JACK_connector_client_name'); 130 | */ 131 | Handle openClientSync(const Arguments &args) // {{{1 132 | { 133 | HandleScope scope; 134 | 135 | if (client != 0 || closing) 136 | THROW_ERR("You need close old JACK-client before open new"); 137 | 138 | String::AsciiValue arg_client_name(args[0]->ToString()); 139 | char *client_name = *arg_client_name; 140 | 141 | for (unsigned int i=0; ; i++) { 142 | if (client_name[i] == '\0' || i>=STR_SIZE-1) { 143 | if (i==0) { 144 | client_name[0] = '\0'; 145 | THROW_ERR("Empty JACK-client name"); 146 | } 147 | client_name[i] = '\0'; 148 | break; 149 | } 150 | 151 | ::client_name[i] = client_name[i]; 152 | } 153 | 154 | client = jack_client_open(client_name, JackNullOption, 0); 155 | if (client == 0) { 156 | client_name[0] = '\0'; 157 | ::client_name[0] = '\0'; 158 | THROW_ERR("Couldn't create JACK-client"); 159 | } 160 | 161 | jack_set_process_callback(client, jack_process, 0); 162 | process = true; 163 | 164 | return scope.Close(Undefined()); 165 | } // openClientSync() }}}1 166 | 167 | // uv_close_task() {{{1 168 | 169 | #define UV_CLOSE_TASK_CLEANUP() \ 170 | { \ 171 | scope.Close(Undefined()); \ 172 | delete task; \ 173 | close_baton = NULL; \ 174 | } 175 | #define UV_CLOSE_TASK_CLEANUP_CALLBACKS() \ 176 | { \ 177 | if (hasCloseCallback) { \ 178 | closeCallback->Call(Context::GetCurrent()->Global(), 0, NULL); \ 179 | hasCloseCallback = false; \ 180 | } \ 181 | if (hasProcessCallback) { \ 182 | hasProcessCallback = false; \ 183 | } \ 184 | } 185 | #define UV_CLOSE_TASK_STOP() \ 186 | { \ 187 | UV_CLOSE_TASK_CLEANUP(); \ 188 | UV_CLOSE_TASK_CLEANUP_CALLBACKS(); \ 189 | return; \ 190 | } 191 | #define UV_CLOSE_TASK_EXCEPTION(err) \ 192 | { \ 193 | if (hasCloseCallback) { \ 194 | const uint8_t argc = 1; \ 195 | Local argv[argc] = { \ 196 | Local::New( err ), \ 197 | }; \ 198 | closeCallback->Call(Context::GetCurrent()->Global(), argc, argv); \ 199 | hasCloseCallback = false; \ 200 | } \ 201 | UV_CLOSE_TASK_STOP(); \ 202 | } 203 | 204 | void uv_close_task(uv_work_t* task, int status) 205 | { 206 | HandleScope scope; 207 | 208 | if (baton) { 209 | UV_CLOSE_TASK_CLEANUP(); 210 | // TODO fix memory leak 211 | close_baton = new uv_work_t(); 212 | uv_queue_work(uv_default_loop(), close_baton, uv_work_plug, uv_close_task); 213 | return; 214 | } 215 | 216 | // deactivate first if client activated 217 | if (client_active) { 218 | if (jack_deactivate(client) != 0) 219 | UV_CLOSE_TASK_EXCEPTION( 220 | Exception::Error(String::New("Couldn't deactivate JACK-client"))); 221 | 222 | client_active = 0; 223 | } 224 | 225 | if (jack_client_close(client) != 0) 226 | UV_CLOSE_TASK_EXCEPTION( 227 | Exception::Error(String::New("Couldn't close JACK-client"))); 228 | 229 | client = 0; 230 | 231 | UV_CLOSE_TASK_CLEANUP_CALLBACKS(); 232 | 233 | // TODO cleanup stuff 234 | 235 | closing = false; 236 | 237 | scope.Close(Undefined()); 238 | delete task; 239 | close_baton = NULL; 240 | } // uv_close_task() }}}1 241 | 242 | /** 243 | * Close JACK-client 244 | * 245 | * @public 246 | * @example 247 | * var jackConnector = require('jack-connector'); 248 | * jackConnector.openClientSync('JACK_connector_client_name'); 249 | * jackConnector.closeClient(function () { 250 | * console.log('client closed'); 251 | * }); 252 | * @async 253 | * @TODO free jack ports 254 | */ 255 | Handle closeClient(const Arguments &args) // {{{1 256 | { 257 | HandleScope scope; 258 | 259 | if (closing) { 260 | THROW_ERR("Already started closing JACK-client"); 261 | } else { 262 | closing = true; 263 | } 264 | 265 | if (client == 0) THROW_ERR("JACK-client already closed"); 266 | 267 | process = false; 268 | 269 | if (args[0]->IsFunction()) { 270 | Local callback = Local::Cast( args[0] ); 271 | closeCallback = Persistent::New( callback ); 272 | hasCloseCallback = true; 273 | } 274 | 275 | close_baton = new uv_work_t(); 276 | uv_queue_work(uv_default_loop(), close_baton, uv_work_plug, uv_close_task); 277 | 278 | return scope.Close(Undefined()); 279 | } // closeClient() }}}1 280 | 281 | /** 282 | * Register new port for this client 283 | * 284 | * @public 285 | * @param {v8::String} port_name Full port name 286 | * @param {v8::Integer} port_type See: enum jack_flags 287 | * @example 288 | * var jackConnector = require('jack-connector'); 289 | * jackConnector.openClientSync('JACK_connector_client_name'); 290 | * jackConnector.registerInPortSync('in_1'); 291 | * jackConnector.registerInPortSync('in_2'); 292 | */ 293 | Handle registerInPortSync(const Arguments &args) // {{{1 294 | { 295 | HandleScope scope; 296 | NEED_JACK_CLIENT_OPENED(); 297 | 298 | String::AsciiValue port_name(args[0]->ToString()); 299 | 300 | capture_ports[own_in_ports_size] = jack_port_register( 301 | client, 302 | *port_name, 303 | JACK_DEFAULT_AUDIO_TYPE, 304 | JackPortIsInput, 305 | 0 306 | ); 307 | 308 | reset_own_ports_list(); 309 | 310 | return scope.Close(Undefined()); 311 | } // registerInPortSync() }}}1 312 | 313 | /** 314 | * Register new port for this client 315 | * 316 | * @public 317 | * @param {v8::String} port_name Full port name 318 | * @example 319 | * var jackConnector = require('jack-connector'); 320 | * jackConnector.openClientSync('JACK_connector_client_name'); 321 | * jackConnector.registerOutPortSync('out_1'); 322 | * jackConnector.registerOutPortSync('out_2'); 323 | */ 324 | Handle registerOutPortSync(const Arguments &args) // {{{1 325 | { 326 | HandleScope scope; 327 | NEED_JACK_CLIENT_OPENED(); 328 | 329 | String::AsciiValue port_name(args[0]->ToString()); 330 | 331 | playback_ports[own_out_ports_size] = jack_port_register( 332 | client, 333 | *port_name, 334 | JACK_DEFAULT_AUDIO_TYPE, 335 | JackPortIsOutput, 336 | 0 337 | ); 338 | 339 | reset_own_ports_list(); 340 | 341 | return scope.Close(Undefined()); 342 | } // registerOutPortSync() }}}1 343 | 344 | /** 345 | * Unregister port for this client 346 | * 347 | * @public 348 | * @param {v8::String} port_name Full port name 349 | * @example 350 | * var jackConnector = require('jack-connector'); 351 | * jackConnector.openClientSync('JACK_connector_client_name'); 352 | * jackConnector.registerOutPortSync('out_1'); 353 | * jackConnector.registerOutPortSync('out_2'); 354 | * jackConnector.unregisterPortSync('out_1'); 355 | * jackConnector.unregisterPortSync('out_2'); 356 | * @TODO deactivating (for stop processing before update ports list) 357 | * @TODO remove port from ports list 358 | */ 359 | Handle unregisterPortSync(const Arguments &args) // {{{1 360 | { 361 | HandleScope scope; 362 | NEED_JACK_CLIENT_OPENED(); 363 | 364 | String::AsciiValue arg_port_name(args[0]->ToString()); 365 | char full_port_name[STR_SIZE]; 366 | char *port_name = *arg_port_name; 367 | 368 | for (int i=0, n=0, m=0; ; i++, m++) { 369 | if (n == 0) { 370 | if (::client_name[m] == '\0') { 371 | full_port_name[i] = ':'; 372 | m = -1; 373 | n = 1; 374 | } else { 375 | full_port_name[i] = ::client_name[m]; 376 | } 377 | } else { 378 | if (port_name[m] == '\0') { 379 | full_port_name[i] = '\0'; 380 | break; 381 | } else { 382 | full_port_name[i] = port_name[m]; 383 | } 384 | } 385 | } 386 | 387 | jack_port_t *port = jack_port_by_name(client, full_port_name); 388 | 389 | if (jack_port_unregister(client, port) != 0) 390 | THROW_ERR("Couldn't unregister JACK-port"); 391 | 392 | // ..... 393 | 394 | reset_own_ports_list(); 395 | 396 | return scope.Close(Undefined()); 397 | } // unregisterPortSync() }}}1 398 | 399 | /** 400 | * Check JACK-client for active 401 | * 402 | * @public 403 | * @example 404 | * var jackConnector = require('jack-connector'); 405 | * if (jackConnector.checkActiveSync()) 406 | * console.log('JACK-client is active'); 407 | * else 408 | * console.log('JACK-client is not active'); 409 | * @returns {v8::Boolean} result True - client is active, false - client is not active 410 | */ 411 | Handle checkActiveSync(const Arguments &args) // {{{1 412 | { 413 | HandleScope scope; 414 | NEED_JACK_CLIENT_OPENED(); 415 | 416 | if (::client_active > 0) { 417 | return scope.Close(Boolean::New(true)); 418 | } else { 419 | return scope.Close(Boolean::New(false)); 420 | } 421 | } // checkActiveSync() }}}1 422 | 423 | /** 424 | * Activate JACK-client 425 | * 426 | * @public 427 | * @example 428 | * var jackConnector = require('jack-connector'); 429 | * jackConnector.openClientSync('JACK_connector_client_name'); 430 | * jackConnector.activateSync(); 431 | */ 432 | Handle activateSync(const Arguments &args) // {{{1 433 | { 434 | HandleScope scope; 435 | NEED_JACK_CLIENT_OPENED(); 436 | 437 | if (client_active) THROW_ERR("JACK-client already activated"); 438 | 439 | if (jack_activate(client) != 0) THROW_ERR("Couldn't activate JACK-client"); 440 | 441 | client_active = 1; 442 | 443 | return scope.Close(Undefined()); 444 | } // activateSync() }}}1 445 | 446 | /** 447 | * Deactivate JACK-client 448 | * 449 | * @public 450 | * @example 451 | * var jackConnector = require('jack-connector'); 452 | * jackConnector.openClientSync('JACK_connector_client_name'); 453 | * jackConnector.activateSync(); 454 | * jackConnector.deactivateSync(); 455 | */ 456 | Handle deactivateSync(const Arguments &args) // {{{1 457 | { 458 | HandleScope scope; 459 | NEED_JACK_CLIENT_OPENED(); 460 | 461 | if (! client_active) THROW_ERR("JACK-client is not active"); 462 | 463 | if (jack_deactivate(client) != 0) THROW_ERR("Couldn't deactivate JACK-client"); 464 | 465 | client_active = 0; 466 | 467 | return scope.Close(Undefined()); 468 | } // deactivateSync() }}}1 469 | 470 | /** 471 | * Connect port to port 472 | * 473 | * @public 474 | * @param {v8::String} sourcePort Full name of source port 475 | * @param {v8::String} destinationPort Full name of destination port 476 | * @example 477 | * var jackConnector = require('jack-connector'); 478 | * jackConnector.openClientSync('JACK_connector_client_name'); 479 | * jackConnector.activateSync(); 480 | * jackConnector.connectPortSync('system:capture_1', 'system:playback_1'); 481 | */ 482 | Handle connectPortSync(const Arguments &args) // {{{1 483 | { 484 | HandleScope scope; 485 | NEED_JACK_CLIENT_OPENED(); 486 | 487 | if (! client_active) THROW_ERR("JACK-client is not active"); 488 | 489 | String::AsciiValue src_port_name(args[0]->ToString()); 490 | jack_port_t *src_port = jack_port_by_name(client, *src_port_name); 491 | if (! src_port) THROW_ERR("Non existing source port"); 492 | 493 | String::AsciiValue dst_port_name(args[1]->ToString()); 494 | jack_port_t *dst_port = jack_port_by_name(client, *dst_port_name); 495 | if (! dst_port) THROW_ERR("Non existing destination port"); 496 | 497 | if (! client_active 498 | && (jack_port_is_mine(client, src_port) || jack_port_is_mine(client, dst_port))) { 499 | THROW_ERR("Jack client must be activated to connect own ports"); 500 | } 501 | 502 | int error = jack_connect(client, *src_port_name, *dst_port_name); 503 | if (error != 0 && error != EEXIST) THROW_ERR("Failed to connect ports"); 504 | 505 | return scope.Close(Undefined()); 506 | } // connectPortSync() }}}1 507 | 508 | /** 509 | * Disconnect ports 510 | * 511 | * @public 512 | * @param {v8::String} sourcePort Full name of source port 513 | * @param {v8::String} destinationPort Full name of destination port 514 | * @example 515 | * var jackConnector = require('jack-connector'); 516 | * jackConnector.openClientSync('JACK_connector_client_name'); 517 | * jackConnector.activateSync(); 518 | * jackConnector.disconnectPortSync('system:capture_1', 'system:playback_1'); 519 | */ 520 | Handle disconnectPortSync(const Arguments &args) // {{{1 521 | { 522 | HandleScope scope; 523 | NEED_JACK_CLIENT_OPENED(); 524 | 525 | if (! client_active) THROW_ERR("JACK-client is not active"); 526 | 527 | String::AsciiValue src_port_name(args[0]->ToString()); 528 | jack_port_t *src_port = jack_port_by_name(client, *src_port_name); 529 | if (! src_port) THROW_ERR("Non existing source port"); 530 | 531 | String::AsciiValue dst_port_name(args[1]->ToString()); 532 | jack_port_t *dst_port = jack_port_by_name(client, *dst_port_name); 533 | if (! dst_port) THROW_ERR("Non existing destination port"); 534 | 535 | if (check_port_connection(*src_port_name, *dst_port_name)) { 536 | if (jack_disconnect(client, *src_port_name, *dst_port_name)) 537 | THROW_ERR("Failed to disconnect ports"); 538 | } 539 | 540 | return scope.Close(Undefined()); 541 | } // disconnectPortSync() }}}1 542 | 543 | /** 544 | * Get all JACK-ports list 545 | * 546 | * @public 547 | * @param {v8::Boolean} [withOwn] Default: true 548 | * @returns {v8::Array} allPortsList Array of full ports names strings 549 | * @example 550 | * var jackConnector = require('jack-connector'); 551 | * jackConnector.openClientSync('JACK_connector_client_name'); 552 | * console.log(jackConnector.getAllPortsSync()); 553 | * // prints: [ "system:playback_1", "system:playback_2", 554 | * // "system:capture_1", "system:capture_2" ] 555 | */ 556 | Handle getAllPortsSync(const Arguments &args) // {{{1 557 | { 558 | HandleScope scope; 559 | NEED_JACK_CLIENT_OPENED(); 560 | 561 | bool withOwn = true; 562 | if (args.Length() > 0 && (args[0]->IsBoolean() || args[0]->IsNumber())) { 563 | withOwn = args[0]->ToBoolean()->BooleanValue(); 564 | } 565 | 566 | Handle allPortsList = get_ports(withOwn, 0); 567 | 568 | return scope.Close(allPortsList); 569 | } // getAllPortsSync() }}}1 570 | 571 | /** 572 | * Get output JACK-ports list 573 | * 574 | * @public 575 | * @param {v8::Boolean} [withOwn] Default: true 576 | * @returns {v8::Array} outPortsList Array of full ports names strings 577 | * @example 578 | * var jackConnector = require('jack-connector'); 579 | * jackConnector.openClientSync('JACK_connector_client_name'); 580 | * console.log(jackConnector.getOutPortsSync()); 581 | * // prints: [ "system:capture_1", "system:capture_2" ] 582 | */ 583 | Handle getOutPortsSync(const Arguments &args) // {{{1 584 | { 585 | HandleScope scope; 586 | NEED_JACK_CLIENT_OPENED(); 587 | 588 | bool withOwn = true; 589 | if (args.Length() > 0 && (args[0]->IsBoolean() || args[0]->IsNumber())) { 590 | withOwn = args[0]->ToBoolean()->BooleanValue(); 591 | } 592 | 593 | Handle outPortsList = get_ports(withOwn, JackPortIsOutput); 594 | 595 | return scope.Close(outPortsList); 596 | } // getOutPortsSync() }}}1 597 | 598 | /** 599 | * Get input JACK-ports list 600 | * 601 | * @public 602 | * @param {v8::Boolean} [withOwn] Default: true 603 | * @returns {v8::Array} inPortsList Array of full ports names strings 604 | * @example 605 | * var jackConnector = require('jack-connector'); 606 | * jackConnector.openClientSync('JACK_connector_client_name'); 607 | * console.log(jackConnector.getInPortsSync()); 608 | * // prints: [ "system:playback_1", "system:playback_2" ] 609 | */ 610 | Handle getInPortsSync(const Arguments &args) // {{{1 611 | { 612 | HandleScope scope; 613 | NEED_JACK_CLIENT_OPENED(); 614 | 615 | bool withOwn = true; 616 | if (args.Length() > 0 && (args[0]->IsBoolean() || args[0]->IsNumber())) { 617 | withOwn = args[0]->ToBoolean()->BooleanValue(); 618 | } 619 | 620 | Handle inPortsList = get_ports(withOwn, JackPortIsInput); 621 | 622 | return scope.Close(inPortsList); 623 | } // getInPortsSync() }}}1 624 | 625 | /** 626 | * Check port for exists by full port name 627 | * 628 | * @public 629 | * @param {v8::String} checkPortName Full port name to check for exists 630 | * @example 631 | * var jackConnector = require('jack-connector'); 632 | * jackConnector.openClientSync('JACK_connector_client_name'); 633 | * console.log(jackConnector.portExistsSync('system:playback_1')); 634 | * // true 635 | * console.log(jackConnector.portExistsSync('nowhere:never')); 636 | * // false 637 | * @returns {v8::Boolean} portExists 638 | */ 639 | Handle portExistsSync(const Arguments &args) // {{{1 640 | { 641 | HandleScope scope; 642 | NEED_JACK_CLIENT_OPENED(); 643 | 644 | String::AsciiValue checkPortName_arg(args[0]->ToString()); 645 | char *checkPortName = *checkPortName_arg; 646 | 647 | return scope.Close(Boolean::New(check_port_exists(checkPortName, 0))); 648 | } // portExistsSync() }}}1 649 | 650 | /** 651 | * Check output port for exists by full port name 652 | * 653 | * @public 654 | * @param {v8::String} checkPortName Full port name to check for exists 655 | * @example 656 | * var jackConnector = require('jack-connector'); 657 | * jackConnector.openClientSync('JACK_connector_client_name'); 658 | * console.log(jackConnector.outPortExistsSync('system:playback_1')); 659 | * // false 660 | * console.log(jackConnector.outPortExistsSync('system:capture_1')); 661 | * // true 662 | * @returns {v8::Boolean} outPortExists 663 | */ 664 | Handle outPortExistsSync(const Arguments &args) // {{{1 665 | { 666 | HandleScope scope; 667 | NEED_JACK_CLIENT_OPENED(); 668 | 669 | String::AsciiValue checkPortName_arg(args[0]->ToString()); 670 | char *checkPortName = *checkPortName_arg; 671 | 672 | return scope.Close(Boolean::New(check_port_exists(checkPortName, JackPortIsOutput))); 673 | } // outPortExistsSync() }}}1 674 | 675 | /** 676 | * Check input port for exists by full port name 677 | * 678 | * @public 679 | * @param {v8::String} checkPortName Full port name to check for exists 680 | * @example 681 | * var jackConnector = require('jack-connector'); 682 | * jackConnector.openClientSync('JACK_connector_client_name'); 683 | * console.log(jackConnector.inPortExistsSync('system:playback_1')); 684 | * // true 685 | * console.log(jackConnector.inPortExistsSync('system:capture_1')); 686 | * // false 687 | * @returns {v8::Boolean} inPortExists 688 | */ 689 | Handle inPortExistsSync(const Arguments &args) // {{{1 690 | { 691 | HandleScope scope; 692 | NEED_JACK_CLIENT_OPENED(); 693 | 694 | String::AsciiValue checkPortName_arg(args[0]->ToString()); 695 | char *checkPortName = *checkPortName_arg; 696 | 697 | return scope.Close(Boolean::New(check_port_exists(checkPortName, JackPortIsInput))); 698 | } // inPortExistsSync() }}}1 699 | 700 | /** 701 | * Bind callback for JACK process 702 | * 703 | * @public 704 | * @param {v8::Function} callback 705 | * @example 706 | * var jackConnector = require('jack-connector'); 707 | * jackConnector.openClientSync('JACK_connector_client_name'); 708 | * jackConnector.registerOutPortSync('output'); 709 | * function process(nframes, playback, capture) { 710 | * for (var i=0; i bindProcessSync(const Arguments &args) // {{{1 717 | { 718 | HandleScope scope; 719 | NEED_JACK_CLIENT_OPENED(); 720 | 721 | if ( ! args[0]->IsFunction()) { 722 | ThrowException(Exception::TypeError(String::New("Callback argument must be a function"))); 723 | return scope.Close(Undefined()); 724 | } 725 | 726 | Local callback = Local::Cast( args[0] ); 727 | processCallback = Persistent::New( callback ); 728 | hasProcessCallback = true; 729 | 730 | return scope.Close(Undefined()); 731 | } // bindProcessSync() }}}1 732 | 733 | 734 | /* System functions */ 735 | 736 | /** 737 | * Get JACK-ports 738 | * 739 | * @private 740 | * @param {bool} withOwn Get ports of this client too 741 | * @param {unsigned long} flags Sum of ports filter 742 | * @returns {v8::Array} allPortsList Array of full ports names strings 743 | * @example Handle portsList = get_ports(true, 0); 744 | * @example Handle outPortsList = get_ports(false, JackPortIsOutput); 745 | */ 746 | Handle get_ports(bool withOwn, unsigned long flags) // {{{1 747 | { 748 | unsigned int ports_count = 0; 749 | const char** jack_ports_list; 750 | jack_ports_list = jack_get_ports(::client, NULL, NULL, flags); 751 | while (jack_ports_list[ports_count]) ports_count++; 752 | 753 | unsigned int parsed_ports_count = 0; 754 | if (withOwn) { 755 | parsed_ports_count = ports_count; 756 | } else { 757 | for (unsigned int i=0; i=STR_SIZE-1) { 760 | parsed_ports_count++; 761 | break; 762 | } 763 | 764 | if (client_name[n] == '\0' && jack_ports_list[i][n] == ':') { 765 | break; 766 | } 767 | 768 | if (client_name[n] != jack_ports_list[i][n]) { 769 | parsed_ports_count++; 770 | break; 771 | } 772 | } 773 | } 774 | } 775 | 776 | Local allPortsList; 777 | if (withOwn) { 778 | allPortsList = Array::New(ports_count); 779 | for (unsigned int i=0; iSet(i, String::NewSymbol(jack_ports_list[i])); 781 | } 782 | } else { 783 | allPortsList = Array::New(parsed_ports_count); 784 | for (unsigned int i=0; i=STR_SIZE-1) { 787 | allPortsList->Set(i, String::NewSymbol(jack_ports_list[i])); 788 | break; 789 | } 790 | 791 | if (client_name[n] == '\0' && jack_ports_list[i][n] == ':') { 792 | break; 793 | } 794 | 795 | if (client_name[n] != jack_ports_list[i][n]) { 796 | allPortsList->Set(i, String::NewSymbol(jack_ports_list[i])); 797 | break; 798 | } 799 | } 800 | } 801 | } 802 | 803 | delete jack_ports_list; 804 | return allPortsList; 805 | } // get_ports() }}}1 806 | 807 | typedef struct get_own_ports_retval_t { 808 | char** names; 809 | char** own_names; // without client name 810 | uint8_t count; 811 | }; 812 | 813 | char* get_port_name_without_client_name(char* port_name) // {{{1 814 | { 815 | char* retval = new char[STR_SIZE]; 816 | uint16_t i=0, n=0; 817 | for (i=0; i= MAX_PORTS) break; 843 | uint8_t found = 1; 844 | for (n=0; ; n++) { 845 | if (n>=STR_SIZE-1) { found = 0; break; } 846 | if (client_name[n] == '\0' && jack_ports_list[i][n] == ':') { break; } 847 | if (client_name[n] != jack_ports_list[i][n]) { found = 0; break; } 848 | } 849 | if (found == 1) { 850 | ports_namesTmp[m] = new char[STR_SIZE]; 851 | for (n=0; n portsList = get_ports(true, flags); 958 | for (uint8_t i=0; iLength(); i++) { 959 | String::AsciiValue port_name_arg(portsList->Get(i)->ToString()); 960 | char *port_name = *port_name_arg; 961 | 962 | for (uint16_t n=0; ; n++) { 963 | if (port_name[n] == '\0' || check_port_name[n] == '\0' || n>=STR_SIZE-1) { 964 | if (port_name[n] == check_port_name[n]) { 965 | return true; 966 | } else { 967 | break; 968 | } 969 | } else if (port_name[n] != check_port_name[n]) { 970 | break; 971 | } 972 | } 973 | } 974 | return false; 975 | } // check_port_exists() }}}1 976 | 977 | /** 978 | * Get own output port index 979 | * 980 | * @param {char} short_port_name - Own port name without client name 981 | * @private 982 | * @returns {int16_t} port_index - Port index or -1 if not found 983 | */ 984 | int16_t get_own_out_port_index(char* short_port_name) // {{{1 985 | { 986 | for (uint8_t n=0; n argv[argc] = { \ 1020 | Local::New( err ), \ 1021 | }; \ 1022 | processCallback->Call(Context::GetCurrent()->Global(), argc, argv); \ 1023 | UV_PROCESS_STOP(); \ 1024 | } 1025 | 1026 | void uv_process(uv_work_t* task, int status) // {{{2 1027 | { 1028 | HandleScope scope; 1029 | 1030 | uint16_t nframes = *((uint16_t*)(&task->data)); 1031 | 1032 | Local capture = Object::New(); 1033 | for (uint8_t i=0; i portBuf = Array::New(nframes); 1035 | for (uint16_t n=0; n sample = Number::New( capture_buf[i][n] ); 1037 | portBuf->Set(n, sample); 1038 | } 1039 | capture->Set( 1040 | String::NewSymbol(own_in_ports_short_names[i]), 1041 | portBuf 1042 | ); 1043 | } 1044 | 1045 | const uint8_t argc = 3; 1046 | Local argv[argc] = { 1047 | Local::New( Null() ), 1048 | Local::New( Number::New( nframes ) ), 1049 | Local::New( capture ) 1050 | }; 1051 | Local retval = 1052 | processCallback->Call(Context::GetCurrent()->Global(), argc, argv); 1053 | 1054 | if (!retval->IsNull() && !retval->IsUndefined() && !retval->IsObject()) { 1055 | UV_PROCESS_EXCEPTION( 1056 | Exception::TypeError(String::New( 1057 | "Returned value of \"process\" callback must be an object" 1058 | " of port{String}:buffer{Array.} values" 1059 | " or null or undefined")) 1060 | ); 1061 | } 1062 | 1063 | if (retval->IsObject()) { 1064 | Local obj = retval.As(); 1065 | Local keys = obj->GetOwnPropertyNames(); 1066 | for (uint16_t i=0; iLength(); i++) { 1067 | Local key = keys->Get(i); 1068 | if (!key->IsString()) { 1069 | UV_PROCESS_EXCEPTION( 1070 | Exception::TypeError(String::New( 1071 | "Incorrect key type in returned value of \"process\"" 1072 | " callback, must be a string (own port name)")) 1073 | ); 1074 | } 1075 | String::AsciiValue port_name(key->ToString()); 1076 | 1077 | int16_t port_index = get_own_out_port_index(*port_name); 1078 | if (port_index == -1) { 1079 | char err[] = "Port \"%s\" not found"; 1080 | char err_msg[STR_SIZE + sizeof(err)]; 1081 | sprintf(err_msg, err, *port_name); 1082 | UV_PROCESS_EXCEPTION(Exception::Error(String::New(err_msg))); 1083 | } 1084 | 1085 | Local val = obj->Get(key); 1086 | if (!val->IsArray()) { 1087 | UV_PROCESS_EXCEPTION( 1088 | Exception::TypeError(String::New( 1089 | "Incorrect buffer type of returned value of \"process\"" 1090 | " callback, must be an Array")) 1091 | ); 1092 | } 1093 | Local buffer = val.As(); 1094 | 1095 | if (buffer->Length() != nframes) { 1096 | UV_PROCESS_EXCEPTION( 1097 | Exception::RangeError(String::New( 1098 | "Incorrect buffer size of returned value" 1099 | " of \"process\" callback")) 1100 | ); 1101 | } 1102 | 1103 | for (uint16_t sample_i=0; sample_i sample = buffer->Get(sample_i); 1105 | if (!sample->IsNumber()) { 1106 | UV_PROCESS_EXCEPTION( 1107 | Exception::TypeError(String::New( 1108 | "Incorrect sample type of returned value" 1109 | " of \"process\" callback" 1110 | ", must be a {Number|Float}")) 1111 | ); 1112 | } 1113 | playback_buf[port_index][sample_i] = sample->ToNumber()->Value(); 1114 | } 1115 | } // for (ports) 1116 | } // if we has something to output from callback 1117 | 1118 | UV_PROCESS_STOP(); 1119 | } // uv_process() }}}2 1120 | 1121 | int jack_process(jack_nframes_t nframes, void *arg) // {{{2 1122 | { 1123 | if (!process) return 0; 1124 | if (!hasProcessCallback) return 0; 1125 | 1126 | if (baton) { 1127 | uv_sem_wait(&semaphore); 1128 | uv_sem_destroy(&semaphore); 1129 | } 1130 | 1131 | baton = new uv_work_t(); 1132 | 1133 | if (uv_sem_init(&semaphore, 0) < 0) { perror("uv_sem_init"); return 1; } 1134 | 1135 | for (uint8_t i=0; idata = (void*)(uint16_t)nframes; 1146 | uv_queue_work(uv_default_loop(), baton, uv_work_plug, uv_process); 1147 | uv_sem_wait(&semaphore); 1148 | uv_sem_destroy(&semaphore); 1149 | 1150 | return 0; 1151 | } // jack_process() }}}2 1152 | 1153 | // processing }}}1 1154 | 1155 | /** 1156 | * Get JACK sample rate 1157 | * 1158 | * @public 1159 | * @returns {v8::Number} sampleRate 1160 | * @example 1161 | * var jackConnector = require('jack-connector'); 1162 | * jackConnector.openClientSync('jack_client_name'); 1163 | * console.log( jackConnector.getSampleRateSync() ); 1164 | */ 1165 | Handle getSampleRateSync(const Arguments &args) // {{{1 1166 | { 1167 | HandleScope scope; 1168 | NEED_JACK_CLIENT_OPENED(); 1169 | Local val = Local::New( 1170 | Number::New( jack_get_sample_rate(client) ) 1171 | ); 1172 | return scope.Close(val); 1173 | } // getSampleRateSync() }}}1 1174 | 1175 | /** 1176 | * Get JACK buffer size 1177 | * 1178 | * @public 1179 | * @returns {v8::Number} bufferSize 1180 | * @example 1181 | * var jackConnector = require('jack-connector'); 1182 | * jackConnector.openClientSync('jack_client_name'); 1183 | * console.log( jackConnector.getBufferSizeSync() ); 1184 | */ 1185 | Handle getBufferSizeSync(const Arguments &args) // {{{1 1186 | { 1187 | HandleScope scope; 1188 | NEED_JACK_CLIENT_OPENED(); 1189 | Local val = Local::New( 1190 | Number::New( jack_get_buffer_size(client) ) 1191 | ); 1192 | return scope.Close(val); 1193 | } // getBufferSizeSync() }}}1 1194 | 1195 | void init(Handle target) // {{{1 1196 | { 1197 | 1198 | target->Set( String::NewSymbol("getVersion"), 1199 | FunctionTemplate::New(getVersion)->GetFunction() ); 1200 | 1201 | // client init 1202 | 1203 | target->Set( String::NewSymbol("checkClientOpenedSync"), 1204 | FunctionTemplate::New(checkClientOpenedSync)->GetFunction() ); 1205 | 1206 | target->Set( String::NewSymbol("openClientSync"), 1207 | FunctionTemplate::New(openClientSync)->GetFunction() ); 1208 | 1209 | target->Set( String::NewSymbol("closeClient"), 1210 | FunctionTemplate::New(closeClient)->GetFunction() ); 1211 | 1212 | // registering ports 1213 | 1214 | target->Set( String::NewSymbol("registerInPortSync"), 1215 | FunctionTemplate::New(registerInPortSync)->GetFunction() ); 1216 | 1217 | target->Set( String::NewSymbol("registerOutPortSync"), 1218 | FunctionTemplate::New(registerOutPortSync)->GetFunction() ); 1219 | 1220 | target->Set( String::NewSymbol("unregisterPortSync"), 1221 | FunctionTemplate::New(unregisterPortSync)->GetFunction() ); 1222 | 1223 | // port connections 1224 | 1225 | target->Set( String::NewSymbol("connectPortSync"), 1226 | FunctionTemplate::New(connectPortSync)->GetFunction() ); 1227 | 1228 | target->Set( String::NewSymbol("disconnectPortSync"), 1229 | FunctionTemplate::New(disconnectPortSync)->GetFunction() ); 1230 | 1231 | // get ports 1232 | 1233 | target->Set( String::NewSymbol("getAllPortsSync"), 1234 | FunctionTemplate::New(getAllPortsSync)->GetFunction() ); 1235 | 1236 | target->Set( String::NewSymbol("getOutPortsSync"), 1237 | FunctionTemplate::New(getOutPortsSync)->GetFunction() ); 1238 | 1239 | target->Set( String::NewSymbol("getInPortsSync"), 1240 | FunctionTemplate::New(getInPortsSync)->GetFunction() ); 1241 | 1242 | // port exists 1243 | 1244 | target->Set( String::NewSymbol("portExistsSync"), 1245 | FunctionTemplate::New(portExistsSync)->GetFunction() ); 1246 | 1247 | target->Set( String::NewSymbol("outPortExistsSync"), 1248 | FunctionTemplate::New(outPortExistsSync)->GetFunction() ); 1249 | 1250 | target->Set( String::NewSymbol("inPortExistsSync"), 1251 | FunctionTemplate::New(inPortExistsSync)->GetFunction() ); 1252 | 1253 | // sound process 1254 | 1255 | target->Set( String::NewSymbol("bindProcessSync"), 1256 | FunctionTemplate::New(bindProcessSync)->GetFunction() ); 1257 | 1258 | // activating client 1259 | 1260 | target->Set( String::NewSymbol("checkActiveSync"), 1261 | FunctionTemplate::New(checkActiveSync)->GetFunction() ); 1262 | 1263 | target->Set( String::NewSymbol("activateSync"), 1264 | FunctionTemplate::New(activateSync)->GetFunction() ); 1265 | 1266 | target->Set( String::NewSymbol("deactivateSync"), 1267 | FunctionTemplate::New(deactivateSync)->GetFunction() ); 1268 | 1269 | // get some jack info 1270 | 1271 | target->Set( String::NewSymbol("getSampleRateSync"), 1272 | FunctionTemplate::New(getSampleRateSync)->GetFunction() ); 1273 | 1274 | target->Set( String::NewSymbol("getBufferSizeSync"), 1275 | FunctionTemplate::New(getBufferSizeSync)->GetFunction() ); 1276 | 1277 | } // init() }}}1 1278 | 1279 | NODE_MODULE(jack_connector, init); 1280 | 1281 | // vim:set ts=4 sts=4 sw=4 et: 1282 | --------------------------------------------------------------------------------