Skip to content

Commit 5161a16

Browse files
authored
Merge pull request #7 from tc-mb/deploy-windows
add windows env
2 parents c3e30a8 + d950851 commit 5161a16

File tree

3 files changed

+109
-55
lines changed

3 files changed

+109
-55
lines changed

tools/omni/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,18 @@ if(ENABLE_COREML)
5252
)
5353
endif()
5454

55+
# Windows-specific definitions
56+
if (WIN32)
57+
target_compile_definitions(omni PRIVATE NOMINMAX _USE_MATH_DEFINES _CRT_SECURE_NO_WARNINGS)
58+
endif()
59+
5560
if (BUILD_SHARED_LIBS)
5661
set_target_properties (omni PROPERTIES POSITION_INDEPENDENT_CODE ON)
5762
target_compile_definitions(omni PRIVATE LLAMA_BUILD)
5863
target_compile_definitions(omni PUBLIC LLAMA_SHARED)
64+
if (WIN32)
65+
set_target_properties(omni PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)
66+
endif()
5967
endif()
6068

6169
set(OMNI_PUBLIC_HEADERS

tools/omni/omni.cpp

Lines changed: 96 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,94 @@
3535
#include <condition_variable>
3636
#include <atomic>
3737
#include <fstream>
38-
#include <sys/time.h>
3938
#include <iomanip>
4039
#include <chrono>
41-
#include <sys/stat.h>
42-
#include <sys/types.h>
43-
#include <sys/wait.h>
44-
#include <unistd.h>
45-
#include <dirent.h>
4640
#include <cmath>
4741
#include <sstream>
4842
#include <random>
4943
#include <cstdarg>
5044
#include <signal.h>
5145

46+
#ifdef _WIN32
47+
#include <windows.h>
48+
#include <direct.h>
49+
#include <io.h>
50+
#include <process.h>
51+
#include <sys/stat.h>
52+
#include <sys/types.h>
53+
// Windows compatibility macros
54+
#define popen _popen
55+
#define pclose _pclose
56+
#define unlink _unlink
57+
#define stat _stat
58+
#define S_IFDIR _S_IFDIR
59+
#else
60+
#include <sys/time.h>
61+
#include <sys/stat.h>
62+
#include <sys/types.h>
63+
#include <sys/wait.h>
64+
#include <unistd.h>
65+
#include <dirent.h>
66+
#endif
67+
68+
// ============================================================
69+
// Cross-platform helper: recursive directory creation
70+
// Replaces "mkdir -p" shell command for Windows compatibility
71+
// ============================================================
72+
static bool cross_platform_mkdir_p(const std::string& path) {
73+
if (path.empty()) return false;
74+
75+
std::string normalized = path;
76+
#ifdef _WIN32
77+
for (char& c : normalized) {
78+
if (c == '/') c = '\\';
79+
}
80+
size_t pos = 0;
81+
if (normalized.size() >= 2 && normalized[1] == ':') {
82+
pos = 2;
83+
if (normalized.size() > 2 && normalized[2] == '\\') pos = 3;
84+
}
85+
while (pos < normalized.size() && normalized[pos] == '\\') pos++;
86+
87+
while (pos < normalized.size()) {
88+
pos = normalized.find('\\', pos);
89+
if (pos == std::string::npos) pos = normalized.size();
90+
std::string sub = normalized.substr(0, pos);
91+
if (!sub.empty()) {
92+
struct _stat info;
93+
if (_stat(sub.c_str(), &info) != 0) {
94+
if (_mkdir(sub.c_str()) != 0 && errno != EEXIST) {
95+
return false;
96+
}
97+
}
98+
}
99+
if (pos < normalized.size()) pos++;
100+
}
101+
return true;
102+
#else
103+
for (char& c : normalized) {
104+
if (c == '\\') c = '/';
105+
}
106+
size_t pos = 0;
107+
if (!normalized.empty() && normalized[0] == '/') pos = 1;
108+
while (pos < normalized.size()) {
109+
pos = normalized.find('/', pos);
110+
if (pos == std::string::npos) pos = normalized.size();
111+
std::string sub = normalized.substr(0, pos);
112+
if (!sub.empty()) {
113+
struct stat info;
114+
if (::stat(sub.c_str(), &info) != 0) {
115+
if (mkdir(sub.c_str(), 0755) != 0 && errno != EEXIST) {
116+
return false;
117+
}
118+
}
119+
}
120+
if (pos < normalized.size()) pos++;
121+
}
122+
return true;
123+
#endif
124+
}
125+
52126
// 前向声明:Python Token2Wav 服务函数(定义在文件后面)
53127
static bool start_python_t2w_service(struct omni_context * ctx_omni);
54128
static void stop_python_t2w_service(struct omni_context * ctx_omni);
@@ -5169,26 +5243,19 @@ static bool generate_audio_tokens_local(
51695243

51705244
// Helper function to play WAV file
51715245
static void play_wav_file(const std::string& wav_file_path) {
5246+
#ifndef _WIN32
51725247
// Play audio asynchronously using fork() to avoid blocking TTS thread
5173-
// This is important because audio playback can take time and shouldn't delay
5174-
// the next TTS request
5175-
51765248
pid_t pid = fork();
51775249
if (pid == 0) {
5178-
// Child process: execute playback command
51795250
#ifdef __APPLE__
51805251
execl("/usr/bin/afplay", "afplay", wav_file_path.c_str(), (char*)NULL);
51815252
#else
51825253
execl("/usr/bin/aplay", "aplay", wav_file_path.c_str(), (char*)NULL);
51835254
#endif
5184-
// If execl fails, exit child process
51855255
_exit(1);
51865256
} else if (pid > 0) {
51875257
// Parent process: continue without waiting
5188-
// Detach child process to avoid zombie processes
5189-
// Note: We don't wait for the child, allowing it to run independently
51905258
} else {
5191-
// Fork failed, fallback to system() with & (less ideal but better than blocking)
51925259
std::string play_cmd;
51935260
#ifdef __APPLE__
51945261
play_cmd = "afplay \"" + wav_file_path + "\" &";
@@ -5198,6 +5265,8 @@ static void play_wav_file(const std::string& wav_file_path) {
51985265
LOG_WRN("TTS: fork() failed, using system() fallback for audio playback\n");
51995266
system(play_cmd.c_str());
52005267
}
5268+
#endif
5269+
// Windows: no-op (audio playback handled by frontend)
52015270
}
52025271

52035272

@@ -5227,14 +5296,11 @@ static void move_old_output_to_archive() {
52275296
struct stat info;
52285297
if (stat(dir_path.c_str(), &info) != 0) {
52295298
// Directory doesn't exist, try to create it
5230-
std::string cmd = "mkdir -p " + dir_path;
5231-
int ret = system(cmd.c_str());
5232-
if (ret != 0) {
5299+
if (!cross_platform_mkdir_p(dir_path)) {
52335300
LOG_ERR("Failed to create output directory: %s\n", dir_path.c_str());
52345301
return false;
5235-
} else {
5236-
return true;
52375302
}
5303+
return true;
52385304
} else if (!(info.st_mode & S_IFDIR)) {
52395305
LOG_ERR("Output path exists but is not a directory: %s\n", dir_path.c_str());
52405306
return false;
@@ -5245,8 +5311,7 @@ static void move_old_output_to_archive() {
52455311
// Helper function to find next available ID in old_output directory
52465312
auto get_next_output_id = [](const std::string& old_output_base) -> int {
52475313
// Ensure old_output base directory exists
5248-
std::string mkdir_cmd = "mkdir -p " + old_output_base;
5249-
system(mkdir_cmd.c_str());
5314+
cross_platform_mkdir_p(old_output_base);
52505315

52515316
// Find maximum ID in old_output directory
52525317
int max_id = -1;
@@ -5410,17 +5475,8 @@ void tts_thread_func_duplex(struct omni_context * ctx_omni, common_params *param
54105475

54115476
// Helper function to create directory
54125477
auto create_dir = [](const std::string& dir_path) {
5413-
struct stat info;
5414-
if (stat(dir_path.c_str(), &info) != 0) {
5415-
std::string cmd = "mkdir -p " + dir_path;
5416-
int ret = system(cmd.c_str());
5417-
if (ret != 0) {
5418-
LOG_ERR("Failed to create output directory: %s\n", dir_path.c_str());
5419-
return false;
5420-
}
5421-
return true;
5422-
} else if (!(info.st_mode & S_IFDIR)) {
5423-
LOG_ERR("Output path exists but is not a directory: %s\n", dir_path.c_str());
5478+
if (!cross_platform_mkdir_p(dir_path)) {
5479+
LOG_ERR("Failed to create output directory: %s\n", dir_path.c_str());
54245480
return false;
54255481
}
54265482
return true;
@@ -6018,14 +6074,11 @@ void tts_thread_func(struct omni_context * ctx_omni, common_params *params) {
60186074
struct stat info;
60196075
if (stat(dir_path.c_str(), &info) != 0) {
60206076
// Directory doesn't exist, try to create it
6021-
std::string cmd = "mkdir -p " + dir_path;
6022-
int ret = system(cmd.c_str());
6023-
if (ret != 0) {
6077+
if (!cross_platform_mkdir_p(dir_path)) {
60246078
LOG_ERR("Failed to create output directory: %s\n", dir_path.c_str());
60256079
return false;
6026-
} else {
6027-
return true;
60286080
}
6081+
return true;
60296082
} else if (!(info.st_mode & S_IFDIR)) {
60306083
LOG_ERR("Output path exists but is not a directory: %s\n", dir_path.c_str());
60316084
return false;
@@ -7872,9 +7925,7 @@ void t2w_thread_func_python(struct omni_context * ctx_omni, common_params *param
78727925

78737926
// 确保输出目录存在
78747927
{
7875-
char mkdir_cmd[512];
7876-
snprintf(mkdir_cmd, sizeof(mkdir_cmd), "mkdir -p %s", tts_wav_output_dir.c_str());
7877-
system(mkdir_cmd);
7928+
cross_platform_mkdir_p(tts_wav_output_dir);
78787929
}
78797930

78807931
while (t2w_thread_running) {
@@ -7897,9 +7948,7 @@ void t2w_thread_func_python(struct omni_context * ctx_omni, common_params *param
78977948
if (!ctx_omni->duplex_mode && ctx_omni->simplex_round_idx != last_round_idx) {
78987949
last_round_idx = ctx_omni->simplex_round_idx;
78997950
tts_wav_output_dir = get_wav_output_dir();
7900-
char mkdir_cmd[512];
7901-
snprintf(mkdir_cmd, sizeof(mkdir_cmd), "mkdir -p %s", tts_wav_output_dir.c_str());
7902-
system(mkdir_cmd);
7951+
cross_platform_mkdir_p(tts_wav_output_dir);
79037952
}
79047953

79057954
// 重置 Python 缓存
@@ -7951,9 +8000,7 @@ void t2w_thread_func_python(struct omni_context * ctx_omni, common_params *param
79518000
last_round_idx, received_round_idx);
79528001
last_round_idx = received_round_idx;
79538002
tts_wav_output_dir = get_wav_output_dir();
7954-
char mkdir_cmd[512];
7955-
snprintf(mkdir_cmd, sizeof(mkdir_cmd), "mkdir -p %s", tts_wav_output_dir.c_str());
7956-
system(mkdir_cmd);
8003+
cross_platform_mkdir_p(tts_wav_output_dir);
79578004
// 重置 wav 索引,因为是新的轮次
79588005
wav_idx = 0;
79598006
}
@@ -8071,9 +8118,7 @@ void t2w_thread_func_python(struct omni_context * ctx_omni, common_params *param
80718118
if (!ctx_omni->duplex_mode && ctx_omni->simplex_round_idx != last_round_idx) {
80728119
last_round_idx = ctx_omni->simplex_round_idx;
80738120
tts_wav_output_dir = get_wav_output_dir();
8074-
char mkdir_cmd[512];
8075-
snprintf(mkdir_cmd, sizeof(mkdir_cmd), "mkdir -p %s", tts_wav_output_dir.c_str());
8076-
system(mkdir_cmd);
8121+
cross_platform_mkdir_p(tts_wav_output_dir);
80778122
}
80788123
}
80798124
break;
@@ -8253,9 +8298,7 @@ void t2w_thread_func_cpp(struct omni_context * ctx_omni, common_params *params)
82538298
print_with_timestamp("T2W线程(C++): 新输出目录 %s\n", tts_wav_output_dir.c_str());
82548299

82558300
// 确保目录存在
8256-
char mkdir_cmd[512];
8257-
snprintf(mkdir_cmd, sizeof(mkdir_cmd), "mkdir -p %s", tts_wav_output_dir.c_str());
8258-
system(mkdir_cmd);
8301+
cross_platform_mkdir_p(tts_wav_output_dir);
82598302
}
82608303

82618304
// Add new tokens to buffer
@@ -8446,9 +8489,7 @@ void t2w_thread_func_cpp(struct omni_context * ctx_omni, common_params *params)
84468489
tts_wav_output_dir = get_wav_output_dir();
84478490
print_with_timestamp("T2W线程: 轮次结束后更新输出目录为 %s\n", tts_wav_output_dir.c_str());
84488491
// 确保目录存在
8449-
char mkdir_cmd[512];
8450-
snprintf(mkdir_cmd, sizeof(mkdir_cmd), "mkdir -p %s", tts_wav_output_dir.c_str());
8451-
system(mkdir_cmd);
8492+
cross_platform_mkdir_p(tts_wav_output_dir);
84528493
}
84538494
}
84548495
// 注意:is_chunk_end 时不重置 buffer,剩余 tokens 保留给下一个 chunk

tools/omni/omni.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212
#include <functional>
1313
#include <atomic>
1414

15+
// Windows compatibility: pid_t is not defined on MSVC
16+
#ifdef _WIN32
17+
typedef int pid_t;
18+
#endif
19+
1520
struct vision_ctx;
1621
struct audition_ctx;
1722
struct audition_audio_f32;

0 commit comments

Comments
 (0)