-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
156 lines (140 loc) · 5.09 KB
/
index.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
150
151
152
153
154
155
156
const chokidar = require('chokidar');
const axios = require('axios');
const path = require('path');
const fs = require('fs');
// Get the directory where the executable is located
const getExeDir = () => {
// When packaged with pkg, process.pkg is defined
if (process.pkg) {
return path.dirname(process.execPath);
}
return __dirname;
};
// Load configuration
let config;
try {
const configPath = path.join(getExeDir(), 'config.json');
config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
} catch (error) {
// Default configuration if config.json is not found
config = {
folderToWatch: './media',
vmixUrl: 'http://localhost:8088',
playlistName: 'List',
supportedExtensions: ['.mp4', '.mov', '.wmv', '.avi', '.mpg', '.mpeg']
};
// Create default config file if it doesn't exist
try {
fs.writeFileSync(
path.join(getExeDir(), 'config.json'),
JSON.stringify(config, null, 2)
);
console.log('Created default config.json');
} catch (writeError) {
console.error('Failed to create default config.json:', writeError.message);
}
}
// Initialize watcher
const watcher = chokidar.watch(config.folderToWatch, {
ignored: /(^|[\/\\])\../, // ignore hidden files
persistent: true,
awaitWriteFinish: {
stabilityThreshold: 2000,
pollInterval: 100
}
});
// Helper function to parse XML response
async function getVmixState() {
try {
const response = await axios.get(`${config.vmixUrl}/api`);
return response.data;
} catch (error) {
console.error(`Error getting vMix state: ${error.message}`);
return null;
}
}
// Helper function to find list items for a specific input
function findListItems(xmlText, absolutePath) {
try {
const listMatch = xmlText.match(/<input[^>]*type="VideoList"[^>]*>[\s\S]*?<list>([\s\S]*?)<\/list>/g);
if (listMatch) {
for (const list of listMatch) {
const items = list.match(/<item[^>]*>(.*?)<\/item>/g);
if (items) {
const index = items.findIndex(item => item.includes(absolutePath)) + 1;
if (index > 0) {
const titleMatch = list.match(/title="([^"]*?)"/);
const inputName = titleMatch ? titleMatch[1] : 'List';
return { index, inputName };
}
}
}
}
return null;
} catch (error) {
console.error(`Error parsing XML: ${error.message}`);
return null;
}
}
// Helper function to add file to vMix playlist
async function addToVmixPlaylist(filePath) {
const extension = path.extname(filePath).toLowerCase();
if (!config.supportedExtensions.includes(extension)) {
console.log(`Ignoring file ${filePath} - unsupported format`);
return;
}
try {
const absolutePath = path.resolve(filePath);
const encodedPath = encodeURIComponent(absolutePath);
const url = `${config.vmixUrl}/api/?Function=ListAdd&Input=${config.playlistName}&Value=${encodedPath}`;
await axios.get(url);
console.log(`Added ${absolutePath} to vMix playlist`);
} catch (error) {
console.error(`Error adding file to vMix: ${error.message}`);
}
}
// Helper function to remove file from vMix playlist
async function removeFromVmixPlaylist(filePath) {
try {
const absolutePath = path.resolve(filePath);
const xmlState = await getVmixState();
if (!xmlState) return;
const fileInfo = findListItems(xmlState, absolutePath);
if (fileInfo) {
const url = `${config.vmixUrl}/api/?Function=ListRemove&Input=${encodeURIComponent(fileInfo.inputName)}&Value=${fileInfo.index}`;
await axios.get(url);
console.log(`Removed ${absolutePath} from vMix playlist "${fileInfo.inputName}" at index ${fileInfo.index}`);
} else {
console.log(`File ${absolutePath} not found in any vMix playlist`);
}
} catch (error) {
console.error(`Error removing file from vMix: ${error.message}`);
}
}
// Watch for file events
watcher
.on('add', path => {
console.log(`File ${path} has been added`);
addToVmixPlaylist(path);
})
.on('unlink', path => {
console.log(`File ${path} has been removed`);
removeFromVmixPlaylist(path);
})
.on('change', path => {
console.log(`File ${path} has been changed`);
addToVmixPlaylist(path);
})
.on('rename', (oldPath, newPath) => {
console.log(`File renamed from ${oldPath} to ${newPath}`);
removeFromVmixPlaylist(oldPath);
addToVmixPlaylist(newPath);
})
.on('error', error => {
console.error(`Watcher error: ${error}`);
});
// Log that we're running
console.log('Configuration:', config);
console.log(`Watching ${config.folderToWatch} for changes...`);
console.log(`vMix API URL: ${config.vmixUrl}`);
console.log(`Supported file types: ${config.supportedExtensions.join(', ')}`);