Skip to content

Commit

Permalink
first version
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaodoudou committed May 12, 2018
1 parent 5c6830d commit 9ef3b5f
Show file tree
Hide file tree
Showing 15 changed files with 9,357 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# http://editorconfig.org

root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
max_line_length = null
25 changes: 25 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"extends": [
"standard"
],
"plugins": [
"sort-class-members"
],
"rules": {
"sort-class-members/sort-class-members": [
2,
{
"order": [
"[static-properties]",
"[static-methods]",
"[properties]",
"[conventional-private-properties]",
"constructor",
"[methods]",
"[conventional-private-methods]"
],
"accessorPairPositioning": "getThenSet"
}
]
}
}
10 changes: 10 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
"dbaeumer.vscode-eslint",
"af4jm.vscode-m3u",
"EditorConfig.editorconfig"
]
}
Empty file added README.md
Empty file.
74 changes: 74 additions & 0 deletions config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
var fs = require('fs')
var template = require('./template.json')
const _ = require('lodash')
const Q = require('q')
const Logger = new (require('./logger'))()

class Config {
constructor () {
// Declares
this.filename = 'settings.json'

// Bindings
this.init = this.init.bind(this)
this.readSettings = this.readSettings.bind(this)
this.mergeWriteSettings = this.mergeWriteSettings.bind(this)
}

init () {
Logger.verbose('Getting settings...')
const deferred = Q.defer()
Q.fcall(this.readSettings)
.then(this.mergeWriteSettings)
.then((settings) => {
Logger.verbose('Has resolve settings')
deferred.resolve(settings)
})
.catch(error => {
Logger.error('Error happen during setting pulling:', error)
process.exit()
})
return deferred.promise
}

readSettings () {
const deferred = Q.defer()
Logger.verbose('Reading file...')
fs.readFile(this.filename, 'utf8', (error, data) => {
if (error) {
if (_.get(error, 'code', '?') === 'ENOENT') {
Logger.verbose("Didn't found file, injecting template...")
deferred.resolve(template)
} else {
Logger.verbose('Error happen', error)
deferred.reject(error)
}
} else {
Logger.verbose('Found file...')
try {
const settings = JSON.parse(data)
deferred.resolve(settings)
} catch (error) {
deferred.reject(error)
}
}
})
return deferred.promise
}

mergeWriteSettings (userSettings) {
const deferred = Q.defer()
const settings = _.merge({}, template, userSettings)
const json = JSON.stringify(settings, null, 2)
fs.writeFile(this.filename, json, 'utf8', (error) => {
if (error) {
deferred.reject(error)
} else {
deferred.resolve(settings)
}
})
return deferred.promise
}
}

module.exports = Config
49 changes: 49 additions & 0 deletions dataStream.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
const EventEmitter = require('events')

class DataStream extends EventEmitter {
constructor () {
super()

// Declares
this._chunks = []
this.listeners = 0
this.isEnded = false

// Bindings
this.tick = this.tick.bind(this)
this.write = this.write.bind(this)
this.end = this.end.bind(this)

// Init
this.tick()
}

tick () {
var hasData = this._chunks.length !== 0
while (this._chunks.length) {
const chunk = this._chunks.shift()
this.emit('data', chunk)
}
if (hasData && this._chunks.length === 0) {
this.emit('empty')
}
if (!this.isEnded) {
setTimeout(() => {
this.tick()
}, 100)
}
}

write (chunck) {
this._chunks.push(chunck)
}

end () {
process.nextTick(() => {
this.isEnded = true
this.emit('end')
})
}
}

module.exports = DataStream
160 changes: 160 additions & 0 deletions dvr.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
const _ = require('lodash')
const SSDP = require('node-ssdp').Server
const Logger = new (require('./logger'))()

class DVR {
constructor (server) {
// Declares
this.version = {
major: 0,
minor: 1
}
this.server = server
this.express = this.server.express
this.scanPossible = 0
this.scanInProgress = 0
this.friendlyName = this.server.settings.serverName
this.manufacturer = 'Silicondust'
this.modelName = 'HDHR - Plex - IPTV'
this.modelNumber = 'HDHR-PLEX-IPTV'
this.serialNumber = '001002003'
this.deviceId = '0123456789'
this.firmwareVersion = `${this.version.major}.${this.version.minor}`
this.firmwareName = `plex-iptv-${this.firmwareVersion}`
this.tunerCount = this.server.settings.tunerCount
this.deviceAuth = 'user123'
this.lineupUrl = '/lineup.json'
this.scanUrl = '/lineup.post'
this.lineStatusUrl = '/lineup_status.json'
this.discoverUrl = '/discover.json'
this.deviceUrl = '/device.xml'

// Bindings
this.init = this.init.bind(this)
this.channels = this.channels.bind(this)
this.lineup = this.lineup.bind(this)
this.scan = this.scan.bind(this)
this.lineupStatus = this.lineupStatus.bind(this)
this.discover = this.discover.bind(this)
this.device = this.device.bind(this)
}

init () {
this.express.use(this.lineupUrl, this.lineup)
this.express.use(this.scanUrl, this.scan)
this.express.use(this.lineStatusUrl, this.lineupStatus)
this.express.use(this.discoverUrl, this.discover)
this.express.use(this.deviceUrl, this.device)

const ssdpServer = new SSDP({
location: {
port: this.express.serverPort,
path: '/device.xml'
},
allowWildcards: true,
ssdpSig: `${this.friendlyName}/${this.firmwareVersion} UPnP/1.0`
})

ssdpServer.addUSN('upnp:rootdevice')
ssdpServer.addUSN('urn:schemas-upnp-org:device:MediassdpServer:1')
ssdpServer.addUSN('urn:schemas-upnp-org:service:ContentDirectory:1')
ssdpServer.addUSN('urn:schemas-upnp-org:service:ConnectionManager:1')
ssdpServer.start()
Logger.verbose('DVR is now initiated.')
}

channels (req) {
let hostname = `http://localhost:${this.express.serverPort}`
if (!_.isUndefined(req)) {
hostname = req.protocol + '://' + req.get('host')
}
const lines = []
_.forEach(this.server.channels, (line) => {
lines.push({
GuideNumber: line.channel,
GuideName: line.name,
URL: `${hostname}/channel/${line.channel}`
})
})
Logger.verbose(`Return ${lines.length} channels.`)
return lines
}

lineup (req, res, next) {
Logger.verbose(`Received a lineup request.`)
res.json(this.channels(req))
}

scan (req, res, next) {
// TODO Need to know what Plex is expecting to simulate properly a scan
Logger.verbose(`Received a scan request.`)
this.scanPossible = 0
this.scanInProgress = 1
setTimeout(() => {
res.json(this.status())
process.nextTick(() => {
this.scanPossible = 1
this.scanInProgress = 0
})
}, 5000)
}

status () {
const status = {
ScanInProgress: this.scanInProgress,
ScanPossible: this.scanPossible,
Source: 'Cable',
SourceList: ['Cable']
}
return status
}

lineupStatus (req, res, next) {
Logger.verbose(`Received a lineup status request.`)
res.json(this.status())
}

discover (req, res, next) {
Logger.verbose(`Received a discover request.`)
var baseUrl = req.protocol + '://' + req.get('host')
const status = {
FriendlyName: this.friendlyName,
Manufacturer: this.manufacturer,
ModelNumber: this.modelName,
FirmwareName: this.firmwareName,
TunerCount: this.tunerCount,
FirmwareVersion: this.firmwareVersion,
DeviceID: this.deviceId,
DeviceAuth: this.deviceAuth,
BaseURL: baseUrl,
LineupURL: `${baseUrl}${this.lineupUrl}`
}
res.json(status)
}

device (req, res, next) {
Logger.verbose(`Received a device identify request.`)
var baseUrl = req.protocol + '://' + req.get('host')
const xmlContent =
`<root xmlns="urn:schemas-upnp-org:device-1-0">
<specVersion>
<major>${this.version.major}</major>
<minor>${this.version.minor}</minor>
</specVersion>
<URLBase>${baseUrl}</URLBase>
<device>
<deviceType>urn:schemas-upnp-org:device:MediaServer:1</deviceType>
<friendlyName>${this.friendlyName}</friendlyName>
<manufacturer>${this.manufacturer}</manufacturer>
<modelName>${this.modelName}</modelName>
<modelNumber>${this.modelNumber}</modelNumber>
<serialNumber>${this.serialNumber}</serialNumber>
<UDN>uuid:${this.deviceId}</UDN>
</device>
</root>`
res.set('Content-Type', 'text/xml')
res.send(xmlContent)
}
}

module.exports = DVR
Loading

0 comments on commit 9ef3b5f

Please sign in to comment.