@bnhf/prismcast 1.3.4-2026.2.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +7 -0
- package/README.md +347 -0
- package/bin/prismcast +6 -0
- package/dist/app.d.ts +6 -0
- package/dist/app.js +315 -0
- package/dist/app.js.map +1 -0
- package/dist/browser/cdp.d.ts +38 -0
- package/dist/browser/cdp.js +155 -0
- package/dist/browser/cdp.js.map +1 -0
- package/dist/browser/channelSelection.d.ts +65 -0
- package/dist/browser/channelSelection.js +202 -0
- package/dist/browser/channelSelection.js.map +1 -0
- package/dist/browser/display.d.ts +34 -0
- package/dist/browser/display.js +54 -0
- package/dist/browser/display.js.map +1 -0
- package/dist/browser/index.d.ts +205 -0
- package/dist/browser/index.js +1205 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/tuning/fox.d.ts +2 -0
- package/dist/browser/tuning/fox.js +83 -0
- package/dist/browser/tuning/fox.js.map +1 -0
- package/dist/browser/tuning/hbo.d.ts +2 -0
- package/dist/browser/tuning/hbo.js +237 -0
- package/dist/browser/tuning/hbo.js.map +1 -0
- package/dist/browser/tuning/hulu.d.ts +2 -0
- package/dist/browser/tuning/hulu.js +550 -0
- package/dist/browser/tuning/hulu.js.map +1 -0
- package/dist/browser/tuning/sling.d.ts +2 -0
- package/dist/browser/tuning/sling.js +518 -0
- package/dist/browser/tuning/sling.js.map +1 -0
- package/dist/browser/tuning/thumbnailRow.d.ts +2 -0
- package/dist/browser/tuning/thumbnailRow.js +108 -0
- package/dist/browser/tuning/thumbnailRow.js.map +1 -0
- package/dist/browser/tuning/tileClick.d.ts +2 -0
- package/dist/browser/tuning/tileClick.js +103 -0
- package/dist/browser/tuning/tileClick.js.map +1 -0
- package/dist/browser/tuning/youtubeTv.d.ts +2 -0
- package/dist/browser/tuning/youtubeTv.js +182 -0
- package/dist/browser/tuning/youtubeTv.js.map +1 -0
- package/dist/browser/video.d.ts +289 -0
- package/dist/browser/video.js +996 -0
- package/dist/browser/video.js.map +1 -0
- package/dist/channels/index.d.ts +3 -0
- package/dist/channels/index.js +392 -0
- package/dist/channels/index.js.map +1 -0
- package/dist/config/index.d.ts +53 -0
- package/dist/config/index.js +233 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/presets.d.ts +98 -0
- package/dist/config/presets.js +241 -0
- package/dist/config/presets.js.map +1 -0
- package/dist/config/profiles.d.ts +79 -0
- package/dist/config/profiles.js +245 -0
- package/dist/config/profiles.js.map +1 -0
- package/dist/config/providers.d.ts +120 -0
- package/dist/config/providers.js +450 -0
- package/dist/config/providers.js.map +1 -0
- package/dist/config/sites.d.ts +22 -0
- package/dist/config/sites.js +377 -0
- package/dist/config/sites.js.map +1 -0
- package/dist/config/userChannels.d.ts +178 -0
- package/dist/config/userChannels.js +543 -0
- package/dist/config/userChannels.js.map +1 -0
- package/dist/config/userConfig.d.ts +235 -0
- package/dist/config/userConfig.js +913 -0
- package/dist/config/userConfig.js.map +1 -0
- package/dist/hdhr/channelMap.d.ts +21 -0
- package/dist/hdhr/channelMap.js +82 -0
- package/dist/hdhr/channelMap.js.map +1 -0
- package/dist/hdhr/deviceId.d.ts +11 -0
- package/dist/hdhr/deviceId.js +84 -0
- package/dist/hdhr/deviceId.js.map +1 -0
- package/dist/hdhr/discover.d.ts +6 -0
- package/dist/hdhr/discover.js +155 -0
- package/dist/hdhr/discover.js.map +1 -0
- package/dist/hdhr/index.d.ts +9 -0
- package/dist/hdhr/index.js +87 -0
- package/dist/hdhr/index.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +144 -0
- package/dist/index.js.map +1 -0
- package/dist/routes/assets.d.ts +6 -0
- package/dist/routes/assets.js +79 -0
- package/dist/routes/assets.js.map +1 -0
- package/dist/routes/auth.d.ts +6 -0
- package/dist/routes/auth.js +77 -0
- package/dist/routes/auth.js.map +1 -0
- package/dist/routes/channels.d.ts +6 -0
- package/dist/routes/channels.js +40 -0
- package/dist/routes/channels.js.map +1 -0
- package/dist/routes/components.d.ts +138 -0
- package/dist/routes/components.js +210 -0
- package/dist/routes/components.js.map +1 -0
- package/dist/routes/config.d.ts +72 -0
- package/dist/routes/config.js +1977 -0
- package/dist/routes/config.js.map +1 -0
- package/dist/routes/debug.d.ts +6 -0
- package/dist/routes/debug.js +274 -0
- package/dist/routes/debug.js.map +1 -0
- package/dist/routes/health.d.ts +6 -0
- package/dist/routes/health.js +85 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/hls.d.ts +6 -0
- package/dist/routes/hls.js +25 -0
- package/dist/routes/hls.js.map +1 -0
- package/dist/routes/index.d.ts +19 -0
- package/dist/routes/index.js +49 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/logs.d.ts +6 -0
- package/dist/routes/logs.js +164 -0
- package/dist/routes/logs.js.map +1 -0
- package/dist/routes/mpegts.d.ts +6 -0
- package/dist/routes/mpegts.js +19 -0
- package/dist/routes/mpegts.js.map +1 -0
- package/dist/routes/play.d.ts +6 -0
- package/dist/routes/play.js +18 -0
- package/dist/routes/play.js.map +1 -0
- package/dist/routes/playlist.d.ts +36 -0
- package/dist/routes/playlist.js +134 -0
- package/dist/routes/playlist.js.map +1 -0
- package/dist/routes/root.d.ts +6 -0
- package/dist/routes/root.js +2920 -0
- package/dist/routes/root.js.map +1 -0
- package/dist/routes/streams.d.ts +6 -0
- package/dist/routes/streams.js +88 -0
- package/dist/routes/streams.js.map +1 -0
- package/dist/routes/theme.d.ts +15 -0
- package/dist/routes/theme.js +275 -0
- package/dist/routes/theme.js.map +1 -0
- package/dist/routes/ui.d.ts +56 -0
- package/dist/routes/ui.js +354 -0
- package/dist/routes/ui.js.map +1 -0
- package/dist/service/commands.d.ts +41 -0
- package/dist/service/commands.js +391 -0
- package/dist/service/commands.js.map +1 -0
- package/dist/service/generators.d.ts +33 -0
- package/dist/service/generators.js +432 -0
- package/dist/service/generators.js.map +1 -0
- package/dist/service/index.d.ts +2 -0
- package/dist/service/index.js +7 -0
- package/dist/service/index.js.map +1 -0
- package/dist/streaming/clients.d.ts +48 -0
- package/dist/streaming/clients.js +114 -0
- package/dist/streaming/clients.js.map +1 -0
- package/dist/streaming/fmp4Segmenter.d.ts +61 -0
- package/dist/streaming/fmp4Segmenter.js +461 -0
- package/dist/streaming/fmp4Segmenter.js.map +1 -0
- package/dist/streaming/hls.d.ts +120 -0
- package/dist/streaming/hls.js +722 -0
- package/dist/streaming/hls.js.map +1 -0
- package/dist/streaming/hlsSegments.d.ts +54 -0
- package/dist/streaming/hlsSegments.js +162 -0
- package/dist/streaming/hlsSegments.js.map +1 -0
- package/dist/streaming/lifecycle.d.ts +33 -0
- package/dist/streaming/lifecycle.js +185 -0
- package/dist/streaming/lifecycle.js.map +1 -0
- package/dist/streaming/monitor.d.ts +74 -0
- package/dist/streaming/monitor.js +1310 -0
- package/dist/streaming/monitor.js.map +1 -0
- package/dist/streaming/mp4Parser.d.ts +74 -0
- package/dist/streaming/mp4Parser.js +566 -0
- package/dist/streaming/mp4Parser.js.map +1 -0
- package/dist/streaming/mpegts.d.ts +14 -0
- package/dist/streaming/mpegts.js +248 -0
- package/dist/streaming/mpegts.js.map +1 -0
- package/dist/streaming/registry.d.ts +119 -0
- package/dist/streaming/registry.js +127 -0
- package/dist/streaming/registry.js.map +1 -0
- package/dist/streaming/setup.d.ts +135 -0
- package/dist/streaming/setup.js +670 -0
- package/dist/streaming/setup.js.map +1 -0
- package/dist/streaming/showInfo.d.ts +30 -0
- package/dist/streaming/showInfo.js +362 -0
- package/dist/streaming/showInfo.js.map +1 -0
- package/dist/streaming/statusEmitter.d.ts +125 -0
- package/dist/streaming/statusEmitter.js +139 -0
- package/dist/streaming/statusEmitter.js.map +1 -0
- package/dist/types/index.d.ts +403 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/debugFilter.d.ts +38 -0
- package/dist/utils/debugFilter.js +157 -0
- package/dist/utils/debugFilter.js.map +1 -0
- package/dist/utils/delay.d.ts +6 -0
- package/dist/utils/delay.js +15 -0
- package/dist/utils/delay.js.map +1 -0
- package/dist/utils/errors.d.ts +15 -0
- package/dist/utils/errors.js +40 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/evaluate.d.ts +51 -0
- package/dist/utils/evaluate.js +124 -0
- package/dist/utils/evaluate.js.map +1 -0
- package/dist/utils/ffmpeg.d.ts +65 -0
- package/dist/utils/ffmpeg.js +317 -0
- package/dist/utils/ffmpeg.js.map +1 -0
- package/dist/utils/fileLogger.d.ts +25 -0
- package/dist/utils/fileLogger.js +248 -0
- package/dist/utils/fileLogger.js.map +1 -0
- package/dist/utils/format.d.ts +16 -0
- package/dist/utils/format.js +46 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/html.d.ts +6 -0
- package/dist/utils/html.js +24 -0
- package/dist/utils/html.js.map +1 -0
- package/dist/utils/index.d.ts +15 -0
- package/dist/utils/index.js +20 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logEmitter.d.ts +17 -0
- package/dist/utils/logEmitter.js +30 -0
- package/dist/utils/logEmitter.js.map +1 -0
- package/dist/utils/logger.d.ts +82 -0
- package/dist/utils/logger.js +219 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/m3u.d.ts +32 -0
- package/dist/utils/m3u.js +148 -0
- package/dist/utils/m3u.js.map +1 -0
- package/dist/utils/morganStream.d.ts +7 -0
- package/dist/utils/morganStream.js +33 -0
- package/dist/utils/morganStream.js.map +1 -0
- package/dist/utils/platform.d.ts +64 -0
- package/dist/utils/platform.js +157 -0
- package/dist/utils/platform.js.map +1 -0
- package/dist/utils/retry.d.ts +15 -0
- package/dist/utils/retry.js +82 -0
- package/dist/utils/retry.js.map +1 -0
- package/dist/utils/streamContext.d.ts +28 -0
- package/dist/utils/streamContext.js +33 -0
- package/dist/utils/streamContext.js.map +1 -0
- package/dist/utils/version.d.ts +37 -0
- package/dist/utils/version.js +228 -0
- package/dist/utils/version.js.map +1 -0
- package/package.json +92 -0
- package/prismcast.png +0 -0
- package/prismcast.svg +74 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"userConfig.js","sourceRoot":"","sources":["../../src/config/userConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a single entry in the channel number mapping.
|
|
3
|
+
*/
|
|
4
|
+
export interface ChannelMapEntry {
|
|
5
|
+
key: string;
|
|
6
|
+
name: string;
|
|
7
|
+
number: number;
|
|
8
|
+
stationId?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Builds the channel number mapping from the current channel configuration. Channels with explicit channelNumber values are assigned first, then remaining
|
|
12
|
+
* channels are auto-assigned sequential numbers starting from AUTO_ASSIGN_START, skipping any numbers already claimed by explicit assignments.
|
|
13
|
+
* @returns Array of channel map entries sorted by channel number, excluding noVideo and disabled channels.
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildChannelMap(): ChannelMapEntry[];
|
|
16
|
+
/**
|
|
17
|
+
* Looks up a channel key by its channel number.
|
|
18
|
+
* @param channelNumber - The numeric channel number to look up.
|
|
19
|
+
* @returns The channel key, or undefined if no channel has this number.
|
|
20
|
+
*/
|
|
21
|
+
export declare function getChannelKeyByNumber(channelNumber: number): string | undefined;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/* Copyright(C) 2024-2026, HJD (https://github.com/hjdhjd). All rights reserved.
|
|
2
|
+
*
|
|
3
|
+
* channelMap.ts: Channel key to channel number mapping for HDHomeRun emulation.
|
|
4
|
+
*/
|
|
5
|
+
import { getAllChannels } from "../config/userChannels.js";
|
|
6
|
+
import { resolveProfile } from "../config/profiles.js";
|
|
7
|
+
/* HDHomeRun devices use numeric channel numbers (GuideNumber) for each channel. Plex requires these for EPG (electronic program guide) matching. PrismCast uses
|
|
8
|
+
* string keys (e.g., "cnn", "nbc") for channels, so we need a mapping layer.
|
|
9
|
+
*
|
|
10
|
+
* Channels can optionally specify an explicit channelNumber for precise EPG alignment. Channels without an explicit number get auto-assigned a number starting
|
|
11
|
+
* from 1000. Auto-assigned numbers are deterministic (alphabetically sorted keys get sequential numbers) but not stable across channel additions or removals.
|
|
12
|
+
* Users who need stable numbers for EPG matching should set explicit channelNumber values.
|
|
13
|
+
*
|
|
14
|
+
* The mapping is rebuilt on each lineup request rather than cached. This ensures immediate consistency when channels are added, removed, or modified through the
|
|
15
|
+
* web UI without requiring restart or cache invalidation.
|
|
16
|
+
*/
|
|
17
|
+
// Auto-assigned channel numbers start at 1000 to avoid conflicts with low user-assigned numbers.
|
|
18
|
+
const AUTO_ASSIGN_START = 1000;
|
|
19
|
+
/**
|
|
20
|
+
* Builds the channel number mapping from the current channel configuration. Channels with explicit channelNumber values are assigned first, then remaining
|
|
21
|
+
* channels are auto-assigned sequential numbers starting from AUTO_ASSIGN_START, skipping any numbers already claimed by explicit assignments.
|
|
22
|
+
* @returns Array of channel map entries sorted by channel number, excluding noVideo and disabled channels.
|
|
23
|
+
*/
|
|
24
|
+
export function buildChannelMap() {
|
|
25
|
+
const channels = getAllChannels();
|
|
26
|
+
const entries = [];
|
|
27
|
+
// Collect all explicit channel numbers first so auto-assignment can skip them.
|
|
28
|
+
const explicitNumbers = new Set();
|
|
29
|
+
for (const [key, channel] of Object.entries(channels)) {
|
|
30
|
+
// Skip non-video channels (static pages like EPGs).
|
|
31
|
+
const profile = resolveProfile(channel.profile);
|
|
32
|
+
if (profile.noVideo) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if ((channel.channelNumber !== undefined) && (channel.channelNumber > 0)) {
|
|
36
|
+
explicitNumbers.add(channel.channelNumber);
|
|
37
|
+
entries.push({
|
|
38
|
+
key,
|
|
39
|
+
name: channel.name ?? key,
|
|
40
|
+
number: channel.channelNumber,
|
|
41
|
+
stationId: channel.stationId
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Auto-assign numbers to channels without explicit channelNumber. Sort keys alphabetically for deterministic assignment.
|
|
46
|
+
const unassignedKeys = Object.keys(channels)
|
|
47
|
+
.filter((key) => {
|
|
48
|
+
const channel = channels[key];
|
|
49
|
+
const profile = resolveProfile(channel.profile);
|
|
50
|
+
return !profile.noVideo && ((channel.channelNumber === undefined) || (channel.channelNumber <= 0));
|
|
51
|
+
})
|
|
52
|
+
.sort();
|
|
53
|
+
let nextNumber = AUTO_ASSIGN_START;
|
|
54
|
+
for (const key of unassignedKeys) {
|
|
55
|
+
const channel = channels[key];
|
|
56
|
+
// Skip numbers already claimed by explicit assignments.
|
|
57
|
+
while (explicitNumbers.has(nextNumber)) {
|
|
58
|
+
nextNumber++;
|
|
59
|
+
}
|
|
60
|
+
entries.push({
|
|
61
|
+
key,
|
|
62
|
+
name: channel.name ?? key,
|
|
63
|
+
number: nextNumber,
|
|
64
|
+
stationId: channel.stationId
|
|
65
|
+
});
|
|
66
|
+
nextNumber++;
|
|
67
|
+
}
|
|
68
|
+
// Sort by channel number for consistent lineup order.
|
|
69
|
+
entries.sort((a, b) => a.number - b.number);
|
|
70
|
+
return entries;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Looks up a channel key by its channel number.
|
|
74
|
+
* @param channelNumber - The numeric channel number to look up.
|
|
75
|
+
* @returns The channel key, or undefined if no channel has this number.
|
|
76
|
+
*/
|
|
77
|
+
export function getChannelKeyByNumber(channelNumber) {
|
|
78
|
+
const map = buildChannelMap();
|
|
79
|
+
const entry = map.find((e) => e.number === channelNumber);
|
|
80
|
+
return entry?.key;
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=channelMap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channelMap.js","sourceRoot":"","sources":["../../src/hdhr/channelMap.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD;;;;;;;;;GASG;AAEH,iGAAiG;AACjG,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAoB/B;;;;GAIG;AACH,MAAM,UAAU,eAAe;IAE7B,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC;IAClC,MAAM,OAAO,GAAsB,EAAE,CAAC;IAEtC,+EAA+E;IAC/E,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;IAE1C,KAAI,MAAM,CAAE,GAAG,EAAE,OAAO,CAAE,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QAEvD,oDAAoD;QACpD,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAEhD,IAAG,OAAO,CAAC,OAAO,EAAE,CAAC;YAEnB,SAAS;QACX,CAAC;QAED,IAAG,CAAC,OAAO,CAAC,aAAa,KAAK,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,GAAG,CAAC,CAAC,EAAE,CAAC;YAExE,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;YAE3C,OAAO,CAAC,IAAI,CAAC;gBAEX,GAAG;gBACH,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,GAAG;gBACzB,MAAM,EAAE,OAAO,CAAC,aAAa;gBAC7B,SAAS,EAAE,OAAO,CAAC,SAAS;aAC7B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,yHAAyH;IACzH,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;SACzC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE;QAEd,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC9B,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAEhD,OAAO,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,aAAa,KAAK,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,IAAI,CAAC,CAAC,CAAC,CAAC;IACrG,CAAC,CAAC;SACD,IAAI,EAAE,CAAC;IAEV,IAAI,UAAU,GAAG,iBAAiB,CAAC;IAEnC,KAAI,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;QAEhC,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;QAE9B,wDAAwD;QACxD,OAAM,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YAEtC,UAAU,EAAE,CAAC;QACf,CAAC;QAED,OAAO,CAAC,IAAI,CAAC;YAEX,GAAG;YACH,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,GAAG;YACzB,MAAM,EAAE,UAAU;YAClB,SAAS,EAAE,OAAO,CAAC,SAAS;SAC7B,CAAC,CAAC;QAEH,UAAU,EAAE,CAAC;IACf,CAAC;IAED,sDAAsD;IACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IAE5C,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,aAAqB;IAEzD,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC;IAC9B,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,aAAa,CAAC,CAAC;IAE1D,OAAO,KAAK,EAAE,GAAG,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates an HDHomeRun DeviceID checksum. A valid DeviceID produces zero when processed through the alternating lookup/raw XOR algorithm.
|
|
3
|
+
* @param deviceId - The 8-character hex DeviceID to validate.
|
|
4
|
+
* @returns True if the checksum is valid.
|
|
5
|
+
*/
|
|
6
|
+
export declare function validateDeviceId(deviceId: string): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Generates a valid HDHomeRun DeviceID. Creates a random 24-bit prefix and finds a final byte that satisfies the checksum constraint.
|
|
9
|
+
* @returns An 8-character lowercase hex string with a valid HDHomeRun checksum.
|
|
10
|
+
*/
|
|
11
|
+
export declare function generateDeviceId(): string;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/* Copyright(C) 2024-2026, HJD (https://github.com/hjdhjd). All rights reserved.
|
|
2
|
+
*
|
|
3
|
+
* deviceId.ts: HDHomeRun DeviceID generation for PrismCast.
|
|
4
|
+
*/
|
|
5
|
+
import crypto from "node:crypto";
|
|
6
|
+
/* HDHomeRun devices are identified by an 8-character hex string (32 bits). The checksum is computed using an XOR-based algorithm from the libhdhomerun reference
|
|
7
|
+
* implementation (hdhomerun_discover_validate_device_id in hdhomerun_discover.c). The checksum ensures that mistyped or corrupted device IDs are detected. Plex
|
|
8
|
+
* validates this checksum when discovering tuners, so we must generate conformant IDs.
|
|
9
|
+
*
|
|
10
|
+
* Algorithm: The 32-bit value is processed as 8 nibbles (4 bits each). Nibbles at even positions (0, 2, 4, 6 counting from the most significant) are
|
|
11
|
+
* transformed through a lookup table before XOR. Nibbles at odd positions (1, 3, 5, 7) are XORed directly. A valid ID produces a checksum of zero.
|
|
12
|
+
*
|
|
13
|
+
* We generate a random 24-bit prefix (6 hex chars), then brute-force the final byte (2 hex chars) to satisfy the checksum constraint.
|
|
14
|
+
*/
|
|
15
|
+
// Lookup table from libhdhomerun for DeviceID checksum validation. Applied to nibbles at even positions only.
|
|
16
|
+
const DEVICEID_LOOKUP = [
|
|
17
|
+
0xA, 0x5, 0xF, 0x6, 0x7, 0xC, 0x1, 0xB,
|
|
18
|
+
0x9, 0x2, 0x8, 0xD, 0x4, 0x3, 0xE, 0x0
|
|
19
|
+
];
|
|
20
|
+
/**
|
|
21
|
+
* Computes the DeviceID checksum matching libhdhomerun's hdhomerun_discover_validate_device_id. Even-positioned nibbles (0, 2, 4, 6) go through the lookup
|
|
22
|
+
* table; odd-positioned nibbles (1, 3, 5, 7) are XORed directly. A valid DeviceID produces a checksum of zero.
|
|
23
|
+
* @param nibbles - Array of 8 nibble values (0-15), most significant first.
|
|
24
|
+
* @returns The checksum value. Zero indicates a valid DeviceID.
|
|
25
|
+
*/
|
|
26
|
+
function computeChecksum(nibbles) {
|
|
27
|
+
let checksum = 0;
|
|
28
|
+
for (let i = 0; i < 8; i++) {
|
|
29
|
+
// Even positions use the lookup table, odd positions use the raw nibble value.
|
|
30
|
+
if ((i % 2) === 0) {
|
|
31
|
+
checksum ^= DEVICEID_LOOKUP[nibbles[i]];
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
checksum ^= nibbles[i];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return checksum;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Validates an HDHomeRun DeviceID checksum. A valid DeviceID produces zero when processed through the alternating lookup/raw XOR algorithm.
|
|
41
|
+
* @param deviceId - The 8-character hex DeviceID to validate.
|
|
42
|
+
* @returns True if the checksum is valid.
|
|
43
|
+
*/
|
|
44
|
+
export function validateDeviceId(deviceId) {
|
|
45
|
+
if (!/^[0-9a-fA-F]{8}$/.test(deviceId)) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
const nibbles = Array.from(deviceId, (ch) => parseInt(ch, 16));
|
|
49
|
+
return computeChecksum(nibbles) === 0;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Generates a valid HDHomeRun DeviceID. Creates a random 24-bit prefix and finds a final byte that satisfies the checksum constraint.
|
|
53
|
+
* @returns An 8-character lowercase hex string with a valid HDHomeRun checksum.
|
|
54
|
+
*/
|
|
55
|
+
export function generateDeviceId() {
|
|
56
|
+
// Generate 3 random bytes (24 bits = 6 hex chars) for the prefix.
|
|
57
|
+
const prefixBytes = crypto.randomBytes(3);
|
|
58
|
+
const prefix = prefixBytes.toString("hex");
|
|
59
|
+
// Parse the prefix into nibbles and compute the partial checksum for the first 6 nibbles (positions 0-5). We compute this directly rather than padding to 8 and
|
|
60
|
+
// using computeChecksum(), because padding with zeros would include LOOKUP[0] for position 6 and skew the result.
|
|
61
|
+
const nibbles = Array.from(prefix, (ch) => parseInt(ch, 16));
|
|
62
|
+
let partialChecksum = 0;
|
|
63
|
+
for (let i = 0; i < 6; i++) {
|
|
64
|
+
if ((i % 2) === 0) {
|
|
65
|
+
partialChecksum ^= DEVICEID_LOOKUP[nibbles[i]];
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
partialChecksum ^= nibbles[i];
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Find the final byte (2 nibbles) that makes the total checksum zero. Position 6 is even (lookup table), position 7 is odd (raw). We try all 256 values. A
|
|
72
|
+
// solution is always guaranteed since for any 4-bit partial checksum, at least one of the 256 final byte combinations will zero the full checksum.
|
|
73
|
+
for (let finalByte = 0; finalByte < 256; finalByte++) {
|
|
74
|
+
const highNibble = (finalByte >> 4) & 0xF;
|
|
75
|
+
const lowNibble = finalByte & 0xF;
|
|
76
|
+
const finalChecksum = partialChecksum ^ DEVICEID_LOOKUP[highNibble] ^ lowNibble;
|
|
77
|
+
if (finalChecksum === 0) {
|
|
78
|
+
return prefix + finalByte.toString(16).padStart(2, "0");
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
// This is unreachable — a solution always exists within the 256 candidates. Fall back to a known-valid ID as a safety net.
|
|
82
|
+
return "1000000f";
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=deviceId.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deviceId.js","sourceRoot":"","sources":["../../src/hdhr/deviceId.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { CONFIG } from "../config/index.js";
|
|
2
|
+
import { buildChannelMap } from "./channelMap.js";
|
|
3
|
+
import { getAllStreams } from "../streaming/registry.js";
|
|
4
|
+
import { getPackageVersion } from "../utils/index.js";
|
|
5
|
+
/**
|
|
6
|
+
* Resolves the hostname from an incoming request for use in generated URLs. We extract the hostname from the request (which Plex already connected to) and
|
|
7
|
+
* combine it with the appropriate port. This ensures URLs work from Plex's network perspective.
|
|
8
|
+
* @param req - The Express request object.
|
|
9
|
+
* @returns The hostname (without port) that the client used to connect.
|
|
10
|
+
*/
|
|
11
|
+
function resolveHostname(req) {
|
|
12
|
+
// Check X-Forwarded-Host first (reverse proxy scenarios), then fall back to the Host header.
|
|
13
|
+
const forwardedHost = req.get("x-forwarded-host");
|
|
14
|
+
const hostHeader = forwardedHost ? forwardedHost.split(",")[0].trim() : req.get("host");
|
|
15
|
+
if (hostHeader) {
|
|
16
|
+
// Strip port from host header if present (e.g., "192.168.1.100:5004" -> "192.168.1.100").
|
|
17
|
+
const bracketIndex = hostHeader.indexOf("]");
|
|
18
|
+
// Handle IPv6 addresses in brackets (e.g., "[::1]:5004").
|
|
19
|
+
if (bracketIndex !== -1) {
|
|
20
|
+
return hostHeader.substring(0, bracketIndex + 1);
|
|
21
|
+
}
|
|
22
|
+
const colonIndex = hostHeader.lastIndexOf(":");
|
|
23
|
+
return (colonIndex !== -1) ? hostHeader.substring(0, colonIndex) : hostHeader;
|
|
24
|
+
}
|
|
25
|
+
// Fallback to configured server host.
|
|
26
|
+
return CONFIG.server.host;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Sets up the HDHomeRun discovery and lineup endpoints on the given Express app.
|
|
30
|
+
* @param app - The Express application for the HDHR server.
|
|
31
|
+
*/
|
|
32
|
+
export function setupHdhrEndpoints(app) {
|
|
33
|
+
// GET /device.xml - UPnP device description. Plex fetches this during tuner discovery before querying discover.json. Without a valid device.xml response,
|
|
34
|
+
// Plex may silently abort the discovery process.
|
|
35
|
+
app.get("/device.xml", (req, res) => {
|
|
36
|
+
const hostname = resolveHostname(req);
|
|
37
|
+
const baseUrl = "http://" + hostname + ":" + String(CONFIG.hdhr.port);
|
|
38
|
+
const deviceId = CONFIG.hdhr.deviceId.toUpperCase();
|
|
39
|
+
const xml = [
|
|
40
|
+
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
|
|
41
|
+
"<root xmlns=\"urn:schemas-upnp-org:device-1-0\">",
|
|
42
|
+
" <specVersion>",
|
|
43
|
+
" <major>1</major>",
|
|
44
|
+
" <minor>0</minor>",
|
|
45
|
+
" </specVersion>",
|
|
46
|
+
" <URLBase>" + baseUrl + "</URLBase>",
|
|
47
|
+
" <device>",
|
|
48
|
+
" <deviceType>urn:schemas-upnp-org:device:MediaServer:1</deviceType>",
|
|
49
|
+
" <friendlyName>" + CONFIG.hdhr.friendlyName + "</friendlyName>",
|
|
50
|
+
" <manufacturer>PrismCast</manufacturer>",
|
|
51
|
+
" <modelName>HDTC-2US</modelName>",
|
|
52
|
+
" <modelNumber>HDTC-2US</modelNumber>",
|
|
53
|
+
" <serialNumber>" + deviceId + "</serialNumber>",
|
|
54
|
+
" <UDN>uuid:" + deviceId + "</UDN>",
|
|
55
|
+
" </device>",
|
|
56
|
+
"</root>"
|
|
57
|
+
].join("\n");
|
|
58
|
+
res.set("Content-Type", "text/xml");
|
|
59
|
+
res.send(xml);
|
|
60
|
+
});
|
|
61
|
+
// GET /discover.json - Device identity and capabilities. Plex uses this to identify the tuner model, determine concurrent stream capacity, and locate the
|
|
62
|
+
// lineup endpoint.
|
|
63
|
+
app.get("/discover.json", (req, res) => {
|
|
64
|
+
const hostname = resolveHostname(req);
|
|
65
|
+
const baseUrl = "http://" + hostname + ":" + String(CONFIG.hdhr.port);
|
|
66
|
+
// The response follows the HDHomeRun HTTP API format that Plex expects. DeviceAuth must be non-empty; we use the DeviceID since there's no DRM context.
|
|
67
|
+
// ModelNumber "HDTC-2US" is the HDHomeRun CONNECT DUO, a widely-supported model that Plex recognizes.
|
|
68
|
+
res.json({
|
|
69
|
+
BaseURL: baseUrl,
|
|
70
|
+
DeviceAuth: CONFIG.hdhr.deviceId.toUpperCase(),
|
|
71
|
+
DeviceID: CONFIG.hdhr.deviceId.toUpperCase(),
|
|
72
|
+
FirmwareName: "hdhomeruntc_atsc",
|
|
73
|
+
FirmwareVersion: getPackageVersion(),
|
|
74
|
+
FriendlyName: CONFIG.hdhr.friendlyName,
|
|
75
|
+
LineupURL: baseUrl + "/lineup.json",
|
|
76
|
+
Manufacturer: "PrismCast",
|
|
77
|
+
ModelNumber: "HDTC-2US",
|
|
78
|
+
TunerCount: CONFIG.streaming.maxConcurrentStreams
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
// GET /lineup.json - Channel lineup with stream URLs. Each entry maps a numeric channel number to an MPEG-TS stream URL on the main PrismCast server. Plex
|
|
82
|
+
// requests the MPEG-TS stream directly from the main server when tuning a channel.
|
|
83
|
+
app.get("/lineup.json", (req, res) => {
|
|
84
|
+
const hostname = resolveHostname(req);
|
|
85
|
+
const mainBaseUrl = "http://" + hostname + ":" + String(CONFIG.server.port);
|
|
86
|
+
const channelMap = buildChannelMap();
|
|
87
|
+
const lineup = channelMap.map((entry) => ({
|
|
88
|
+
AudioCodec: "AAC",
|
|
89
|
+
GuideName: entry.name,
|
|
90
|
+
GuideNumber: String(entry.number),
|
|
91
|
+
HD: 1,
|
|
92
|
+
URL: mainBaseUrl + "/stream/" + entry.key,
|
|
93
|
+
VideoCodec: "H264"
|
|
94
|
+
}));
|
|
95
|
+
res.json(lineup);
|
|
96
|
+
});
|
|
97
|
+
// GET /lineup_status.json - Channel scan status. Plex checks this during tuner setup. We return a static response indicating scan is complete since PrismCast's
|
|
98
|
+
// channels are configured, not scanned.
|
|
99
|
+
app.get("/lineup_status.json", (_req, res) => {
|
|
100
|
+
res.json({
|
|
101
|
+
ScanInProgress: 0,
|
|
102
|
+
ScanPossible: 1,
|
|
103
|
+
Source: "Cable",
|
|
104
|
+
SourceList: ["Cable"]
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
// POST /lineup.post - Channel scan control. Some clients (Plex during initial setup) POST scan=start to this endpoint. We return 200 OK since PrismCast's channels
|
|
108
|
+
// are statically configured and scanning is not applicable.
|
|
109
|
+
app.post("/lineup.post", (_req, res) => {
|
|
110
|
+
res.sendStatus(200);
|
|
111
|
+
});
|
|
112
|
+
// GET /status.json - Tuner status. Returns a JSON array with one entry per tuner slot. Active tuners include channel info and signal stats; idle tuners have only
|
|
113
|
+
// Resource. Monitoring dashboards (Home Assistant, Homepage) poll this endpoint to display real-time tuner activity.
|
|
114
|
+
app.get("/status.json", (_req, res) => {
|
|
115
|
+
const channelMap = buildChannelMap();
|
|
116
|
+
const channelByKey = new Map(channelMap.map((entry) => [entry.key, entry]));
|
|
117
|
+
const streams = getAllStreams().sort((a, b) => a.id - b.id);
|
|
118
|
+
const tunerCount = CONFIG.streaming.maxConcurrentStreams;
|
|
119
|
+
const tuners = [];
|
|
120
|
+
// Build active tuner entries from currently running streams.
|
|
121
|
+
for (let i = 0; i < streams.length; i++) {
|
|
122
|
+
const stream = streams[i];
|
|
123
|
+
const channelEntry = channelByKey.get(stream.info.storeKey);
|
|
124
|
+
// Build the tuner entry. Active tuners include channel info and signal stats. Signal values are hardcoded at 100 since PrismCast streams are network-based and
|
|
125
|
+
// either working or not — there is no analog signal quality to report.
|
|
126
|
+
const tuner = {
|
|
127
|
+
Frequency: 0,
|
|
128
|
+
Resource: "tuner" + String(i),
|
|
129
|
+
SignalQualityPercent: 100,
|
|
130
|
+
SignalStrengthPercent: 100,
|
|
131
|
+
SymbolQualityPercent: 100
|
|
132
|
+
};
|
|
133
|
+
// Add channel info if available. Prefer the channel map for VctNumber (numeric channel) and VctName (display name). Fall back to stream.channelName for VctName
|
|
134
|
+
// if the channel was removed from the map after the stream started.
|
|
135
|
+
if (channelEntry) {
|
|
136
|
+
tuner.VctName = channelEntry.name;
|
|
137
|
+
tuner.VctNumber = String(channelEntry.number);
|
|
138
|
+
}
|
|
139
|
+
else if (stream.channelName) {
|
|
140
|
+
tuner.VctName = stream.channelName;
|
|
141
|
+
}
|
|
142
|
+
// Add client address if known. Normalize IPv6-mapped IPv4 addresses (::ffff:192.168.1.1 → 192.168.1.1).
|
|
143
|
+
if (stream.clientAddress) {
|
|
144
|
+
tuner.TargetIP = stream.clientAddress.startsWith("::ffff:") ? stream.clientAddress.slice(7) : stream.clientAddress;
|
|
145
|
+
}
|
|
146
|
+
tuners.push(tuner);
|
|
147
|
+
}
|
|
148
|
+
// Fill remaining slots with idle tuner entries.
|
|
149
|
+
for (let i = streams.length; i < tunerCount; i++) {
|
|
150
|
+
tuners.push({ Resource: "tuner" + String(i) });
|
|
151
|
+
}
|
|
152
|
+
res.json(tuners);
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=discover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/hdhr/discover.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Starts the HDHomeRun emulation server if enabled in configuration. This includes generating a DeviceID on first run and starting the HTTP server for discovery
|
|
3
|
+
* endpoints. If the configured port is unavailable, HDHR emulation is disabled gracefully.
|
|
4
|
+
*/
|
|
5
|
+
export declare function startHdhrServer(): Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* Stops the HDHomeRun emulation server. Called during graceful shutdown.
|
|
8
|
+
*/
|
|
9
|
+
export declare function stopHdhrServer(): void;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/* Copyright(C) 2024-2026, HJD (https://github.com/hjdhjd). All rights reserved.
|
|
2
|
+
*
|
|
3
|
+
* index.ts: HDHomeRun emulation server for PrismCast.
|
|
4
|
+
*/
|
|
5
|
+
import { generateDeviceId, validateDeviceId } from "./deviceId.js";
|
|
6
|
+
import { loadUserConfig, saveUserConfig } from "../config/userConfig.js";
|
|
7
|
+
import { CONFIG } from "../config/index.js";
|
|
8
|
+
import { LOG } from "../utils/index.js";
|
|
9
|
+
import express from "express";
|
|
10
|
+
import { formatError } from "../utils/errors.js";
|
|
11
|
+
import { setupHdhrEndpoints } from "./discover.js";
|
|
12
|
+
/* When HDHomeRun emulation is enabled, PrismCast runs a separate Express server that responds to HDHomeRun API requests from Plex. This server is intentionally
|
|
13
|
+
* lightweight — it only serves device discovery and lineup metadata. All actual video streaming flows through PrismCast's main HTTP server via the HLS URLs in
|
|
14
|
+
* the lineup response.
|
|
15
|
+
*
|
|
16
|
+
* The HDHR server runs on a configurable port (default 5004) independently of the main server. If the port is unavailable, the HDHR feature is disabled
|
|
17
|
+
* gracefully without affecting the main server. Plex does not auto-detect emulated tuners — users must manually enter the address (IP:port) in Plex's DVR setup.
|
|
18
|
+
*/
|
|
19
|
+
// The HDHR HTTP server instance, used for graceful shutdown.
|
|
20
|
+
let hdhrServer = null;
|
|
21
|
+
/**
|
|
22
|
+
* Starts the HDHomeRun emulation server if enabled in configuration. This includes generating a DeviceID on first run and starting the HTTP server for discovery
|
|
23
|
+
* endpoints. If the configured port is unavailable, HDHR emulation is disabled gracefully.
|
|
24
|
+
*/
|
|
25
|
+
export async function startHdhrServer() {
|
|
26
|
+
if (!CONFIG.hdhr.enabled) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
// Generate a DeviceID on first run, or regenerate if the stored ID fails checksum validation (e.g., hand-edited config with a typo). Plex silently rejects
|
|
30
|
+
// tuners with invalid DeviceIDs during discovery, so we catch this early.
|
|
31
|
+
if (!CONFIG.hdhr.deviceId || !validateDeviceId(CONFIG.hdhr.deviceId)) {
|
|
32
|
+
if (CONFIG.hdhr.deviceId) {
|
|
33
|
+
LOG.warn("HDHomeRun DeviceID '%s' has an invalid checksum. Generating a new one.", CONFIG.hdhr.deviceId.toUpperCase());
|
|
34
|
+
}
|
|
35
|
+
CONFIG.hdhr.deviceId = generateDeviceId();
|
|
36
|
+
LOG.info("Generated HDHomeRun DeviceID: %s.", CONFIG.hdhr.deviceId.toUpperCase());
|
|
37
|
+
// Save the generated ID to the user config so it persists across restarts. We load the current config, set the deviceId, and save to avoid overwriting other
|
|
38
|
+
// settings.
|
|
39
|
+
try {
|
|
40
|
+
const result = await loadUserConfig();
|
|
41
|
+
if (!result.parseError) {
|
|
42
|
+
result.config.hdhr ??= {};
|
|
43
|
+
result.config.hdhr.deviceId = CONFIG.hdhr.deviceId;
|
|
44
|
+
await saveUserConfig(result.config);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
LOG.warn("Failed to persist HDHomeRun DeviceID: %s. A new ID will be generated on next restart.", formatError(error));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Build the HDHR Express application.
|
|
52
|
+
const app = express();
|
|
53
|
+
app.set("trust proxy", true);
|
|
54
|
+
setupHdhrEndpoints(app);
|
|
55
|
+
// Start listening on the configured port. Handle EADDRINUSE gracefully.
|
|
56
|
+
try {
|
|
57
|
+
hdhrServer = await new Promise((resolve, reject) => {
|
|
58
|
+
const server = app.listen(CONFIG.hdhr.port, CONFIG.server.host, () => {
|
|
59
|
+
resolve(server);
|
|
60
|
+
});
|
|
61
|
+
server.on("error", (error) => {
|
|
62
|
+
reject(error);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
LOG.info("HDHomeRun emulation is now listening on %s:%s (DeviceID: %s).", CONFIG.server.host, CONFIG.hdhr.port, CONFIG.hdhr.deviceId.toUpperCase());
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
const errnoError = error;
|
|
69
|
+
if (errnoError.code === "EADDRINUSE") {
|
|
70
|
+
LOG.warn("HDHomeRun port %s is already in use. HDHomeRun emulation is disabled. Check for conflicting services on this port.", CONFIG.hdhr.port);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
LOG.warn("Failed to start HDHomeRun server: %s. HDHomeRun emulation is disabled.", formatError(error));
|
|
74
|
+
}
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Stops the HDHomeRun emulation server. Called during graceful shutdown.
|
|
80
|
+
*/
|
|
81
|
+
export function stopHdhrServer() {
|
|
82
|
+
if (hdhrServer) {
|
|
83
|
+
hdhrServer.close();
|
|
84
|
+
hdhrServer = null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hdhr/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|