stuff
This commit is contained in:
11
buildfiles/app/node_modules/metaflac-js2/.prettierrc
generated
vendored
Normal file
11
buildfiles/app/node_modules/metaflac-js2/.prettierrc
generated
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"printWidth": 120,
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"bracketSpacing": true,
|
||||
"endOfLine": "lf",
|
||||
"arrowParens": "always"
|
||||
}
|
39
buildfiles/app/node_modules/metaflac-js2/README.md
generated
vendored
Normal file
39
buildfiles/app/node_modules/metaflac-js2/README.md
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
# metaflac-js2
|
||||
|
||||
A pure JavaScript implementation of the metaflac (the official FLAC tool written in C++)
|
||||
|
||||
> This is a tool that has just been completed, I hope to help you, and I hope we can optimize it together.
|
||||
|
||||
Use as module:
|
||||
|
||||
```
|
||||
npm i metaflac-js2 --save
|
||||
```
|
||||
|
||||
```
|
||||
const Metaflac = require('metaflac-js2');
|
||||
const flac = new Metaflac('/path/to/flac.flac or buffer');
|
||||
flac.setTag('TITLE=My Music');
|
||||
flac.save();
|
||||
```
|
||||
|
||||
Use as cli:
|
||||
|
||||
Usage is basically consistent with official tools.
|
||||
|
||||
```
|
||||
npm i metaflac-js2 -g
|
||||
metaflac-js -h
|
||||
```
|
||||
|
||||
Note: here is the official FLAC tools [doc](https://xiph.org/flac/documentation_tools_metaflac.html)
|
||||
|
||||
- This is a fork of [metaflac-js](https://github.com/ishowshao/metaflac-js) with minor improvements for detecting image dimensions and mime type.
|
||||
|
||||
#### Changelog:
|
||||
|
||||
- Removed `importPictureFrom`and `importPictureFromBuffer`
|
||||
- Added `importPicture`
|
||||
|
||||
|
||||
importPicture takes either path or buffer
|
151
buildfiles/app/node_modules/metaflac-js2/cli.js
generated
vendored
Executable file
151
buildfiles/app/node_modules/metaflac-js2/cli.js
generated
vendored
Executable file
@ -0,0 +1,151 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const path = require('path');
|
||||
const program = require('commander');
|
||||
const info = require('./package.json');
|
||||
const Metaflac = require('./index');
|
||||
|
||||
let file;
|
||||
|
||||
program.version(info.version, '-v, --version');
|
||||
|
||||
program.arguments('<FLACfile>').action((FLACfile) => {
|
||||
file = FLACfile;
|
||||
});
|
||||
program.option('--show-md5sum', 'Show the MD5 signature from the STREAMINFO block.');
|
||||
program.option('--show-min-blocksize', 'Show the minimum block size from the STREAMINFO block.');
|
||||
program.option('--show-max-blocksize', 'Show the maximum block size from the STREAMINFO block.');
|
||||
program.option('--show-min-framesize', 'Show the minimum frame size from the STREAMINFO block.');
|
||||
program.option('--show-max-framesize', 'Show the maximum frame size from the STREAMINFO block.');
|
||||
program.option('--show-sample-rate', 'Show the sample rate from the STREAMINFO block.');
|
||||
program.option('--show-channels', 'Show the number of channels from the STREAMINFO block.');
|
||||
program.option('--show-bps', 'Show the # of bits per sample from the STREAMINFO block.');
|
||||
program.option('--show-total-samples', 'Show the total # of samples from the STREAMINFO block.');
|
||||
program.option('--show-vendor-tag', 'Show the vendor string from the VORBIS_COMMENT block.');
|
||||
program.option('--show-tag <NAME>', 'Show all tags where the the field name matches NAME.');
|
||||
program.option('--remove-tag <NAME>', 'Remove all tags whose field name is NAME.');
|
||||
program.option('--remove-first-tag <NAME>', 'Remove first tag whose field name is NAME.');
|
||||
program.option('--remove-all-tags', 'Remove all tags, leaving only the vendor string.');
|
||||
program.option(
|
||||
'--set-tag <FIELD>',
|
||||
'Add a tag. The FIELD must comply with the Vorbis comment spec, of the form NAME=VALUE. If there is currently no tag block, one will be created.'
|
||||
);
|
||||
program.option(
|
||||
'--set-tag-from-file <FIELD>',
|
||||
'Like --set-tag, except the VALUE is a filename whose contents will be read verbatim to set the tag value.'
|
||||
);
|
||||
program.option('--import-tags-from <FILE>', 'Import tags from a file.');
|
||||
program.option(
|
||||
'--export-tags-to <FILE>',
|
||||
'Export tags to a file. Use - for stdout. Each line will be of the form NAME=VALUE.'
|
||||
);
|
||||
program.option('--import-picture-from <FILENAME>', 'Import a picture and store it in a PICTURE metadata block.');
|
||||
program.option('--export-picture-to <FILE>', 'Export PICTURE block to a file.');
|
||||
program.option('--list-picture', 'List all picture block info.');
|
||||
|
||||
program.parse(process.argv);
|
||||
|
||||
if (typeof file === 'undefined') {
|
||||
console.error('ERROR: you must specify one FLAC file;');
|
||||
process.exit(1);
|
||||
}
|
||||
try {
|
||||
const flac = new Metaflac(file);
|
||||
if (program.showMd5sum) {
|
||||
console.log(flac.getMd5sum());
|
||||
}
|
||||
if (program.showMinBlocksize) {
|
||||
console.log(flac.getMinBlocksize());
|
||||
}
|
||||
if (program.showMaxBlocksize) {
|
||||
console.log(flac.getMaxBlocksize());
|
||||
}
|
||||
if (program.showMinFramesize) {
|
||||
console.log(flac.getMinFramesize());
|
||||
}
|
||||
if (program.showMaxFramesize) {
|
||||
console.log(flac.getMaxFramesize());
|
||||
}
|
||||
if (program.showSampleRate) {
|
||||
console.log(flac.getSampleRate());
|
||||
}
|
||||
if (program.showChannels) {
|
||||
console.log(flac.getChannels());
|
||||
}
|
||||
if (program.showBps) {
|
||||
console.log(flac.getBps());
|
||||
}
|
||||
if (program.showTotalSamples) {
|
||||
console.log(flac.getTotalSamples());
|
||||
}
|
||||
if (program.showVendorTag) {
|
||||
console.log(flac.getVendorTag());
|
||||
}
|
||||
if (program.showTag) {
|
||||
console.log(flac.getTag(program.showTag));
|
||||
}
|
||||
if (program.removeTag) {
|
||||
flac.removeTag(program.removeTag);
|
||||
console.log(flac.getAllTags().join('\n'));
|
||||
}
|
||||
if (program.removeFirstTag) {
|
||||
flac.removeFirstTag(program.removeFirstTag);
|
||||
console.log(flac.getAllTags().join('\n'));
|
||||
}
|
||||
if (program.removeAllTags) {
|
||||
flac.removeAllTags();
|
||||
console.log(flac.getAllTags().join('\n'));
|
||||
}
|
||||
if (program.setTag) {
|
||||
flac.setTag(program.setTag);
|
||||
console.log(flac.getAllTags().join('\n'));
|
||||
flac.save();
|
||||
}
|
||||
if (program.setTagFromFile) {
|
||||
flac.setTagFromFile(program.setTagFromFile);
|
||||
console.log(flac.getAllTags().join('\n'));
|
||||
}
|
||||
if (program.importTagsFrom) {
|
||||
flac.importTagsFrom(program.importTagsFrom);
|
||||
console.log(flac.getAllTags().join('\n'));
|
||||
}
|
||||
if (program.exportTagsTo) {
|
||||
if (program.exportTagsTo === '-') {
|
||||
console.log(flac.getAllTags().join('\n'));
|
||||
} else {
|
||||
let filepath;
|
||||
if (!path.isAbsolute(program.exportTagsTo)) {
|
||||
filepath = path.resolve(process.cwd(), program.exportTagsTo);
|
||||
} else {
|
||||
filepath = program.exportTagsTo;
|
||||
}
|
||||
flac.exportTagsTo(filepath);
|
||||
}
|
||||
}
|
||||
if (program.importPictureFrom) {
|
||||
let filepath;
|
||||
if (!path.isAbsolute(program.importPictureFrom)) {
|
||||
filepath = path.resolve(process.cwd(), program.importPictureFrom);
|
||||
} else {
|
||||
filepath = program.importPictureFrom;
|
||||
}
|
||||
flac.importPictureFrom(filepath);
|
||||
flac.save();
|
||||
}
|
||||
if (program.exportPictureTo) {
|
||||
let filepath;
|
||||
if (!path.isAbsolute(program.exportPictureTo)) {
|
||||
filepath = path.resolve(process.cwd(), program.exportPictureTo);
|
||||
} else {
|
||||
filepath = program.exportPictureTo;
|
||||
}
|
||||
flac.exportPictureTo(filepath);
|
||||
}
|
||||
|
||||
if (program.listPicture) {
|
||||
flac.getPicturesSpecs().forEach((spec) => console.log(spec));
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(`Error: ${e.message}`);
|
||||
process.exit(1);
|
||||
}
|
480
buildfiles/app/node_modules/metaflac-js2/index.js
generated
vendored
Normal file
480
buildfiles/app/node_modules/metaflac-js2/index.js
generated
vendored
Normal file
@ -0,0 +1,480 @@
|
||||
const fs = require('fs');
|
||||
const imageSize = require('probe-image-size');
|
||||
const formatVorbisComment = require('./lib/formatVorbisComment');
|
||||
|
||||
const BLOCK_TYPE = {
|
||||
0: 'STREAMINFO',
|
||||
1: 'PADDING',
|
||||
2: 'APPLICATION',
|
||||
3: 'SEEKTABLE',
|
||||
4: 'VORBIS_COMMENT', // There may be only one VORBIS_COMMENT block in a stream.
|
||||
5: 'CUESHEET',
|
||||
6: 'PICTURE',
|
||||
};
|
||||
|
||||
const STREAMINFO = 0;
|
||||
const PADDING = 1;
|
||||
const APPLICATION = 2;
|
||||
const SEEKTABLE = 3;
|
||||
const VORBIS_COMMENT = 4;
|
||||
const CUESHEET = 5;
|
||||
const PICTURE = 6;
|
||||
|
||||
class Metaflac {
|
||||
constructor(flac) {
|
||||
if (typeof flac !== 'string' && !Buffer.isBuffer(flac)) {
|
||||
throw new Error('Metaflac(flac) flac must be string or buffer.');
|
||||
}
|
||||
this.flac = flac;
|
||||
this.buffer = null;
|
||||
this.marker = '';
|
||||
this.streamInfo = null;
|
||||
this.blocks = [];
|
||||
this.padding = null;
|
||||
this.vorbisComment = null;
|
||||
this.vendorString = '';
|
||||
this.tags = [];
|
||||
this.pictures = [];
|
||||
this.picturesSpecs = [];
|
||||
this.picturesDatas = [];
|
||||
this.framesOffset = 0;
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
typeof this.flac === 'string' ? (this.buffer = fs.readFileSync(this.flac)) : (this.buffer = this.flac);
|
||||
|
||||
let offset = 0;
|
||||
const marker = this.buffer.slice(0, (offset += 4)).toString('ascii');
|
||||
if (marker !== 'fLaC') {
|
||||
throw new Error('The file does not appear to be a FLAC file.');
|
||||
}
|
||||
|
||||
let blockType = 0;
|
||||
let isLastBlock = false;
|
||||
while (!isLastBlock) {
|
||||
blockType = this.buffer.readUInt8(offset++);
|
||||
isLastBlock = blockType > 128;
|
||||
blockType = blockType % 128;
|
||||
// console.log('Block Type: %d %s', blockType, BLOCK_TYPE[blockType]);
|
||||
|
||||
const blockLength = this.buffer.readUIntBE(offset, 3);
|
||||
offset += 3;
|
||||
// console.log('Offset: %d', offset);
|
||||
|
||||
if (blockType === STREAMINFO) {
|
||||
this.streamInfo = this.buffer.slice(offset, offset + blockLength);
|
||||
}
|
||||
|
||||
/*
|
||||
if (blockType === PADDING) {
|
||||
this.padding = this.buffer.slice(offset, offset + blockLength);
|
||||
}
|
||||
*/
|
||||
|
||||
if (blockType === VORBIS_COMMENT) {
|
||||
this.vorbisComment = this.buffer.slice(offset, offset + blockLength);
|
||||
this.parseVorbisComment();
|
||||
}
|
||||
|
||||
/*
|
||||
if (blockType === PICTURE) {
|
||||
this.pictures.push(this.buffer.slice(offset, offset + blockLength));
|
||||
this.parsePictureBlock();
|
||||
}
|
||||
*/
|
||||
|
||||
if ([APPLICATION, SEEKTABLE, CUESHEET].includes(blockType)) {
|
||||
this.blocks.push([blockType, this.buffer.slice(offset, offset + blockLength)]);
|
||||
}
|
||||
// console.log('Block Length: %d', blockLength);
|
||||
offset += blockLength;
|
||||
}
|
||||
this.framesOffset = offset;
|
||||
// console.log('Total Length: %d', offset);
|
||||
}
|
||||
|
||||
parseVorbisComment() {
|
||||
const vendorLength = this.vorbisComment.readUInt32LE(0);
|
||||
// console.log('Vendor length: %d', vendorLength);
|
||||
this.vendorString = this.vorbisComment.slice(4, vendorLength + 4).toString('utf8');
|
||||
// console.log('Vendor string: %s', this.vendorString);
|
||||
/*
|
||||
const userCommentListLength = this.vorbisComment.readUInt32LE(4 + vendorLength);
|
||||
// console.log('user_comment_list_length: %d', userCommentListLength);
|
||||
const userCommentListBuffer = this.vorbisComment.slice(4 + vendorLength + 4);
|
||||
for (let offset = 0; offset < userCommentListBuffer.length; ) {
|
||||
const length = userCommentListBuffer.readUInt32LE(offset);
|
||||
offset += 4;
|
||||
const comment = userCommentListBuffer.slice(offset, offset += length).toString('utf8');
|
||||
// console.log('Comment length: %d, this.buffer: %s', length, comment);
|
||||
this.tags.push(comment);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
parsePictureBlock() {
|
||||
this.pictures.forEach((picture) => {
|
||||
let offset = 0;
|
||||
const type = picture.readUInt32BE(offset);
|
||||
offset += 4;
|
||||
const mimeTypeLength = picture.readUInt32BE(offset);
|
||||
offset += 4;
|
||||
const mime = picture.slice(offset, offset + mimeTypeLength).toString('ascii');
|
||||
offset += mimeTypeLength;
|
||||
const descriptionLength = picture.readUInt32BE(offset);
|
||||
offset += 4;
|
||||
const description = picture.slice(offset, (offset += descriptionLength)).toString('utf8');
|
||||
const width = picture.readUInt32BE(offset);
|
||||
offset += 4;
|
||||
const height = picture.readUInt32BE(offset);
|
||||
offset += 4;
|
||||
const depth = picture.readUInt32BE(offset);
|
||||
offset += 4;
|
||||
const colors = picture.readUInt32BE(offset);
|
||||
offset += 4;
|
||||
const pictureDataLength = picture.readUInt32BE(offset);
|
||||
offset += 4;
|
||||
this.picturesDatas.push(picture.slice(offset, offset + pictureDataLength));
|
||||
this.picturesSpecs.push(
|
||||
this.buildSpecification({
|
||||
type,
|
||||
mime,
|
||||
description,
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
colors,
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
getPicturesSpecs() {
|
||||
return this.picturesSpecs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MD5 signature from the STREAMINFO block.
|
||||
*/
|
||||
getMd5sum() {
|
||||
return this.streamInfo.slice(18, 34).toString('hex');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the minimum block size from the STREAMINFO block.
|
||||
*/
|
||||
getMinBlocksize() {
|
||||
return this.streamInfo.readUInt16BE(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum block size from the STREAMINFO block.
|
||||
*/
|
||||
getMaxBlocksize() {
|
||||
return this.streamInfo.readUInt16BE(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the minimum frame size from the STREAMINFO block.
|
||||
*/
|
||||
getMinFramesize() {
|
||||
return this.streamInfo.readUIntBE(4, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum frame size from the STREAMINFO block.
|
||||
*/
|
||||
getMaxFramesize() {
|
||||
return this.streamInfo.readUIntBE(7, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sample rate from the STREAMINFO block.
|
||||
*/
|
||||
getSampleRate() {
|
||||
// 20 bits number
|
||||
return this.streamInfo.readUIntBE(10, 3) >> 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of channels from the STREAMINFO block.
|
||||
*/
|
||||
getChannels() {
|
||||
// 3 bits
|
||||
return this.streamInfo.readUIntBE(10, 3) & (0x00000f >> 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the # of bits per sample from the STREAMINFO block.
|
||||
*/
|
||||
getBps() {
|
||||
return this.streamInfo.readUIntBE(12, 2) & (0x01f0 >> 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the total # of samples from the STREAMINFO block.
|
||||
*/
|
||||
getTotalSamples() {
|
||||
return this.streamInfo.readUIntBE(13, 5) & 0x0fffffffff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the vendor string from the VORBIS_COMMENT block.
|
||||
*/
|
||||
getVendorTag() {
|
||||
return this.vendorString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all tags where the the field name matches NAME.
|
||||
*
|
||||
* @param {string} name
|
||||
*/
|
||||
getTag(name) {
|
||||
return this.tags
|
||||
.filter((item) => {
|
||||
const itemName = item.split('=')[0];
|
||||
return itemName === name;
|
||||
})
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all tags whose field name is NAME.
|
||||
*
|
||||
* @param {string} name
|
||||
*/
|
||||
removeTag(name) {
|
||||
this.tags = this.tags.filter((item) => {
|
||||
const itemName = item.split('=')[0];
|
||||
return itemName !== name;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove first tag whose field name is NAME.
|
||||
*
|
||||
* @param {string} name
|
||||
*/
|
||||
removeFirstTag(name) {
|
||||
const found = this.tags.findIndex((item) => {
|
||||
return item.split('=')[0] === name;
|
||||
});
|
||||
if (found !== -1) {
|
||||
this.tags.splice(found, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all tags, leaving only the vendor string.
|
||||
*/
|
||||
removeAllTags() {
|
||||
this.tags = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a tag.
|
||||
* The FIELD must comply with the Vorbis comment spec, of the form NAME=VALUE. If there is currently no tag block, one will be created.
|
||||
*
|
||||
* @param {string} field
|
||||
*/
|
||||
setTag(field) {
|
||||
if (field.indexOf('=') === -1) {
|
||||
throw new Error(`malformed vorbis comment field "${field}", field contains no '=' character`);
|
||||
}
|
||||
this.tags.push(field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Like setTag, except the VALUE is a filename whose contents will be read verbatim to set the tag value.
|
||||
*
|
||||
* @param {string} field
|
||||
*/
|
||||
setTagFromFile(field) {
|
||||
const position = field.indexOf('=');
|
||||
if (position === -1) {
|
||||
throw new Error(`malformed vorbis comment field "${field}", field contains no '=' character`);
|
||||
}
|
||||
const name = field.substring(0, position);
|
||||
const filename = field.substr(position + 1);
|
||||
let value;
|
||||
try {
|
||||
value = fs.readFileSync(filename, 'utf8');
|
||||
} catch (e) {
|
||||
throw new Error(`can't open file '${filename}' for '${name}' tag value`);
|
||||
}
|
||||
this.tags.push(`${name}=${value}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import tags from a file.
|
||||
* Each line should be of the form NAME=VALUE.
|
||||
*
|
||||
* @param {string} filename
|
||||
*/
|
||||
importTagsFrom(filename) {
|
||||
const tags = fs.readFileSync(filename, 'utf8').split('\n');
|
||||
tags.forEach((line) => {
|
||||
if (line.indexOf('=') === -1) {
|
||||
throw new Error(`malformed vorbis comment "${line}", contains no '=' character`);
|
||||
}
|
||||
});
|
||||
this.tags = this.tags.concat(tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export tags to a file.
|
||||
* Each line will be of the form NAME=VALUE.
|
||||
*
|
||||
* @param {string} filename
|
||||
*/
|
||||
exportTagsTo(filename) {
|
||||
fs.writeFileSync(filename, this.tags.join('\n'), 'utf8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a picture and store it in a PICTURE metadata block.
|
||||
*
|
||||
* @param {string} filename
|
||||
*/
|
||||
importPicture(picture) {
|
||||
if (!Buffer.isBuffer(picture)) {
|
||||
picture = fs.readFileSync(picture);
|
||||
}
|
||||
|
||||
const dimensions = imageSize.sync(picture);
|
||||
if (!dimensions) {
|
||||
throw new Error('Unable to determine image dimensions');
|
||||
}
|
||||
if (dimensions.mime !== 'image/jpeg' && dimensions.mime !== 'image/png') {
|
||||
throw new Error(`only support image/jpeg and image/png picture temporarily, current import ${mime}`);
|
||||
}
|
||||
|
||||
const spec = this.buildSpecification({
|
||||
mime: dimensions.mime,
|
||||
width: dimensions.width,
|
||||
height: dimensions.height,
|
||||
});
|
||||
|
||||
this.pictures.push(this.buildPictureBlock(picture, spec));
|
||||
this.picturesSpecs.push(spec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export PICTURE block to a file.
|
||||
*
|
||||
* @param {string} filename
|
||||
*/
|
||||
exportPictureTo(filename) {
|
||||
if (this.picturesDatas.length > 0) {
|
||||
fs.writeFileSync(filename, this.picturesDatas[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all tags.
|
||||
*/
|
||||
getAllTags() {
|
||||
return this.tags;
|
||||
}
|
||||
|
||||
buildSpecification(spec = {}) {
|
||||
const defaults = {
|
||||
type: 3,
|
||||
mime: 'image/jpeg',
|
||||
description: '',
|
||||
width: 0,
|
||||
height: 0,
|
||||
depth: 24,
|
||||
colors: 0,
|
||||
};
|
||||
return Object.assign(defaults, spec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a picture block.
|
||||
*
|
||||
* @param {Buffer} picture
|
||||
* @param {Object} specification
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
buildPictureBlock(picture, specification = {}) {
|
||||
const pictureType = Buffer.alloc(4);
|
||||
const mimeLength = Buffer.alloc(4);
|
||||
const mime = Buffer.from(specification.mime, 'ascii');
|
||||
const descriptionLength = Buffer.alloc(4);
|
||||
const description = Buffer.from(specification.description, 'utf8');
|
||||
const width = Buffer.alloc(4);
|
||||
const height = Buffer.alloc(4);
|
||||
const depth = Buffer.alloc(4);
|
||||
const colors = Buffer.alloc(4);
|
||||
const pictureLength = Buffer.alloc(4);
|
||||
|
||||
pictureType.writeUInt32BE(specification.type);
|
||||
mimeLength.writeUInt32BE(specification.mime.length);
|
||||
descriptionLength.writeUInt32BE(specification.description.length);
|
||||
width.writeUInt32BE(specification.width);
|
||||
height.writeUInt32BE(specification.height);
|
||||
depth.writeUInt32BE(specification.depth);
|
||||
colors.writeUInt32BE(specification.colors);
|
||||
pictureLength.writeUInt32BE(picture.length);
|
||||
|
||||
return Buffer.concat([
|
||||
pictureType,
|
||||
mimeLength,
|
||||
mime,
|
||||
descriptionLength,
|
||||
description,
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
colors,
|
||||
pictureLength,
|
||||
picture,
|
||||
]);
|
||||
}
|
||||
|
||||
buildMetadataBlock(type, block, isLast = false) {
|
||||
const header = Buffer.alloc(4);
|
||||
if (isLast) {
|
||||
type += 128;
|
||||
}
|
||||
header.writeUIntBE(type, 0, 1);
|
||||
header.writeUIntBE(block.length, 1, 3);
|
||||
return Buffer.concat([header, block]);
|
||||
}
|
||||
|
||||
buildMetadata() {
|
||||
const bufferArray = [];
|
||||
bufferArray.push(this.buildMetadataBlock(STREAMINFO, this.streamInfo));
|
||||
this.blocks.forEach((block) => {
|
||||
bufferArray.push(this.buildMetadataBlock(...block));
|
||||
});
|
||||
bufferArray.push(this.buildMetadataBlock(VORBIS_COMMENT, formatVorbisComment(this.vendorString, this.tags)));
|
||||
this.pictures.forEach((block) => {
|
||||
bufferArray.push(this.buildMetadataBlock(PICTURE, block));
|
||||
});
|
||||
if (this.padding == null) this.padding = Buffer.alloc(16384);
|
||||
bufferArray.push(this.buildMetadataBlock(PADDING, this.padding, true));
|
||||
return bufferArray;
|
||||
}
|
||||
|
||||
buildStream() {
|
||||
const metadata = this.buildMetadata();
|
||||
return [this.buffer.slice(0, 4), ...metadata, this.buffer.slice(this.framesOffset)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Save change to file or return changed buffer.
|
||||
*/
|
||||
save() {
|
||||
if (typeof this.flac === 'string') {
|
||||
fs.writeFileSync(this.flac, Buffer.concat(this.buildStream()));
|
||||
} else {
|
||||
return Buffer.concat(this.buildStream());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Metaflac;
|
21
buildfiles/app/node_modules/metaflac-js2/lib/formatVorbisComment.js
generated
vendored
Normal file
21
buildfiles/app/node_modules/metaflac-js2/lib/formatVorbisComment.js
generated
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
module.exports = (vendorString, commentList) => {
|
||||
const bufferArray = [];
|
||||
const vendorStringBuffer = Buffer.from(vendorString, 'utf8');
|
||||
const vendorLengthBuffer = Buffer.alloc(4);
|
||||
vendorLengthBuffer.writeUInt32LE(vendorStringBuffer.length);
|
||||
|
||||
const userCommentListLengthBuffer = Buffer.alloc(4);
|
||||
userCommentListLengthBuffer.writeUInt32LE(commentList.length);
|
||||
|
||||
bufferArray.push(vendorLengthBuffer, vendorStringBuffer, userCommentListLengthBuffer);
|
||||
|
||||
for (let i = 0; i < commentList.length; i++) {
|
||||
const comment = commentList[i];
|
||||
const commentBuffer = Buffer.from(comment, 'utf8');
|
||||
const lengthBuffer = Buffer.alloc(4);
|
||||
lengthBuffer.writeUInt32LE(commentBuffer.length);
|
||||
bufferArray.push(lengthBuffer, commentBuffer);
|
||||
}
|
||||
|
||||
return Buffer.concat(bufferArray);
|
||||
};
|
62
buildfiles/app/node_modules/metaflac-js2/package.json
generated
vendored
Normal file
62
buildfiles/app/node_modules/metaflac-js2/package.json
generated
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
{
|
||||
"_args": [
|
||||
[
|
||||
"metaflac-js2@1.0.7",
|
||||
"/home/shihaam/www/freezer.shihaam.me/app"
|
||||
]
|
||||
],
|
||||
"_from": "metaflac-js2@1.0.7",
|
||||
"_id": "metaflac-js2@1.0.7",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-iHLEepKmMp7BuxsGwaUnaef3b+OPouDtEkDLsgzspkbAsjTLXA/Yawn1e1wsYqAF4EtmERdpww/bYFCnDWfG8w==",
|
||||
"_location": "/metaflac-js2",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "version",
|
||||
"registry": true,
|
||||
"raw": "metaflac-js2@1.0.7",
|
||||
"name": "metaflac-js2",
|
||||
"escapedName": "metaflac-js2",
|
||||
"rawSpec": "1.0.7",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "1.0.7"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/metaflac-js2/-/metaflac-js2-1.0.7.tgz",
|
||||
"_spec": "1.0.7",
|
||||
"_where": "/home/shihaam/www/freezer.shihaam.me/app",
|
||||
"author": {
|
||||
"name": "Sayem Chowdhury"
|
||||
},
|
||||
"bin": {
|
||||
"metaflac-js": "cli.js"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/d-fi/metaflac-js2/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": "^3.0.1",
|
||||
"probe-image-size": "^5.0.0"
|
||||
},
|
||||
"description": "A pure JavaScript implementation of the metaflac (official FLAC tool)",
|
||||
"homepage": "https://github.com/d-fi/metaflac-js2#readme",
|
||||
"keywords": [
|
||||
"metaflac",
|
||||
"flac",
|
||||
"metadata",
|
||||
"writer"
|
||||
],
|
||||
"license": "ISC",
|
||||
"main": "index.js",
|
||||
"name": "metaflac-js2",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/d-fi/metaflac-js2.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"version": "1.0.7"
|
||||
}
|
Reference in New Issue
Block a user