-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.js
101 lines (88 loc) · 3.02 KB
/
main.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
'use strict'
const cp = require('child_process')
const http = require('http')
const ask = require('./ask')
const upnp = require('./upnp')
// Handle CTRL+C
process.on('SIGINT', () => {
console.log('\nbye')
process.exit()
})
// https://nodejs.org/api/http.html#http_http_get_url_options_callback
function stream(url) {
const req = http.get(url, (res) => {
console.log(res.statusCode, res.statusMessage)
console.log(res.headers)
let bytes = 0
res.on('error', (err) => {
console.error(err)
})
res.on('data', (chunk) => {
bytes += chunk.length
process.stdout.write('.')
})
res.on('end', () => {
const ok = bytes == res.headers['content-length']
console.log(`\nactual bytes downloaded = ${bytes} (ok=${ok})`)
})
})
}
// `ffplay` is included in FFmpeg (https://ffmpeg.org/)
// `gst-play-1.0` is included in GStreamer (https://gstreamer.freedesktop.org/)
function play(url) {
//const cmd = `ffplay -nodisp -loglevel quiet -autoexit -t 10 ${url}`
const cmd = `gst-play-1.0 ${url}`
console.log(cmd)
const args = cmd.split(' ')
const player = cp.spawn(args[0], args.slice(1), {stdio: 'inherit'})
player.on('close', () => console.log('bye'))
}
async function browse(mediaServers) {
const orange = 208
const cyan = 14
let choices
let answer
// Ask user to choose media server
choices = mediaServers.map(mediaServer => mediaServer.friendlyName + '/')
answer = await ask(choices, {color: orange})
console.log(`\x1b[38;5;${orange}m${choices[answer]}\x1b[0m`)
// Browse directories and files
const mediaServer = mediaServers[answer]
let objectId = 0
let isContainer = true
let choice
while (isContainer) {
const contents = await mediaServer.browse(objectId)
if (contents.length === 0) break
choices = contents.map(content => content.isContainer ? content.title + '/' : content.title)
console.log(`What do you want to listen today? (${choices.length})`)
answer = await ask(choices, {color: cyan})
console.log(`\x1b[38;5;${cyan}m${choices[answer]}\x1b[0m`)
choice = contents[answer]
objectId = choice.id
isContainer = choice.isContainer
}
console.log(choice)
if (choice.url) play(choice.url) // call stream() or play()
}
function main() {
const mediaServers = []
const watcher = upnp.discover()
watcher.on('error', (err) => {
console.error(`discover error:\n${err}`)
})
watcher.on('listening', (address) => {
//console.log(`Local client listening on ${address.address}:${address.port}`)
})
watcher.on('mediaServer', (mediaServer) => {
mediaServers.push(mediaServer)
console.log(mediaServer)
})
watcher.on('end', () => {
console.log(`Found ${mediaServers.length} media servers.`)
if (mediaServers.length > 0) {
browse(mediaServers).catch(err => console.error(err))
}
})
}
main()