forked from TooTallNate/nTunes
-
Notifications
You must be signed in to change notification settings - Fork 0
/
handlers.js
149 lines (128 loc) · 4.8 KB
/
handlers.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
var fs = require("fs");
var sys = require("sys");
var http = require("http");
var Step = require("step");
var im = require("imagemagick");
var helpers = require("helpers");
var nSpecifier = require("nTunes-specifier");
var playlistParser = require("radio-playlist-parser");
/* Here are the custom "handlers" that come packaged with nTunes. These
* are the most common functionality missing from the standard iTunes API.
*/
module.exports = function(CLASSES) {
// A handler for "file tracks" which first looks up the 'location' of the
// specified track, then streams the file to the HTTP client.
// Meant to be played back with HTML5 <audio>, <video>, Flash, etc.
CLASSES["track"].addHandler("raw", function(req, res, nTunes) {
// First we get the "location" and "kind" of the specified track.
// TODO: Add a pre-check to ensure that this is a single track, and not a list.
var parent = this.parent();
Step(
function() {
parent.get("location", "kind", this);
},
function(err, location, kind) {
if (err) {
return nTunes.sendNTunesResponse(res, 500, null, {
error: err
});
}
if (location == 'missing value') {
return nTunes.sendNTunesResponse(res, 500, null, {
error: new Error("Can't find track. Check file location.")
});
}
// Make sure that we got a String, and not an Array.
// An array would mean the user requested 'raw' on a list of tracks (we
// can only do single tracks).
if (Array.isArray(location)) {
res.writeHead(400, {});
return res.end('cannot call "raw" on lists.');
}
// Now that we have a filename, we must serve the raw media file back
// to the client over HTTP.
helpers.serveStaticFile(req, res, location);
}
);
});
// The 'streams' handler on 'URL track's first retrieves the "address" of
// URL track, which is a URL to an iTunes redirecting service.
// "radio-playlist-parser.js" retrieves the remote file and parses it,
// ultimately returning an Array of absolute URLs to infinite audio streams
// of the 'URL track'.
CLASSES["track"].addHandler("streams", function(req, res, nTunes) {
// First we're gonna want to get the address of the requested URL track.
// TODO: Add a check to ensure that this is a single track, and not a list.
var parent = this.parent();
Step(
function() {
parent.get("address", this);
},
function(err, address) {
if (err) throw err;
playlistParser.getPlaylist(address, this);
},
function(err, playlist) {
if (err) {
return nTunes.sendNTunesResponse(res, 500, null, {
error: err
});
}
nTunes.sendNTunesResponse(res, 200, null, playlist);
}
);
});
// The 'raw' handler on the 'artwork' class has a similar concept to the raw
// for the 'tracks' class: it returns a browser-ready Image with the proper
// "Content-Type" header (determined from the 'format' property), etc.
CLASSES["artwork"].addHandler("raw", function(req, res, nTunes) {
// First we're gonna get the "format" and the "raw data" of the
// requested "artwork".
var parent = this.parent();
Step(
function() {
parent.get("format", "raw data", this);
},
function(err, format, rawData) {
if (err) throw err;
// Inspect the "format" property to determine whether it's a
// JPEG or PNG
if (/JPEG/i.test(format)) {
format = "jpg";
} else if (/PNG/i.test(format)) {
format = "png";
} else {
throw new Error("Unrecognized iTunes Artwork format: \"" + format +'"')
}
var args = req.parsedUrl.query;
if (args) {
if (args.size) args.width = args.height = args.size;
this.parallel()(null, args.format || format);
args.srcData = rawData.toString('binary');
args.srcFormat = format;
args.format = args.format || format;
delete args.dstPath;
im.resize(args, this.parallel());
} else {
// No query params given, just send the original image data.
this.parallel()(null, format);
this.parallel()(null, rawData);
}
},
function(err, format, rawData) {
if (err) {
return nTunes.sendNTunesResponse(res, 500, null, {
error: err
});
}
if (!Buffer.isBuffer(rawData)) {
rawData = new Buffer(rawData, 'binary');
}
// Send the binary image data back to the HTTP client.
nTunes.sendNTunesResponse(res, 200, {
"Content-Type": helpers.mime(format)
}, rawData);
}
);
});
}