diff --git a/AceStepWorker.cpp b/AceStepWorker.cpp index 123ed19..eaabd7c 100644 --- a/AceStepWorker.cpp +++ b/AceStepWorker.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include AceStepWorker::AceStepWorker(QObject *parent) : QObject(parent), @@ -48,10 +50,10 @@ void AceStepWorker::workerFinished() // Worker implementation void AceStepWorker::Worker::run() { - + uint64_t uid = QRandomGenerator::global()->generate(); // Create temporary JSON file for the request QString tempDir = QStandardPaths::writableLocation(QStandardPaths::TempLocation); - QString requestFile = tempDir + "/request_" + QString::number(QCoreApplication::applicationPid()) + ".json"; + QString requestFile = tempDir + "/request_" + QString::number(uid) + ".json"; // Parse and modify the template QJsonParseError parseError; @@ -139,10 +141,10 @@ void AceStepWorker::Worker::run() return; } - if (!qwen3Process.waitForFinished(30000)) { // 30 second timeout + if (!qwen3Process.waitForFinished(60000)) { // 60 second timeout qwen3Process.terminate(); qwen3Process.waitForFinished(5000); - emit parent->generationError("ace-qwen3 timed out after 30 seconds"); + emit parent->generationError("ace-qwen3 timed out after 60 seconds"); return; } @@ -152,13 +154,19 @@ void AceStepWorker::Worker::run() emit parent->generationError("ace-qwen3 exited with code " + QString::number(exitCode) + ": " + errorOutput); return; } + + QString requestLmOutputFile = tempDir + "/request_" + QString::number(uid) + "0.json"; + if (!QFileInfo::exists(requestLmOutputFile)) { + emit parent->generationError("ace-qwen3 failed to create enhaced request file "+requestLmOutputFile); + return; + } emit parent->progressUpdate(50); // Step 2: Run dit-vae to generate audio QProcess ditVaeProcess; QStringList ditVaeArgs; - ditVaeArgs << "--request" << requestFile; + ditVaeArgs << "--request" << requestLmOutputFile; ditVaeArgs << "--text-encoder" << textEncoderModel; ditVaeArgs << "--dit" << ditModel; ditVaeArgs << "--vae" << vaeModel; @@ -188,17 +196,14 @@ void AceStepWorker::Worker::run() emit parent->progressUpdate(90); // Find the generated WAV file - QDir requestDir(QFileInfo(requestFile).absolutePath()); - QStringList wavFiles = requestDir.entryList(QStringList("request*.wav"), QDir::Files, QDir::Name); - - if (wavFiles.isEmpty()) { - emit parent->generationError("No WAV file generated"); + QString wavFile = QFileInfo(requestFile).absolutePath()+"/request_" + QString::number(uid) + "00.wav"; + if (!QFileInfo::exists(wavFile)) { + emit parent->generationError("No WAV file generated at "+wavFile); return; } - QString wavFile = requestDir.absoluteFilePath(wavFiles.first()); - // Clean up temporary files + QFile::remove(requestLmOutputFile); QFile::remove(requestFile); emit parent->progressUpdate(100); diff --git a/CMakeLists.txt b/CMakeLists.txt index 939cdcc..2b40c9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.14) -project(MusicGeneratorGUI LANGUAGES CXX) +project(aceradio LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -7,14 +7,13 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) # Find Qt packages find_package(Qt6 COMPONENTS Core Gui Widgets Multimedia REQUIRED) -# Include acestep.cpp as a subdirectory -#add_subdirectory(acestep.cpp) +# Note: acestep.cpp binaries and models should be provided at runtime set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) # Add executable -add_executable(MusicGeneratorGUI +add_executable(${PROJECT_NAME} main.cpp MainWindow.ui MainWindow.cpp @@ -25,25 +24,19 @@ add_executable(MusicGeneratorGUI ) # UI file -target_include_directories(MusicGeneratorGUI PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) -# Link libraries -target_link_libraries(MusicGeneratorGUI PRIVATE +# Link libraries (only Qt libraries - acestep.cpp is external) +target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core Qt6::Gui Qt6::Widgets Qt6::Multimedia - acestep-core ) -# Include directories -target_include_directories(MusicGeneratorGUI PRIVATE +# Include directories (only our source directory - acestep.cpp is external) +target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/acestep.cpp/src - ${CMAKE_CURRENT_SOURCE_DIR}/acestep.cpp/ggml/include ) -# Copy models directory if it exists -if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/acestep.cpp/models") - file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/acestep.cpp/models" DESTINATION "${CMAKE_BINARY_DIR}") -endif() +# Note: acestep.cpp binaries (ace-qwen3, dit-vae) and models should be provided at runtime diff --git a/MainWindow.cpp b/MainWindow.cpp index 9575393..df71d7b 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -11,6 +11,7 @@ #include #include #include +#include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), @@ -116,6 +117,7 @@ void MainWindow::updateControls() ui->playButton->setEnabled(hasSongs && !isPlaying); ui->skipButton->setEnabled(isPlaying); + ui->stopButton->setEnabled(isPlaying); ui->addSongButton->setEnabled(true); ui->editSongButton->setEnabled(hasSongs && ui->songListView->currentIndex().isValid()); ui->removeSongButton->setEnabled(hasSongs && ui->songListView->currentIndex().isValid()); @@ -148,6 +150,17 @@ void MainWindow::on_skipButton_clicked() } } +void MainWindow::on_stopButton_clicked() +{ + if (isPlaying) { + // Stop current playback completely + audioPlayer->stop(); + isPlaying = false; + ui->statusLabel->setText("Stopped"); + updateControls(); + } +} + void MainWindow::on_shuffleButton_clicked() { shuffleMode = ui->shuffleButton->isChecked(); @@ -414,9 +427,32 @@ void MainWindow::playNextSong() void MainWindow::generationError(const QString &error) { - QMessageBox::critical(this, "Generation Error", "Failed to generate song: " + error); + // Show detailed error in a dialog with QTextEdit + QDialog dialog(this); + dialog.setWindowTitle("Generation Error"); + dialog.resize(600, 400); + + QVBoxLayout *layout = new QVBoxLayout(&dialog); + + QLabel *errorLabel = new QLabel("Error occurred during music generation:"); + errorLabel->setStyleSheet("font-weight: bold; color: darkred;"); + layout->addWidget(errorLabel); + + QTextEdit *errorTextEdit = new QTextEdit(); + errorTextEdit->setReadOnly(true); + errorTextEdit->setPlainText(error); + errorTextEdit->setLineWrapMode(QTextEdit::NoWrap); + errorTextEdit->setFontFamily("Monospace"); + layout->addWidget(errorTextEdit); + + QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok); + layout->addWidget(buttonBox); + + connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); + + dialog.exec(); + isPlaying = false; - ui->statusLabel->setText("Error: " + error); updateControls(); } diff --git a/MainWindow.h b/MainWindow.h index bfeb6c2..a4380bc 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -24,6 +24,7 @@ public: private slots: void on_playButton_clicked(); void on_skipButton_clicked(); + void on_stopButton_clicked(); void on_shuffleButton_clicked(); void on_addSongButton_clicked(); void on_editSongButton_clicked();