Compare commits
2
Commits
a990a2da0c
...
b140aafa2d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b140aafa2d | ||
|
|
eb0adfc2e0 |
+60
-1
@@ -838,6 +838,10 @@ function resolveManagedPath(inputPath) {
|
|||||||
return { logicalPath: 'list.txt', fullPath: listFilePath };
|
return { logicalPath: 'list.txt', fullPath: listFilePath };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (normalized === 'Audio/general/line.txt' || normalized === 'uploads/audio/general/line.txt') {
|
||||||
|
return { logicalPath: 'Audio/general/line.txt', fullPath: path.join(audioGeneralDir, 'line.txt') };
|
||||||
|
}
|
||||||
|
|
||||||
const prefixes = [
|
const prefixes = [
|
||||||
{ prefix: 'Audio/music/', baseDir: audioMusicDir, logicalPrefix: 'Audio/music/' },
|
{ prefix: 'Audio/music/', baseDir: audioMusicDir, logicalPrefix: 'Audio/music/' },
|
||||||
{ prefix: 'Audio/voice/', baseDir: audioVoiceDir, logicalPrefix: 'Audio/voice/' },
|
{ prefix: 'Audio/voice/', baseDir: audioVoiceDir, logicalPrefix: 'Audio/voice/' },
|
||||||
@@ -923,7 +927,7 @@ function getManagedFiles() {
|
|||||||
files.push({
|
files.push({
|
||||||
name: file,
|
name: file,
|
||||||
path: `Audio/general/${file}`,
|
path: `Audio/general/${file}`,
|
||||||
type: 'beep',
|
type: file === 'line.txt' ? 'config' : 'beep',
|
||||||
size: stats.size,
|
size: stats.size,
|
||||||
mtime: stats.mtimeMs
|
mtime: stats.mtimeMs
|
||||||
});
|
});
|
||||||
@@ -1587,7 +1591,11 @@ function handleMessage(ws, data) {
|
|||||||
handleStationRegister(ws, data);
|
handleStationRegister(ws, data);
|
||||||
break;
|
break;
|
||||||
case 'train_arrival':
|
case 'train_arrival':
|
||||||
|
handleTrainArrival(ws, data);
|
||||||
|
break;
|
||||||
case 'train_departure':
|
case 'train_departure':
|
||||||
|
handleTrainDeparture(ws, data);
|
||||||
|
break;
|
||||||
case 'play_sequence':
|
case 'play_sequence':
|
||||||
break;
|
break;
|
||||||
case 'request_station_time':
|
case 'request_station_time':
|
||||||
@@ -1752,6 +1760,57 @@ function findStationByFlexibleName(targetName) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleTrainArrival(ws, data) {
|
||||||
|
const trainId = data.trainId;
|
||||||
|
const stationName = getCorrectStationName(data.stationName);
|
||||||
|
|
||||||
|
const existingIndex = activeTrains.findIndex(t => t.trainId === trainId);
|
||||||
|
const trainData = {
|
||||||
|
trainId,
|
||||||
|
stationName,
|
||||||
|
status: 'arrived',
|
||||||
|
lastUpdated: Date.now()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (existingIndex >= 0) {
|
||||||
|
activeTrains[existingIndex] = trainData;
|
||||||
|
} else {
|
||||||
|
activeTrains.push(trainData);
|
||||||
|
}
|
||||||
|
|
||||||
|
log('INFO', `Train ${trainId} arrived at ${stationName}`);
|
||||||
|
saveData();
|
||||||
|
broadcastUpdate();
|
||||||
|
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
type: 'train_arrival_ack',
|
||||||
|
success: true,
|
||||||
|
message: 'Train arrival processed successfully',
|
||||||
|
trainId
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleTrainDeparture(ws, data) {
|
||||||
|
const trainId = data.trainId;
|
||||||
|
const stationName = getCorrectStationName(data.stationName);
|
||||||
|
|
||||||
|
const existingIndex = activeTrains.findIndex(t => t.trainId === trainId);
|
||||||
|
if (existingIndex >= 0) {
|
||||||
|
activeTrains.splice(existingIndex, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
log('INFO', `Train ${trainId} departed from ${stationName}`);
|
||||||
|
saveData();
|
||||||
|
broadcastUpdate();
|
||||||
|
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
type: 'train_departure_ack',
|
||||||
|
success: true,
|
||||||
|
message: 'Train departure processed successfully',
|
||||||
|
trainId
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
function handleStationTimeRequest(ws, data) {
|
function handleStationTimeRequest(ws, data) {
|
||||||
// Simple logic: default to 60s or lookup schedule
|
// Simple logic: default to 60s or lookup schedule
|
||||||
const stationTime = 60;
|
const stationTime = 60;
|
||||||
|
|||||||
+28
-1
@@ -2,7 +2,7 @@
|
|||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
-- 1. Configuration & Constants
|
-- 1. Configuration & Constants
|
||||||
-- ============================================================================
|
-- ============================================================================
|
||||||
local APP_VERSION_TEXT = "v1.0.13"
|
local APP_VERSION_TEXT = "v1.0.14"
|
||||||
|
|
||||||
local CONFIG = {
|
local CONFIG = {
|
||||||
CLOUD_URL = "ws://stabadmin.fse-media.group",
|
CLOUD_URL = "ws://stabadmin.fse-media.group",
|
||||||
@@ -14,6 +14,7 @@ local CONFIG = {
|
|||||||
DISK_AUDIO_STATION = "disk/Audio/Station/",
|
DISK_AUDIO_STATION = "disk/Audio/Station/",
|
||||||
STATION_IDENTITY_FILE = "station_identity.cfg",
|
STATION_IDENTITY_FILE = "station_identity.cfg",
|
||||||
AUDIO_VOLUME = 3,
|
AUDIO_VOLUME = 3,
|
||||||
|
AUDIO_STREAM_PREROLL_CHUNKS = 2,
|
||||||
DEBUG = true
|
DEBUG = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -740,6 +741,14 @@ function Audio.createStream()
|
|||||||
return table.remove(chunks, 1)
|
return table.remove(chunks, 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
stream.count = function()
|
||||||
|
return #chunks
|
||||||
|
end
|
||||||
|
|
||||||
|
stream.isFinished = function()
|
||||||
|
return finished
|
||||||
|
end
|
||||||
|
|
||||||
return stream
|
return stream
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1393,8 +1402,10 @@ function Audio.playWavStreamItem(item)
|
|||||||
|
|
||||||
local playSeq = State.interruptSeq
|
local playSeq = State.interruptSeq
|
||||||
local source = item.audioData
|
local source = item.audioData
|
||||||
|
local streamObj = nil
|
||||||
|
|
||||||
if type(source) == "table" and source.read then
|
if type(source) == "table" and source.read then
|
||||||
|
streamObj = source
|
||||||
source = source.read
|
source = source.read
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1407,6 +1418,22 @@ function Audio.playWavStreamItem(item)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local prebufferChunks = math.max(0, tonumber(CONFIG.AUDIO_STREAM_PREROLL_CHUNKS) or 0)
|
||||||
|
if streamObj and prebufferChunks > 0 then
|
||||||
|
Utils.log("INFO", "Prebuffering live WAV stream: target chunks=" .. tostring(prebufferChunks))
|
||||||
|
while streamObj.count() < prebufferChunks and not streamObj.isFinished() do
|
||||||
|
if shouldStop(playSeq) then
|
||||||
|
Audio.stop("current")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not waitForInterruptibleDelay(playSeq, 0.02) then
|
||||||
|
Audio.stop("current")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Utils.log("INFO", "Live WAV prebuffer ready: chunks=" .. tostring(streamObj.count()))
|
||||||
|
end
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
if shouldStop(playSeq) then
|
if shouldStop(playSeq) then
|
||||||
Audio.stop("current")
|
Audio.stop("current")
|
||||||
|
|||||||
Reference in New Issue
Block a user