diff --git a/assets/20-taverns.mp3 b/assets/20-taverns.mp3 new file mode 100644 index 00000000..3007ebbf Binary files /dev/null and b/assets/20-taverns.mp3 differ diff --git a/include/audio/music_manager.hpp b/include/audio/music_manager.hpp index 981a0673..5305f208 100644 --- a/include/audio/music_manager.hpp +++ b/include/audio/music_manager.hpp @@ -18,6 +18,7 @@ public: void shutdown(); void playMusic(const std::string& mpqPath, bool loop = true); + void playFilePath(const std::string& filePath, bool loop = true); void stopMusic(float fadeMs = 2000.0f); void crossfadeTo(const std::string& mpqPath, float fadeMs = 3000.0f); void update(float deltaTime); diff --git a/include/rendering/renderer.hpp b/include/rendering/renderer.hpp index 3faa2c97..a2c051a9 100644 --- a/include/rendering/renderer.hpp +++ b/include/rendering/renderer.hpp @@ -130,6 +130,7 @@ public: double getLastTerrainRenderMs() const { return lastTerrainRenderMs; } double getLastWMORenderMs() const { return lastWMORenderMs; } double getLastM2RenderMs() const { return lastM2RenderMs; } + audio::MusicManager* getMusicManager() { return musicManager.get(); } private: core::Window* window = nullptr; diff --git a/include/ui/auth_screen.hpp b/include/ui/auth_screen.hpp index d519a2d6..3eaa90f9 100644 --- a/include/ui/auth_screen.hpp +++ b/include/ui/auth_screen.hpp @@ -37,6 +37,8 @@ public: */ bool isAuthenticating() const { return authenticating; } + void stopLoginMusic(); + /** * Get status message */ @@ -88,6 +90,9 @@ private: // Background video bool videoInitAttempted = false; rendering::VideoPlayer backgroundVideo; + + bool musicInitAttempted = false; + bool musicPlaying = false; }; }} // namespace wowee::ui diff --git a/src/audio/music_manager.cpp b/src/audio/music_manager.cpp index f84aeacd..7b721662 100644 --- a/src/audio/music_manager.cpp +++ b/src/audio/music_manager.cpp @@ -72,6 +72,33 @@ void MusicManager::playMusic(const std::string& mpqPath, bool loop) { } } +void MusicManager::playFilePath(const std::string& filePath, bool loop) { + if (filePath.empty()) return; + if (filePath == currentTrack && playing) return; + + stopCurrentProcess(); + + std::vector args; + args.push_back("-nodisp"); + args.push_back("-autoexit"); + if (loop) { + args.push_back("-loop"); + args.push_back("0"); + } + args.push_back("-volume"); + args.push_back("30"); + args.push_back(filePath); + + playerPid = platform::spawnProcess(args); + if (playerPid != INVALID_PROCESS) { + playing = true; + currentTrack = filePath; + LOG_INFO("Music: Playing file ", filePath); + } else { + LOG_ERROR("Music: Failed to spawn ffplay process"); + } +} + void MusicManager::stopMusic(float fadeMs) { (void)fadeMs; // ffplay doesn't support fade easily stopCurrentProcess(); diff --git a/src/ui/auth_screen.cpp b/src/ui/auth_screen.cpp index 75ee8d79..bdba4be5 100644 --- a/src/ui/auth_screen.cpp +++ b/src/ui/auth_screen.cpp @@ -1,6 +1,10 @@ #include "ui/auth_screen.hpp" #include "auth/crypto.hpp" +#include "core/application.hpp" #include "core/logger.hpp" +#include "rendering/renderer.hpp" +#include "pipeline/asset_manager.hpp" +#include "audio/music_manager.hpp" #include #include #include @@ -71,6 +75,23 @@ void AuthScreen::render(auth::AuthHandler& authHandler) { } } + if (!musicInitAttempted) { + musicInitAttempted = true; + auto& app = core::Application::getInstance(); + auto* renderer = app.getRenderer(); + auto* assets = app.getAssetManager(); + if (renderer) { + auto* music = renderer->getMusicManager(); + if (music && assets && assets->isInitialized() && !music->isInitialized()) { + music->initialize(assets); + } + if (music && !musicPlaying) { + music->playFilePath("assets/20-taverns.mp3", true); + musicPlaying = true; + } + } + } + ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver); ImGui::Begin("WoW 3.3.5a Authentication", nullptr, ImGuiWindowFlags_NoCollapse); @@ -197,6 +218,17 @@ void AuthScreen::render(auth::AuthHandler& authHandler) { ImGui::End(); } +void AuthScreen::stopLoginMusic() { + if (!musicPlaying) return; + auto& app = core::Application::getInstance(); + auto* renderer = app.getRenderer(); + if (!renderer) return; + auto* music = renderer->getMusicManager(); + if (!music) return; + music->stopMusic(500.0f); + musicPlaying = false; +} + void AuthScreen::attemptAuth(auth::AuthHandler& authHandler) { // Validate inputs if (strlen(username) == 0) { diff --git a/src/ui/ui_manager.cpp b/src/ui/ui_manager.cpp index bedfcd27..c768360d 100644 --- a/src/ui/ui_manager.cpp +++ b/src/ui/ui_manager.cpp @@ -97,30 +97,35 @@ void UIManager::render(core::AppState appState, auth::AuthHandler* authHandler, break; case core::AppState::REALM_SELECTION: + authScreen->stopLoginMusic(); if (authHandler) { realmScreen->render(*authHandler); } break; case core::AppState::CHARACTER_CREATION: + authScreen->stopLoginMusic(); if (gameHandler) { characterCreateScreen->render(*gameHandler); } break; case core::AppState::CHARACTER_SELECTION: + authScreen->stopLoginMusic(); if (gameHandler) { characterScreen->render(*gameHandler); } break; case core::AppState::IN_GAME: + authScreen->stopLoginMusic(); if (gameHandler) { gameScreen->render(*gameHandler); } break; case core::AppState::DISCONNECTED: + authScreen->stopLoginMusic(); // Show disconnected message ImGui::SetNextWindowSize(ImVec2(400, 150), ImGuiCond_Always); ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x * 0.5f - 200,