culturered_client/PlaySound/SDLWindow.cpp

211 lines
5.8 KiB
C++
Raw Permalink Normal View History

2024-09-07 03:34:44 +00:00
#include "SDLWindow.h"
#include <iostream>
#include <irrKlang.h>
// include console I/O methods (conio.h for windows, our wrapper in linux)
#if defined(WIN32)
#include <conio.h>
#else
#include "../common/conio.h"
#endif
#include "serial/serial.h"
constexpr char kWindowClassName[] = "Playsound";
constexpr char kWindowName[] = "Playsound";
SDLWindow::SDLWindow()
{
// 创建窗口
WNDCLASS wc = { 0 };
wc.lpfnWndProc = StaticWindowProcedure;
wc.hInstance = GetModuleHandle(NULL);
wc.lpszClassName = kWindowClassName;
RegisterClass(&wc);
hWnd = CreateWindow(wc.lpszClassName, kWindowName, 0, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, wc.hInstance, (LPVOID)this);
}
SDLWindow::~SDLWindow()
{
// 移除托盘图标
Shell_NotifyIcon(NIM_DELETE, &trayIconData);
}
int32_t SDLWindow::Run()
{
// 创建托盘图标
CreateTrayIcon();
// 初始化SDL音频设备
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
std::cerr << "SDL initialization failed: " << SDL_GetError() << std::endl;
return -1;
}
SDL_AtomicSet(&Quit, 0);
SDL_zero(audioSpec);
audioSpec.freq = 44100;
audioSpec.format = AUDIO_S16SYS;
audioSpec.channels = 2;
audioSpec.samples = 4096;
audioSpec.callback = AudioCallback;
audioDeviceID = SDL_OpenAudioDevice(NULL, 0, &audioSpec, NULL, 0);
if (audioDeviceID == 0) {
std::cerr << "Failed to open audio device: " << SDL_GetError() << std::endl;
return -1;
}
// 创建串口监听线程
HANDLE hSerialListenerThread = CreateThread(NULL, 0, SerialListenerThread, this, 0, NULL);
// 主消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// 等待串口监听线程结束
WaitForSingleObject(hSerialListenerThread, INFINITE);
CloseHandle(hSerialListenerThread);
// 停止音频设备
SDL_PauseAudioDevice(audioDeviceID, 1);
SDL_CloseAudioDevice(audioDeviceID);
SDL_Quit();
return 0;
}
void SDLWindow::CreateTrayIcon()
{
ZeroMemory(&trayIconData, sizeof(NOTIFYICONDATA));
trayIconData.cbSize = sizeof(NOTIFYICONDATA);
trayIconData.hWnd = hWnd;
trayIconData.uID = TRAY_ICON_ID;
trayIconData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
trayIconData.uCallbackMessage = WM_TRAYICON;
trayIconData.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_APPLICATION));
strcpy_s(trayIconData.szTip, sizeof(trayIconData.szTip), kWindowName);
Shell_NotifyIcon(NIM_ADD, &trayIconData);
}
void SDLWindow::QuitApplication()
{
// 在这里添加退出逻辑
SDL_AtomicSet(&Quit, 1);
// 终止应用程序消息循环
PostQuitMessage(0);
}
LRESULT SDLWindow::WindowProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == WM_TRAYICON && wParam == TRAY_ICON_ID) {
if (lParam == WM_RBUTTONDOWN) {
// 创建右键退出菜单
HMENU hMenu = CreatePopupMenu();
AppendMenu(hMenu, MF_STRING, 1, "Exit");
// 获取鼠标位置
POINT pt;
GetCursorPos(&pt);
// 显示右键退出菜单
SetForegroundWindow(hWnd);
TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, pt.x, pt.y, 0, hWnd, NULL);
// 销毁菜单
DestroyMenu(hMenu);
}
} else if (uMsg == WM_COMMAND && LOWORD(wParam) == 1) {
// 退出菜单被点击
QuitApplication();
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
LRESULT CALLBACK SDLWindow::StaticWindowProcedure(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
SDLWindow* pWindow = nullptr;
if (uMsg == WM_NCCREATE) {
CREATESTRUCT* pCreateStruct = (CREATESTRUCT*)lParam;
pWindow = (SDLWindow*)pCreateStruct->lpCreateParams;
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)pWindow);
} else {
pWindow = (SDLWindow*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
}
if (pWindow) {
return pWindow->WindowProcedure(hWnd, uMsg, wParam, lParam);
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
DWORD WINAPI SDLWindow::SerialListenerThread(LPVOID lpParam) {
SDLWindow* pWindow = (SDLWindow*)lpParam;
TCHAR path[MAX_PATH] = { 0 };
GetModuleFileName(NULL, path, sizeof(path));
std::string exeDir = path;
std::size_t pos = exeDir.find_last_of("\\/");
if (pos != std::string::npos) {
exeDir = exeDir.substr(0, pos);
}
const std::string configPath = exeDir + "\\playsound.ini";
const TCHAR* iniFile = configPath.c_str();
TCHAR section[] = TEXT("Settings");
TCHAR port[256];
DWORD code = GetPrivateProfileString(section, TEXT("port"), TEXT(""), port, sizeof(port), iniFile);
DWORD errorCode = GetLastError();
int baudrate = GetPrivateProfileInt(section, TEXT("baudrate"), 9600, iniFile);
uint32_t timeout = GetPrivateProfileInt(section, TEXT("timeout"), 1000, iniFile);
irrklang::ISoundEngine* soundEngine = irrklang::createIrrKlangDevice();
if (nullptr == soundEngine) {
return -1;
}
// 此处添加串口监听线程代码
serial::Serial serialPort(port, baudrate, serial::Timeout::simpleTimeout(timeout));
if (!serialPort.isOpen()) {
return -1;
}
constexpr int32_t bufferSize = 1024;
while (0 == SDL_AtomicGet(&pWindow->Quit)) {
std::string result = serialPort.read(bufferSize);
if (result.empty()) {
continue;
}
// 此处添加串口数据处理代码
//soundEngine->play2D()
const std::string mediaPath = exeDir + "\\media\\getout.ogg";
soundEngine->play2D(mediaPath.c_str());
}
soundEngine->drop();
return 0;
}
void SDLWindow::AudioCallback(void* userdata, Uint8* stream, int len)
{
// 此处添加音频处理代码
}