Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,12 @@ target_sources(${PROJECT_NAME}
src/gui/HoverHandler.h
src/gui/ControlComponent.h
src/gui/ToggleWithLabel.h
src/gui/FileChooserWithLabel.h

src/media/MediaDisplayComponent.cpp
src/media/AudioDisplayComponent.cpp
src/media/MidiDisplayComponent.cpp
src/media/FileDisplayComponent.cpp
src/media/OutputLabelComponent.cpp

src/media/pianoroll/KeyboardComponent.cpp
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ The currently available versions of HARP and pyharp are mutually compatible.
<!-- website/content/contributing/add_model.md -->
# Adding Models with pyharp

[![ReadMe Card](https://github-readme-stats.vercel.app/api/pin/?username=TEAMuP-dev&repo=pyharp)](https://github.com/TEAMuP-dev/pyharp)
[![PyHARP](https://gh-card.dev/repos/TEAMuP-dev/pyharp.svg)](https://github.com/TEAMuP-dev/pyharp)

pyharp provides a lightweight API to build HARP-compatible [Gradio](https://www.gradio.app) apps. It allows researchers to easily create DAW-friendly interfaces for any audio processing code with minimal Python wrapping.

Expand Down
2 changes: 1 addition & 1 deletion pyharp
Submodule pyharp updated 5 files
+1 −1 LICENSE
+196 −60 README.md
+24 −7 examples/ui_tester/app.py
+22 −8 pyharp/core.py
+2 −2 setup.py
65 changes: 65 additions & 0 deletions src/Model.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,31 @@ class Model
}
}

std::map<Uuid, std::string> fileControlRemotePaths;

for (const auto& controlComponent : controlComponents)
{
if (auto* fileComponentInfo = dynamic_cast<FileComponentInfo*>(controlComponent.get()))
{
if (fileComponentInfo->path.empty())
continue;

String remoteFilePath;

result =
client->uploadFile(loadedPath, File(fileComponentInfo->path), remoteFilePath);

if (result.failed())
{
setStatus(ModelStatus::FAILURE);

return result;
}

fileControlRemotePaths[fileComponentInfo->id] = remoteFilePath.toStdString();
}
}

/* Extract control values for JSON payload in order */

Array<var> controlValues;
Expand Down Expand Up @@ -314,6 +339,25 @@ class Model
{
controlValue = var(comboBoxComponentInfo->value);
}
else if (auto fileComponentInfo = dynamic_cast<FileComponentInfo*>(componentInfo.get()))
{
auto it = fileControlRemotePaths.find(fileComponentInfo->id);

if (it == fileControlRemotePaths.end() || it->second.empty())
{
controlValue = var();
}
else
{
DynamicObject::Ptr fileObj = new DynamicObject();

fileObj->setProperty("path", var(it->second));

controlValue = var(fileObj);
}

wasFile = true;
}
else
{
// Unsupported control was added
Expand Down Expand Up @@ -440,6 +484,17 @@ class Model
DBG_AND_LOG("Model::extractInputs: MIDI track input \"" + midiTrack->label
+ "\" extracted.");
}
else if (type == "generic_file")
{
std::shared_ptr<ModelComponentInfo> fileChooser =
std::make_shared<FileComponentInfo>(controlsDict);

newControls.push_back(fileChooser);
tempComponentIDs.push_back(fileChooser->id);

DBG_AND_LOG("Model::extractInputs: File chooser control \"" + fileChooser->label
+ "\" extracted.");
}
else if (type == "text_box")
{
std::shared_ptr<ModelComponentInfo> textControl =
Expand Down Expand Up @@ -563,6 +618,16 @@ class Model
DBG_AND_LOG("Model::extractOutputs: MIDI track output \"" + midiTrack->label
+ "\" extracted.");
}
else if (type == "generic_file")
{
std::shared_ptr<ModelComponentInfo> fileOutput =
std::make_shared<FileComponentInfo>(controlsDict);

newOutputs.push_back(fileOutput);

DBG_AND_LOG("Model::extractOutputs: File output \"" + fileOutput->label
+ "\" extracted.");
}
else if (type == "json")
{
// Labels are handled separately
Expand Down
21 changes: 20 additions & 1 deletion src/ModelTab.h
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,23 @@ class ModelTab : public Component, private ChangeListener, public ChangeBroadcas
}
}

for (const auto& controlInfo : model->getControls())
{
if (auto* fileInfo = dynamic_cast<FileComponentInfo*>(controlInfo.get()))
{
if (fileInfo->required && fileInfo->path.empty())
{
AlertWindow::showMessageBoxAsync(
AlertWindow::WarningIcon,
"Error",
"Required file input \"" + String(fileInfo->label)
+ "\" is empty. Please select a file before processing.");

return;
}
}
}

modelSelectionWidget.setDisabled();
processCancelButton.setMode(cancelButtonInfo.displayLabel);

Expand Down Expand Up @@ -536,7 +553,9 @@ class ModelTab : public Component, private ChangeListener, public ChangeBroadcas
{
auto& outputMediaDisplays = outputTrackAreaWidget.getMediaDisplays();

for (size_t i = 0; i < outputMediaDisplays.size(); ++i)
for (size_t i = 0;
i < outputMediaDisplays.size() && i < outputFilesPtr->size();
++i)
{
outputMediaDisplays[i]->initializeDisplay(
URL((*outputFilesPtr)[i]));
Expand Down
5 changes: 5 additions & 0 deletions src/gui/ControlComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ class ControlComponent : public Component
public:
virtual ~ControlComponent() = default;

/**
* Returns the preferred height for this control, or 0 to use the layout default.
*/
virtual int getPreferredHeight() const { return 0; }

/**
* Returns the minimum width required to display this control properly.
* This includes the label width plus any necessary padding.
Expand Down
Loading
Loading