Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
leetreveil committed Jan 18, 2016
1 parent 4164900 commit a411d05
Show file tree
Hide file tree
Showing 11 changed files with 404 additions and 345 deletions.
80 changes: 41 additions & 39 deletions lib/asf.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,46 @@
var fs = require('fs');
var util = require('util');
var events = require('events');
var strtok = require('strtok2');
var Calippo = require('Calippo');
var common = require('./common');
var equal = require('deep-equal');

var decodeString = common.decodeString;

module.exports = function (stream, callback, done) {
module.exports = function () {
var currentState = startState;

strtok.parse(stream, function (v, cb) {
currentState = currentState.parse(callback, v, done);
return currentState.getExpectedType();
return new Calippo({'objectMode': true}, function (v) {
currentState = currentState.parse(this, v);
return currentState.getExpectedType(this);
})
};

var startState = {
parse: function (callback) {
parse: function (parser) {
return idState;
},
}

var finishedState = {
parse: function (callback) {
parse: function (parser) {
return this;
},
getExpectedType: function () {
return strtok.DONE;
getExpectedType: function (parser) {
parser.push(null);
}
}

var idState = {
parse: function (callback, data, done) {
parse: function (parser, data) {
if (!equal(common.asfGuidBuf, data)) {
done(new Error('expected asf header but was not found'));
parser.emit('error', new Error('expected asf header but was not found'));
return finishedState;
}
return headerDataState;
},
getExpectedType: function () {
return new strtok.BufferType(common.asfGuidBuf.length);
getExpectedType: function (parser) {
return parser.Buffer(common.asfGuidBuf.length);
}
};

Expand All @@ -50,7 +50,7 @@ function ReadObjectState(size, objectCount) {
this.objectCount = objectCount;
}

ReadObjectState.prototype.parse = function(callback, data, done) {
ReadObjectState.prototype.parse = function(parser, data) {
var guid = data.slice(0, 16);
var size = readUInt64LE(data, 16)
var State = stateByGuid(guid) || IgnoreObjectState;
Expand All @@ -60,21 +60,21 @@ ReadObjectState.prototype.parse = function(callback, data, done) {
return new State(nextState, size - 24);
}

ReadObjectState.prototype.getExpectedType = function() {
return new strtok.BufferType(24);
ReadObjectState.prototype.getExpectedType = function(parser) {
return parser.Buffer(24);
}

var headerDataState = {
parse: function (callback, data, done) {
parse: function (parser, data) {
var size = readUInt64LE(data, 0);
var objectCount = data.readUInt32LE(8);
return new ReadObjectState(size, objectCount);
},
getExpectedType: function () {
getExpectedType: function (parser) {
// 8 bytes size
// 4 bytes object count
// 2 bytes ignore
return new strtok.BufferType(14);
return parser.Buffer(14);
}
};

Expand All @@ -83,13 +83,13 @@ function IgnoreObjectState(nextState, size) {
this.size = size;
}

IgnoreObjectState.prototype.parse = function(callback, data, done) {
if (this.nextState === finishedState) done();
IgnoreObjectState.prototype.parse = function(parser, data) {
if (this.nextState === finishedState) parser.push(null);
return this.nextState;
}

IgnoreObjectState.prototype.getExpectedType = function() {
return new strtok.IgnoreType(this.size);
IgnoreObjectState.prototype.getExpectedType = function(parser) {
return parser.Skip(this.size)
}

function ContentDescriptionObjectState(nextState, size) {
Expand All @@ -98,7 +98,7 @@ function ContentDescriptionObjectState(nextState, size) {
}

var contentDescTags = ['Title', 'Author', 'Copyright', 'Description', 'Rating'];
ContentDescriptionObjectState.prototype.parse = function(callback, data, done) {
ContentDescriptionObjectState.prototype.parse = function(parser, data) {
var lengths = [
data.readUInt16LE(0),
data.readUInt16LE(2),
Expand All @@ -113,16 +113,17 @@ ContentDescriptionObjectState.prototype.parse = function(callback, data, done) {
var end = pos + length;
if (length > 0) {
var value = parseUnicodeAttr(data.slice(pos, end));
callback(tagName, value);
parser.push([tagName, value])
}
pos = end;
}
if (this.nextState === finishedState) done();
// if (this.nextState === finishedState) done();
// TODO: what to do about this
return this.nextState;
}

ContentDescriptionObjectState.prototype.getExpectedType = function() {
return new strtok.BufferType(this.size);
ContentDescriptionObjectState.prototype.getExpectedType = function(parser) {
return parser.Buffer(this.size);
}

ContentDescriptionObjectState.guid = new Buffer([
Expand All @@ -145,7 +146,7 @@ var attributeParsers = [
parseByteArrayAttr,
];

ExtendedContentDescriptionObjectState.prototype.parse = function(callback, data, done) {
ExtendedContentDescriptionObjectState.prototype.parse = function(parser, data) {
var attrCount = data.readUInt16LE(0);
var pos = 2;
for (var i = 0; i < attrCount; i += 1) {
Expand All @@ -161,18 +162,19 @@ ExtendedContentDescriptionObjectState.prototype.parse = function(callback, data,
pos += valueLen;
var parseAttr = attributeParsers[valueType];
if (!parseAttr) {
done(new Error('unexpected value type: ' + valueType));
parser.emit(['error', new Error('unexpected value type: ' + valueType)]);
// TODO: startstate?
return finishedState;
}
var attr = parseAttr(value);
callback(name, attr);
parser.push([name, attr])
}
if (this.nextState === finishedState) done();
if (this.nextState === finishedState) parser.push(null);
return this.nextState;
}

ExtendedContentDescriptionObjectState.prototype.getExpectedType = function() {
return new strtok.BufferType(this.size);
ExtendedContentDescriptionObjectState.prototype.getExpectedType = function(parser) {
return parser.Buffer(this.size);
}

ExtendedContentDescriptionObjectState.guid = new Buffer([
Expand All @@ -185,17 +187,17 @@ function FilePropertiesObject(nextState, size) {
this.size = size;
}

FilePropertiesObject.prototype.parse = function (callback, data, done) {
FilePropertiesObject.prototype.parse = function (parser, data) {
// in miliseconds
var playDuration = parseQWordAttr(data.slice(40, 48)) / 10000
callback('duration', Math.round(playDuration / 1000))
parser.push(['duration', Math.round(playDuration / 1000)])

if (this.nextState === finishedState) done();
if (this.nextState === finishedState) parser.push(null);
return this.nextState;
}

FilePropertiesObject.prototype.getExpectedType = function() {
return new strtok.BufferType(this.size);
FilePropertiesObject.prototype.getExpectedType = function(parser) {
return parser.Buffer(this.size);
}

FilePropertiesObject.guid = new Buffer([
Expand Down
54 changes: 26 additions & 28 deletions lib/flac.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
'use strict';
var strtok = require('strtok2');
var Calippo = require('calippo');
var common = require('./common');

module.exports = function (stream, callback, done) {
module.exports = function () {
var currentState = startState;

strtok.parse(stream, function (v, cb) {
currentState = currentState.parse(callback, v, done);
return currentState.getExpectedType();
return new Calippo({'objectMode': true}, function (v) {
currentState = currentState.parse(this, v);
return currentState.getExpectedType(this);
})
}

Expand All @@ -17,7 +17,7 @@ var DataDecoder = function (data) {
}

DataDecoder.prototype.readInt32 = function () {
var value = strtok.UINT32_LE.get(this.data, this.offset);
var value = this.data.readUInt32LE(this.offset);
this.offset += 4;
return value;
}
Expand All @@ -30,11 +30,11 @@ DataDecoder.prototype.readStringUtf8 = function () {
};

var finishedState = {
parse: function (callback) {
parse: function (parser, data) {
return this;
},
getExpectedType: function () {
return strtok.DONE;
getExpectedType: function (parser) {
parser.push(null)
}
}

Expand All @@ -44,7 +44,7 @@ var BlockDataState = function (type, length, nextStateFactory) {
this.nextStateFactory = nextStateFactory;
}

BlockDataState.prototype.parse = function (callback, data) {
BlockDataState.prototype.parse = function (parser, data) {
if (this.type === 4) {
var decoder = new DataDecoder(data);
var vendorString = decoder.readStringUtf8();
Expand All @@ -56,64 +56,62 @@ BlockDataState.prototype.parse = function (callback, data) {
for (i = 0; i < commentListLength; i++) {
comment = decoder.readStringUtf8();
split = comment.split('=');
callback(split[0].toUpperCase(), split[1]);
parser.push([split[0].toUpperCase(), split[1]])
}
} else if (this.type === 6) {
var picture = common.readVorbisPicture(data);
callback('METADATA_BLOCK_PICTURE', picture);
parser.push(['METADATA_BLOCK_PICTURE', picture])
} else if (this.type === 0) { // METADATA_BLOCK_STREAMINFO
if (data.length < 34) return; // invalid streaminfo
var sampleRate = common.strtokUINT24_BE.get(data, 10) >> 4;
var totalSamples = data.readUInt32BE(14);
var duration = totalSamples / sampleRate;
callback('duration', Math.round(duration));
parser.push(['duration', Math.round(duration)]);
}

return this.nextStateFactory();
}

BlockDataState.prototype.getExpectedType = function () {
return new strtok.BufferType(this.length);
BlockDataState.prototype.getExpectedType = function (parser) {
return parser.Buffer(this.length);
}

var blockHeaderState = {
parse: function (callback, data, done) {
parse: function (parser, data) {
var header = {
lastBlock: (data[0] & 0x80) == 0x80,
type: data[0] & 0x7f,
length: common.strtokUINT24_BE.get(data, 1)
}
var followingStateFactory = header.lastBlock ? function() {
done();
return finishedState;
} : function() {
return blockHeaderState;
}

return new BlockDataState(header.type, header.length, followingStateFactory);
},
getExpectedType: function () {
return new strtok.BufferType(4);
getExpectedType: function (parser) {
return parser.Buffer(4);
}
}

var idState = {
parse: function (callback, data, done) {
parse: function (parser, data) {
if (data !== 'fLaC') {
done(new Error('expected flac header but was not found'));
// TODO: shouldn't the param be wrapped in an array?? []
parser.emit('error', new Error('expected flac header but was not found'))
return startState;
}
return blockHeaderState;
},
getExpectedType: function () {
return new strtok.StringType(4);
getExpectedType: function (parser) {
return parser.String(4);
}
};

var startState = {
parse: function (callback) {
parse: function (parser, data) {
return idState;
},
getExpectedType: function () {
return strtok.DONE;
}
getExpectedType: function (parser) {}
}
Loading

0 comments on commit a411d05

Please sign in to comment.