UNPKG

icecast-stack

Version:

A `StreamStack` implementation for parsing and/or injecting metadata with SHOUTcast/Icecast radio streams.

68 lines (58 loc) 2.47 kB
var net = require('net') , parse = require('url').parse , HttpRequestStack = require('http-stack').HttpRequestStack , IcecastReadStack = require('./icecast-stack').IcecastReadStack /** * A full-blown Icecast/SHOUTcast compliant Client class. Conveniently takes * care of creating a low-level TCP connection, sending an HTTP request, and * filtering the 'metadata' events out of the resulting audio stream. */ function Client(url, headers, retainMetadata) { // parse the URL into a usable object var parsedUrl = parse(url); // ensure an HTTP based path and port parsedUrl.pathname = parsedUrl.pathname || '/'; parsedUrl.port || (parsedUrl.port = parsedUrl.protocol == "https:" ? 443 : 80); // Create the low-level TCP connection to the remote server. var stream = net.createConnection(parsedUrl.port, parsedUrl.hostname); stream.allowHalfOpen = true; stream.remoteAddress = parsedUrl.hostname; stream.remotePort = parsedUrl.port; // Stack an 'HttpRequstStack' instance on it, and send an HTTP request // to the specified URL. stream = new HttpRequestStack(stream); headers.push('Host: ' + parsedUrl.host); headers.push('Icy-MetaData: 1'); stream.get(parsedUrl.pathname, headers); stream.end(); // Next stack "this" 'IcecastReadStack' instance on top of that, setting the // inital 'metaint' value to Infinity. Setting to Infinity is just a hack // that allows us to have the 'createClient' function return immediately, // instead of invoking a callback with the stream instance. IcecastReadStack.call(this, stream, Infinity, retainMetadata); // Keep a reference to the URL used to connect to the Icecast server. this.url = url; // When the 'response' event is fired (bubbled down from the // HttpRequestStack instance), check for the 'icy-metaint' response header. this.on('response', function(res) { this.headers = res.headers; if (res.headers['icy-metaint']) { this.metaint = Number(res.headers['icy-metaint']); } }); } exports.Client = Client; require('util').inherits(Client, IcecastReadStack); /** * Convenience function to create a new Icecast 'Client' instance. */ function createClient(url, headers, retainMetadata) { if (headers === true || headers === false) { retainMetadata = headers; headers = []; } else if (!Array.isArray(headers)) { headers = []; } return new Client(url, headers, retainMetadata); } exports.createClient = createClient;