Skip to content

Commit

Permalink
Expose is_playing; add tests around stop/start exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
ideoforms committed Nov 5, 2023
1 parent 726372c commit 67c1810
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 1 deletion.
10 changes: 10 additions & 0 deletions source/include/signalflow/core/exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,14 @@ struct node_already_playing_exception : public std::runtime_error
: std::runtime_error(message) {}
};

struct node_not_playing_exception : public std::runtime_error
{
using std::runtime_error::runtime_error;

node_not_playing_exception()
: std::runtime_error("Node cannot be stopped as it is not playing") {}
node_not_playing_exception(const char *message)
: std::runtime_error(message) {}
};

}
10 changes: 10 additions & 0 deletions source/include/signalflow/core/graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,16 @@ class AudioGraph
*--------------------------------------------------------------------------------*/
void play(NodeRef node);

/**--------------------------------------------------------------------------------
* Query whether the specified node is currently playing (i.e., connected to
* the graph's output).
*
* @param node The node to query
* @returns true if playing, false otherwise
*
*--------------------------------------------------------------------------------*/
bool is_playing(NodeRef node);

/**--------------------------------------------------------------------------------
* Similar to add_node, but for patches.
* Is a bit of a hacky workaround for the situation in which a Patch is connected
Expand Down
23 changes: 22 additions & 1 deletion source/src/core/graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,15 @@ void AudioGraph::play(NodeRef node)
output->add_input(node);
}

bool AudioGraph::is_playing(NodeRef node)
{
// TODO: This currently only works if the node is wired directly to the
// graph's output. To support nested nodes, should recursively
// traverse the outputs of the node.
AudioOut_Abstract *audioout = (AudioOut_Abstract *) (this->output.get());
return audioout->has_input(node);
}

void AudioGraph::stop(PatchRef patch) { this->stop(patch.get()); }

void AudioGraph::stop(Patch *patch)
Expand All @@ -515,7 +524,19 @@ void AudioGraph::stop(Patch *patch)
nodes_to_remove.insert(patch->get_output());
}

void AudioGraph::stop(NodeRef node) { nodes_to_remove.insert(node); }
void AudioGraph::stop(NodeRef node)
{
// TODO: Should ideally do node->is_playing() here, but this won't catch cases in
// which the node is embedded somewhere within the graph.
if (!node->outputs.empty())
{
nodes_to_remove.insert(node);
}
else
{
throw node_not_playing_exception();
}
}

void AudioGraph::replace(NodeRef node, NodeRef other) { nodes_to_replace.insert(std::make_pair(node, other)); }

Expand Down
1 change: 1 addition & 0 deletions source/src/python/exceptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ void init_python_exceptions(py::module &m)
py::register_exception<signalflow::device_not_found_exception>(m, "DeviceNotFoundException");
py::register_exception<signalflow::audio_io_exception>(m, "AudioIOException");
py::register_exception<signalflow::node_already_playing_exception>(m, "NodeAlreadyPlayingException");
py::register_exception<signalflow::node_not_playing_exception>(m, "NodeNotPlayingException");
py::register_exception<signalflow::cpu_usage_above_limit_exception>(m, "CPUUsageAboveLimitException");
}
13 changes: 13 additions & 0 deletions source/src/python/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,17 @@ void init_python_node(py::module &m)
return inputs;
},
R"pbdoc(Returns a dict of the node's input names and values)pbdoc")
.def_property_readonly(
"outputs", [](Node &node) {
std::vector<Node *> outputs(node.get_outputs().size());
int index = 0;
for (auto output : node.get_outputs())
{
outputs[index++] = output.first;
}
return outputs;
},
R"pbdoc(Returns a list of the node's output connections)pbdoc")
.def_property_readonly(
"output_buffer", [](Node &node) {
/*--------------------------------------------------------------------------------
Expand Down Expand Up @@ -271,6 +282,8 @@ void init_python_node(py::module &m)
*-------------------------------------------------------------------------------*/
.def(
"play", [](NodeRef node) { node->get_graph()->play(node); }, R"pbdoc(Begin playing the node by connecting it to the graph's output)pbdoc")
.def_property_readonly(
"is_playing", [](NodeRef node) { return node->get_graph()->is_playing(node); }, R"pbdoc(Query whether the node is currently playing)pbdoc")
.def(
"stop", [](NodeRef node) { node->get_graph()->stop(node); }, R"pbdoc(Stop playing the node by disconnecting it from the graph's output)pbdoc");

Expand Down

0 comments on commit 67c1810

Please sign in to comment.