diff --git a/.gitignore b/.gitignore index c795b05..e3fbd98 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -build \ No newline at end of file +build +node_modules diff --git a/examples/play_ffmpeg.js b/examples/play_ffmpeg.js index 19c6ddf..5753b6a 100644 --- a/examples/play_ffmpeg.js +++ b/examples/play_ffmpeg.js @@ -2,10 +2,10 @@ var airtunes = require('../lib/'), spawn = require('child_process').spawn, argv = require('optimist') .usage('Usage: $0 --host [host] --port [num] --ffmpeg [path] --file [path] --volume [num] --password [string]') - .default('port', 5000) + .default('port', 5002) .default('volume', 50) .default('ffmpeg', '/usr/local/bin/ffmpeg') - .default('file', './sample.mp3') + .default('file', './wakeup.mp3') .demand(['host']) .argv; diff --git a/examples/sample.mp3 b/examples/sample.mp3 deleted file mode 100644 index 5460855..0000000 Binary files a/examples/sample.mp3 and /dev/null differ diff --git a/examples/wakeup.mp3 b/examples/wakeup.mp3 new file mode 100644 index 0000000..9327319 Binary files /dev/null and b/examples/wakeup.mp3 differ diff --git a/lib/audio_out.js b/lib/audio_out.js index fbfa818..e127b24 100644 --- a/lib/audio_out.js +++ b/lib/audio_out.js @@ -1,8 +1,7 @@ var events = require('events'), util = require('util'), config = require('./config.js'), - nu = require('./num_util.js'), - circularBuffer = require('./circular_buffer.js'); + nu = require('./num_util.js'); function AudioOut() { events.EventEmitter.call(this); @@ -13,7 +12,7 @@ function AudioOut() { util.inherits(AudioOut, events.EventEmitter); -AudioOut.prototype.init = function(devices) { +AudioOut.prototype.init = function(devices, circularBuffer) { var self = this; config.rtp_time_ref = new Date().getTime(); @@ -34,7 +33,7 @@ AudioOut.prototype.init = function(devices) { if(self.hasAirTunes && seq % config.sync_period == 0) self.emit('need_sync', seq); - + self.emit('packet', packet); packet.release(); } @@ -65,4 +64,4 @@ AudioOut.prototype.init = function(devices) { syncAudio(); } -module.exports = new AudioOut(); +module.exports = AudioOut; \ No newline at end of file diff --git a/lib/circular_buffer.js b/lib/circular_buffer.js index b28b20c..94cc2c5 100644 --- a/lib/circular_buffer.js +++ b/lib/circular_buffer.js @@ -1,7 +1,6 @@ var Stream = require('stream'), util = require('util'), - config = require('./config.js'), - packetPool = require('./packet_pool.js'); + PacketPool = require('./packet_pool.js'); var WAITING = 0, FILLING = 1, @@ -13,6 +12,7 @@ var WAITING = 0, function CircularBuffer(packetsInBuffer, packetSize) { Stream.call(this); + this.packetPool = new PacketPool(); this.maxSize = packetsInBuffer*packetSize; this.packetSize = packetSize; this.writable = true; @@ -51,7 +51,7 @@ CircularBuffer.prototype.write = function(chunk) { }; CircularBuffer.prototype.readPacket = function() { - var packet = packetPool.getPacket(); + var packet = this.packetPool.getPacket(); // play silence until buffer is filled enough if(this.status !== ENDING && this.status !== ENDED && @@ -127,4 +127,4 @@ CircularBuffer.prototype.reset = function() { this.status = WAITING; }; -module.exports = new CircularBuffer(config.packets_in_buffer, config.packet_size); \ No newline at end of file +module.exports = CircularBuffer; \ No newline at end of file diff --git a/lib/device_airtunes.js b/lib/device_airtunes.js index 571b871..23d85a9 100644 --- a/lib/device_airtunes.js +++ b/lib/device_airtunes.js @@ -4,23 +4,25 @@ var dgram = require('dgram'), config = require('./config.js'), nu = require('./num_util.js'), RTSP = require('./rtsp.js'), - udpServers = require('./udp_servers.js'), - audioOut = require('./audio_out.js'), + UdpServers = require('./udp_servers.js'), bindings = require('../build/Release/airtunes'); + udpServers = new UdpServers(); var RTP_HEADER_SIZE = 12; -function AirTunesDevice(host, options) { +function AirTunesDevice(host, audioOut, options) { events.EventEmitter.call(this); if(!host) throw new Error('host is mandatory'); + this.udpServers = udpServers; + this.audioOut = audioOut; this.type = 'airtunes'; this.host = host; this.port = options.port || 5000; this.key = this.host + ':' + this.port; - this.rtsp = new RTSP.Client(options.volume || 50, options.password || null); + this.rtsp = new RTSP.Client(options.volume || 50, options.password || null, audioOut); this.audioCallback = null; this.encoder = bindings.newEncoder(); } @@ -32,7 +34,7 @@ AirTunesDevice.prototype.start = function() { this.audioSocket = dgram.createSocket('udp4'); // Wait until timing and control ports are chosen. We need them in RTSP handshake. - udpServers.once('ports', function(err) { + this.udpServers.once('ports', function(err) { if(err) { self.status = 'stopped'; self.emit('status', 'stopped'); @@ -44,7 +46,7 @@ AirTunesDevice.prototype.start = function() { self.doHandshake(); }); - udpServers.bind(this.host); + this.udpServers.bind(this.host); }; AirTunesDevice.prototype.doHandshake = function() { @@ -69,7 +71,7 @@ AirTunesDevice.prototype.doHandshake = function() { self.emit(err); }); - this.rtsp.startHandshake(udpServers, this.host, this.port); + this.rtsp.startHandshake(this.udpServers, this.host, this.port); }; AirTunesDevice.prototype.relayAudio = function() { @@ -85,11 +87,11 @@ AirTunesDevice.prototype.relayAudio = function() { ); }; - audioOut.on('packet', this.audioCallback); + this.audioOut.on('packet', this.audioCallback); }; AirTunesDevice.prototype.onSyncNeeded = function(seq) { - udpServers.sendControlSync(seq, this); + this.udpServers.sendControlSync(seq, this); }; AirTunesDevice.prototype.cleanup = function() { @@ -98,10 +100,11 @@ AirTunesDevice.prototype.cleanup = function() { this.emit('status', 'stopped'); if(this.audioCallback) { - audioOut.removeListener('packet', this.audioCallback); + this.audioOut.removeListener('packet', this.audioCallback); this.audioCallback = null; } + this.udpServers.close(); this.removeAllListeners(); }; diff --git a/lib/device_coreaudio.js b/lib/device_coreaudio.js index c010bef..af0ec51 100644 --- a/lib/device_coreaudio.js +++ b/lib/device_coreaudio.js @@ -1,12 +1,12 @@ var events = require('events'), util = require('util'), config = require('./config.js'), - audioOut = require('./audio_out.js'), bindings = require('../build/Release/airtunes'); -function CoreAudioDevice(hasAirTunes, options) { +function CoreAudioDevice(hasAirTunes, audioOut, options) { events.EventEmitter.call(this); + this.audioOut = audioOut; this.type = 'coreaudio'; this.key = 'coreaudio'; this.coreAudio = null; @@ -30,9 +30,9 @@ CoreAudioDevice.prototype.start = function(hideStatus) { var elapsed = new Date().getTime() - config.rtp_time_ref; var elapsedFrames = Math.floor(elapsed*config.sampling_rate/1000); - var caTimeRef = this.latency + audioOut.lastSeq*config.frames_per_packet - elapsedFrames; + var caTimeRef = this.latency + this.audioOut.lastSeq*config.frames_per_packet - elapsedFrames; this.coreAudio = bindings.newCoreAudio(); - + /* * Since the AudioQueue consumes data as fast as we send it, the internal buffer never * has a chance to fill. We add this margin to avoid ever draining the buffer. @@ -55,14 +55,14 @@ CoreAudioDevice.prototype.start = function(hideStatus) { this.setVolume(this.volume); this.status = 'ready'; - if(!hideStatus) + if(!hideStatus) this.emit('status', 'ready'); this.audioCallback = function(packet) { bindings.enqueuePacket(self.coreAudio, packet.pcm, packet.pcm.length); }; - audioOut.on('packet', this.audioCallback); + this.audioOut.on('packet', this.audioCallback); } CoreAudioDevice.prototype.reportStatus = function(){ @@ -109,7 +109,7 @@ CoreAudioDevice.prototype.cleanup = function() { this.started = false; if(this.audioCallback) { - audioOut.removeListener('packet', this.audioCallback); + this.audioOut.removeListener('packet', this.audioCallback); this.audioCallback = null; } diff --git a/lib/devices.js b/lib/devices.js index a6b0659..050f2f4 100644 --- a/lib/devices.js +++ b/lib/devices.js @@ -3,22 +3,22 @@ var events = require('events'), async = require('async'), CoreAudioDevice = require('./device_coreaudio.js'), AirTunesDevice = require('./device_airtunes.js'), - audioOut = require('./audio_out.js'), config = require('./config.js'); -function Devices() { +function Devices(audioOut) { events.EventEmitter.call(this); this.source = null; this.devices = {}; this.hasAirTunes = false; + this.audioOut = audioOut; } util.inherits(Devices, events.EventEmitter); Devices.prototype.init = function() { var self = this; - audioOut.on('need_sync', function(seq) { + self.audioOut.on('need_sync', function(seq) { // relay to all devices self.forEach(function(dev) { if(dev.onSyncNeeded && dev.controlPort) @@ -41,8 +41,8 @@ Devices.prototype.add = function(type, host, options) { options = options || {}; var dev = type === 'coreaudio' ? - new CoreAudioDevice(this.hasAirTunes, options) : - new AirTunesDevice(host, options); + new CoreAudioDevice(this.hasAirTunes, this.audioOut, options) : + new AirTunesDevice(host, this.audioOut, options); var previousDev = this.devices[dev.key]; @@ -157,4 +157,4 @@ Devices.prototype.checkAirTunesDevices = function() { this.hasAirTunes = newHasAirTunes; }; -module.exports = new Devices(); +module.exports = Devices; diff --git a/lib/index.js b/lib/index.js index 7cc85b6..6e09611 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,30 +1,36 @@ var Stream = require('stream'), util = require('util'), - devices = require('./devices.js'), - circularBuffer = require('./circular_buffer.js'), - audioOut = require('./audio_out.js'); + Devices = require('./devices.js'), + config = require('./config.js'), + CircularBuffer = require('./circular_buffer.js'), + AudioOut = require('./audio_out.js'); function AirTunes() { var self = this; Stream.call(this); - devices.init(); - devices.on('status', function(key, status, desc) { + var audioOut = new AudioOut(); + this.devices = new Devices(audioOut); + + this.devices.init(); + this.devices.on('status', function(key, status, desc) { self.emit('device', key, status, desc); }); - circularBuffer.on('status', function(status) { + this.circularBuffer = new CircularBuffer(config.packets_in_buffer, config.packet_size); + + this.circularBuffer.on('status', function(status) { self.emit('buffer', status); }); - audioOut.init(devices); + audioOut.init(this.devices, this.circularBuffer); - circularBuffer.on('drain', function() { + this.circularBuffer.on('drain', function() { self.emit('drain'); }); - circularBuffer.on('error', function(err) { + this.circularBuffer.on('error', function(err) { self.emit('error', err); }); @@ -34,39 +40,40 @@ function AirTunes() { util.inherits(AirTunes, Stream); AirTunes.prototype.add = function(host, options) { - return devices.add('airtunes', host, options); + return this.devices.add('airtunes', host, options); }; AirTunes.prototype.addCoreAudio = function(options) { - return devices.add('coreaudio', null, options); + return this.devices.add('coreaudio', null, options); }; AirTunes.prototype.stopAll = function(cb) { - devices.stopAll(cb); + this.devices.stopAll(cb); }; AirTunes.prototype.setVolume = function(deviceKey, volume, callback) { - devices.setVolume(deviceKey, volume, callback); + this.devices.setVolume(deviceKey, volume, callback); }; AirTunes.prototype.setTrackInfo = function(deviceKey, name, artist, album, callback) { - devices.setTrackInfo(deviceKey, name, artist, album, callback); + this.devices.setTrackInfo(deviceKey, name, artist, album, callback); }; AirTunes.prototype.reset = function() { - circularBuffer.reset(); + this.circularBuffer.reset(); }; AirTunes.prototype.setArtwork = function(deviceKey, art, contentType, callback) { - devices.setArtwork(deviceKey, art, contentType, callback); + this.devices.setArtwork(deviceKey, art, contentType, callback); }; AirTunes.prototype.write = function(data) { - return circularBuffer.write(data); + return this.circularBuffer.write(data); }; AirTunes.prototype.end = function() { - circularBuffer.end(); + this.circularBuffer.end(); }; module.exports = new AirTunes(); +module.exports.AirTunes = AirTunes; \ No newline at end of file diff --git a/lib/packet_pool.js b/lib/packet_pool.js index 507604a..2407f01 100644 --- a/lib/packet_pool.js +++ b/lib/packet_pool.js @@ -39,4 +39,4 @@ Packet.prototype.release = function() { } }; -module.exports = new PacketPool(); +module.exports = PacketPool; diff --git a/lib/rtsp.js b/lib/rtsp.js index aa32c09..939bdec 100644 --- a/lib/rtsp.js +++ b/lib/rtsp.js @@ -4,7 +4,6 @@ var net = require('net'), util = require('util'), fs = require('fs'), config = require('./config.js'), - audioOut = require('./audio_out.js'), nu = require('./num_util.js'); var OPTIONS = 0, @@ -18,9 +17,10 @@ var OPTIONS = 0, SETDAAP = 8, SETART = 9; -function Client(volume, password) { +function Client(volume, password, audioOut) { events.EventEmitter.call(this); + this.audioOut = audioOut; this.status = OPTIONS; this.socket = null; this.cseq = 0; @@ -49,11 +49,11 @@ Client.prototype.startHandshake = function(udpServers, host, port) { var self = this; this.startTimeout(); - + this.controlPort = udpServers.control.port; this.timingPort = udpServers.timing.port; - - + + this.socket = net.connect(port, host, function() { self.clearTimeout(); self.sendNextRequest(); @@ -68,16 +68,18 @@ Client.prototype.startHandshake = function(udpServers, host, port) { * I assume that all responses have empty bodies. */ data = data.toString(); - var endIndex = data.indexOf('\r\n\r\n'); - if(endIndex < 0) { - blob += data; + blob += data; + var endIndex = blob.indexOf('\r\n\r\n'); + + if (endIndex < 0) { return; } - endIndex += 4; // the end of \r\n\r\n + endIndex += 4; + + blob = blob.substring(0, endIndex); - blob += data.substring(0, endIndex); self.processData(blob); blob = data.substring(endIndex); @@ -229,7 +231,7 @@ function parseResponse(blob) { var headers = {}; lines.slice(1).forEach(function(line) { - var res = /([^:]+): (.*)/.exec(line); + var res = /([^:]+):\s*(.*)/.exec(line); if(!res) return; @@ -279,7 +281,7 @@ Client.prototype.makeHeadWithURL = function(method, digestInfo) { } Client.prototype.makeRtpInfo = function() { - var nextSeq = audioOut.lastSeq + 1; + var nextSeq = this.audioOut.lastSeq + 1; var rtpSyncTime = nextSeq*config.frames_per_packet + 2*config.sampling_rate; return 'RTP-Info: seq=' + nextSeq + ';rtptime=' + rtpSyncTime + '\r\n'; }; diff --git a/lib/udp_servers.js b/lib/udp_servers.js index 4f984cb..7101309 100644 --- a/lib/udp_servers.js +++ b/lib/udp_servers.js @@ -33,7 +33,7 @@ util.inherits(UDPServers, events.EventEmitter); UDPServers.prototype.bind = function(host) { var self = this; - + this.hosts.push(host); switch(this.status) { @@ -54,10 +54,10 @@ UDPServers.prototype.bind = function(host) { this.timing.socket = dgram.createSocket('udp4'); this.timing.socket.on('message', function(msg, rinfo) { - - // only listen and respond on own hosts + + // only listen and respond on own hosts if (self.hosts.indexOf(rinfo.address) < 0) return; - + var ts1 = msg.readUInt32BE(24); var ts2 = msg.readUInt32BE(28); @@ -84,10 +84,10 @@ UDPServers.prototype.bind = function(host) { this.control.socket = dgram.createSocket('udp4'); this.control.socket.on('message', function(msg, rinfo) { - - // only listen for own hosts + + // only listen for own hosts if (self.hosts.indexOf(rinfo.address) < 0) return; - + var serverSeq = msg.readUInt16BE(2); var missedSeq = msg.readUInt16BE(4); var count = msg.readUInt16BE(6); @@ -142,7 +142,7 @@ UDPServers.prototype.bind = function(host) { } UDPServers.prototype.close = function() { - if(this.status === UNBOUND) + if(this.status === UNBOUND) return; this.status = UNBOUND; @@ -163,7 +163,7 @@ UDPServers.prototype.sendControlSync = function(seq, dev) { packet.writeUInt16BE(0x80d4, 0); packet.writeUInt16BE(0x0007, 2); packet.writeUInt32BE(nu.low32(seq*config.frames_per_packet), 4); - + var ntpTime = ntp.timestamp(); ntpTime.copy(packet, 8); @@ -171,8 +171,8 @@ UDPServers.prototype.sendControlSync = function(seq, dev) { nu.low32(seq*config.frames_per_packet + config.sampling_rate*2), 16 ); - + this.control.socket.send(packet, 0, packet.length, dev.controlPort, dev.host); } -module.exports = new UDPServers(); +module.exports = UDPServers; diff --git a/src/bindings.cc b/src/bindings.cc index c97a6ed..d8f8a50 100644 --- a/src/bindings.cc +++ b/src/bindings.cc @@ -12,7 +12,9 @@ void InitCoreAudio(Handle); #endif void Initialize(Handle target) { - HandleScope scope; + + Isolate* isolate = v8::Isolate::GetCurrent(); + HandleScope scope(isolate); InitCodec(target); #ifdef __APPLE__ diff --git a/src/codec.cc b/src/codec.cc index eb55530..f1956a8 100644 --- a/src/codec.cc +++ b/src/codec.cc @@ -55,17 +55,12 @@ void FillOutputAudioFormat(AudioFormatDescription *format) { format->mReserved = 0; } -void encoder_weak_callback (Persistent wrapper, void *arg) { - HandleScope scope; - ALACEncoder *encoder = (ALACEncoder *)arg; - delete encoder; - wrapper.Dispose(); -} - // Creates a new encoder instance and wraps it in a JavaScript object. // This encoder is freed when the object is released by the GC. -Handle NewEncoder(const Arguments& args) { - HandleScope scope; +//Handle NewEncoder(const Arguments& args) { +void NewEncoder(const FunctionCallbackInfo& args) { + Isolate* isolate = Isolate::GetCurrent(); + EscapableHandleScope scope(isolate); AudioFormatDescription outputFormat; FillOutputAudioFormat(&outputFormat); @@ -75,25 +70,26 @@ Handle NewEncoder(const Arguments& args) { encoder->SetFrameSize(kFramesPerPacket); encoder->InitializeEncoder(outputFormat); - Persistent encoderClass = Persistent::New(ObjectTemplate::New()); + Local encoderClass = ObjectTemplate::New(isolate); encoderClass->SetInternalFieldCount(1); - Persistent o = Persistent::New(encoderClass->NewInstance()); - o->SetPointerInInternalField(0, encoder); - o.MakeWeak(encoder, encoder_weak_callback); - return scope.Close(o); + Local obj = encoderClass->NewInstance(); + obj->SetAlignedPointerInInternalField(0, encoder); + + args.GetReturnValue().Set(obj); } -Handle EncodeALAC(const Arguments& args) { - HandleScope scope; +void EncodeALAC(const FunctionCallbackInfo& args) { + Isolate* isolate = Isolate::GetCurrent(); + EscapableHandleScope scope(isolate); if(args.Length() < 4) { printf("expected: EncodeALAC(encoder, pcmData, pcmSize, alacData, alacSize)\n"); - return scope.Close(Null()); + args.GetReturnValue().Set(Null(isolate)); } Localwrapper = args[0]->ToObject(); - ALACEncoder *encoder = (ALACEncoder*)wrapper->GetPointerFromInternalField(0); + ALACEncoder *encoder = (ALACEncoder*)wrapper->GetAlignedPointerFromInternalField(0); Local pcmBuffer = args[1]; unsigned char* pcmData = (unsigned char*)Buffer::Data(pcmBuffer->ToObject()); @@ -110,15 +106,16 @@ Handle EncodeALAC(const Arguments& args) { int32_t alacSize = pcmSize; encoder->Encode(inputFormat, outputFormat, pcmData, alacData, &alacSize); - return scope.Close(Integer::New(alacSize)); + args.GetReturnValue().Set(Integer::New(isolate, alacSize)); } -Handle EncryptAES(const Arguments& args) { - HandleScope scope; +void EncryptAES(const FunctionCallbackInfo& args) { + Isolate* isolate = v8::Isolate::GetCurrent(); + EscapableHandleScope scope(isolate); if(args.Length() < 2) { printf("expected: EncryptAES(alacData, alacSize)\n"); - return scope.Close(Null()); + args.GetReturnValue().Set(Null(isolate)); } Local alacBuffer = args[0]; @@ -146,7 +143,7 @@ Handle EncryptAES(const Arguments& args) { i += kBlockSize; } - return scope.Close(Null()); + args.GetReturnValue().Set(Null(isolate)); } void InitCodec(Handle target) { diff --git a/src/coreaudio.cc b/src/coreaudio.cc index 9537c72..41f3429 100644 --- a/src/coreaudio.cc +++ b/src/coreaudio.cc @@ -1,3 +1,13 @@ +// Conversion to modern node (v4) +// +// TODO: understand. I have no idea what I'm doing here. HandleScope/Isolate? +// +// https://nodejs.org/api/addons.html +// https://developers.google.com/v8/embed?hl=en +// https://strongloop.com/strongblog/node-js-v0-12-c-apis-breaking/ +// https://github.com/nodejs/nan/blob/master/doc/persistent.md + + #include #include #include @@ -43,11 +53,9 @@ namespace nodeairtunes { }; // This will free the AudioQueue when the wraping JS object is released by the GC - void coreAudio_weak_callback(v8::Persistent wrapper, void *arg) { - v8::HandleScope scope; - struct coreAudioObjects *coreAudio = (struct coreAudioObjects *) arg; + void coreAudio_weak_callback(const v8::WeakCallbackInfo &data) { + struct coreAudioObjects *coreAudio = (struct coreAudioObjects *) data.GetParameter(); AudioQueueDispose(coreAudio->audioQueue, true); - wrapper.Dispose(); } void OnAudioQueueBufferConsumed(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) { @@ -110,15 +118,20 @@ namespace nodeairtunes { pthread_mutex_unlock(&(coreAudio->queueBuffersMutex)); } - v8::Handle NewCoreAudio(const v8::Arguments& args) { - v8::HandleScope scope; + void NewCoreAudio(const v8::FunctionCallbackInfo& args) { + v8::Isolate* isolate = args.GetIsolate(); + + v8::HandleScope handle_scope(isolate); + + struct coreAudioObjects *coreAudio + = (struct coreAudioObjects *) malloc(sizeof (*coreAudio)); - struct coreAudioObjects *coreAudio = (struct coreAudioObjects *) malloc(sizeof (*coreAudio)); - v8::Persistent coreAudioClass = v8::Persistent::New(v8::ObjectTemplate::New()); - coreAudioClass->SetInternalFieldCount(1); - v8::Persistent o = v8::Persistent::New(coreAudioClass->NewInstance()); - o->SetPointerInInternalField(0, coreAudio); - o.MakeWeak(coreAudio, coreAudio_weak_callback); + v8::Persistent o; + o.SetWeak( + coreAudio, + coreAudio_weak_callback, + v8::WeakCallbackType::kParameter + ); coreAudio->isPlaying = false; coreAudio->buffersUsed = 0; @@ -143,7 +156,8 @@ namespace nodeairtunes { // Allocating AudioQueue if ((LRet = AudioQueueNewOutput(&LFormat, OnAudioQueueBufferConsumed, coreAudio, NULL, NULL, 0, &(coreAudio->audioQueue)))) { - return scope.Close(v8::Null()); + args.GetReturnValue().Set(v8::Null(isolate)); + return; } OSStatus status = 0; @@ -154,19 +168,20 @@ namespace nodeairtunes { coreAudio->inuse[i] = false; } - return scope.Close(o); + args.GetReturnValue().Set(o); } - v8::Handle EnqueuePacket(const v8::Arguments& args) { - v8::HandleScope scope; + void EnqueuePacket(const v8::FunctionCallbackInfo& args) { + v8::Isolate* isolate = args.GetIsolate(); if (args.Length() < 3) { printf("expected: EnqueuePacket(coreAudio, pcmData, pcmSize)\n"); - return scope.Close(v8::Null()); + args.GetReturnValue().Set(v8::Null(isolate)); + return; } - v8::Localwrapper = args[0]->ToObject(); - struct coreAudioObjects *coreAudio = (struct coreAudioObjects *) wrapper->GetPointerFromInternalField(0); + v8::Local wrapper = args[0]->ToObject(); + struct coreAudioObjects *coreAudio = (struct coreAudioObjects *) *wrapper; v8::Local pcmBuffer = args[1]; unsigned char* pcmData = (unsigned char*) (Buffer::Data(pcmBuffer->ToObject())); @@ -204,23 +219,24 @@ namespace nodeairtunes { offset += copySize; } - return scope.Close(v8::Null()); + args.GetReturnValue().Set(v8::Null(isolate)); } - v8::Handle Play(const v8::Arguments& args) { - v8::HandleScope scope; + void Play(const v8::FunctionCallbackInfo& args) { + v8::Isolate* isolate = args.GetIsolate(); if (args.Length() < 2) { printf("expected: Play(coreAudio, audioQueueTimeRef)\n"); - return scope.Close(v8::Null()); + args.GetReturnValue().Set(v8::Null(isolate)); + return; } - v8::Localwrapper = args[0]->ToObject(); - struct coreAudioObjects *coreAudio = (struct coreAudioObjects *) wrapper->GetPointerFromInternalField(0); + v8::Local wrapper = args[0]->ToObject(); + struct coreAudioObjects *coreAudio = (struct coreAudioObjects *) *wrapper; int64_t timeStamp = args[1]->IntegerValue(); - AudioTimeStamp myAudioQueueStartTime = {0}; + AudioTimeStamp myAudioQueueStartTime; // = {0}; Float64 theNumberOfSecondsInTheFuture = timeStamp/44100.0; Float64 hostTimeFreq = CAHostTimeBase::GetFrequency(); @@ -237,19 +253,20 @@ namespace nodeairtunes { } } - return scope.Close(v8::Null()); + args.GetReturnValue().Set(v8::Null(isolate)); } - v8::Handle Stop(const v8::Arguments& args) { - v8::HandleScope scope; + void Stop(const v8::FunctionCallbackInfo& args) { + v8::Isolate* isolate = args.GetIsolate(); if (args.Length() < 1) { - printf("expected: Play(coreAudio)\n"); - return scope.Close(v8::Null()); + printf("expected: Play(coreAudio)\n"); + args.GetReturnValue().Set(v8::Null(isolate)); + return; } - v8::Localwrapper = args[0]->ToObject(); - struct coreAudioObjects *coreAudio = (struct coreAudioObjects *) wrapper->GetPointerFromInternalField(0); + v8::Local wrapper = args[0]->ToObject(); + struct coreAudioObjects *coreAudio = (struct coreAudioObjects *) *wrapper; if (coreAudio->isPlaying) { if (AudioQueueStop(coreAudio->audioQueue, true)) { @@ -259,34 +276,36 @@ namespace nodeairtunes { } } - return scope.Close(v8::Null()); + args.GetReturnValue().Set(v8::Null(isolate)); } - v8::Handle SetVolume(const v8::Arguments& args) { - v8::HandleScope scope; + void SetVolume(const v8::FunctionCallbackInfo& args) { + v8::Isolate* isolate = args.GetIsolate(); if (args.Length() < 1) { printf("expected: Play(coreAudio)\n"); - return scope.Close(v8::Null()); + args.GetReturnValue().Set(v8::Null(isolate)); + return; } - v8::Localwrapper = args[0]->ToObject(); - struct coreAudioObjects *coreAudio = (struct coreAudioObjects *) wrapper->GetPointerFromInternalField(0); + v8::Local wrapper = args[0]->ToObject(); + struct coreAudioObjects *coreAudio = (struct coreAudioObjects *) *wrapper; float volumeToSet=args[1]->IntegerValue()/100.0; if (coreAudio->isPlaying) AudioQueueSetParameter(coreAudio->audioQueue, kAudioQueueParam_Volume, volumeToSet); - return scope.Close(v8::Null()); + args.GetReturnValue().Set(v8::Null(isolate)); } - - v8::Handle GetBufferLevel(const v8::Arguments& args) { - v8::HandleScope scope; - v8::Localwrapper = args[0]->ToObject(); - struct coreAudioObjects *coreAudio = (struct coreAudioObjects *) wrapper->GetPointerFromInternalField(0); - v8::Handle o= v8::Integer::New((int)((coreAudio->buffersUsed/(float)NUMBER_OF_BUFFERS)*100)); - - return scope.Close(o); + + void GetBufferLevel(const v8::FunctionCallbackInfo& args) { + v8::Isolate* isolate = args.GetIsolate(); + + v8::Local wrapper = args[0]->ToObject(); + struct coreAudioObjects *coreAudio = (struct coreAudioObjects *) *wrapper; + v8::Local o = v8::Integer::New(isolate, (int)((coreAudio->buffersUsed/(float)NUMBER_OF_BUFFERS)*100)); + + args.GetReturnValue().Set(o); } void InitCoreAudio(v8::Handle target) {