Skip to content

Commit 3265b23

Browse files
refactor: destination ownership and connection logic
1 parent 08a5ee2 commit 3265b23

4 files changed

Lines changed: 76 additions & 13 deletions

File tree

packages/react-native-audio-api/common/cpp/audioapi/HostObjects/AudioNodeHostObject.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ JSI_HOST_FUNCTION_IMPL(AudioNodeHostObject, disconnect) {
8181
// node_->disconnect();
8282
return jsi::Value::undefined();
8383
}
84+
8485
auto obj = args[0].getObject(runtime);
8586
if (obj.isHostObject<AudioNodeHostObject>(runtime)) {
8687
auto node = obj.getHostObject<AudioNodeHostObject>(runtime);
Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <audioapi/HostObjects/destinations/AudioDestinationNodeHostObject.h>
2+
#include <audioapi/HostObjects/utils/JsEnumParser.h>
23

34
#include <memory>
45
#include <utility>
@@ -7,24 +8,56 @@ namespace audioapi {
78

89
AudioDestinationNodeHostObject::AudioDestinationNodeHostObject(
910
utils::graph::HostGraph::Node *node,
10-
std::shared_ptr<AudioDestinationNode> destination)
11-
: node_(node), destination_(std::move(destination)) {
12-
addGetters(
13-
JSI_EXPORT_PROPERTY_GETTER(AudioDestinationNodeHostObject, numberOfInputs),
14-
JSI_EXPORT_PROPERTY_GETTER(AudioDestinationNodeHostObject, numberOfOutputs),
15-
JSI_EXPORT_PROPERTY_GETTER(AudioDestinationNodeHostObject, channelCount));
11+
std::shared_ptr<AudioDestinationNode> destination,
12+
const AudioDestinationOptions &options)
13+
: node_(node), destination_(std::move(destination)),
14+
numberOfInputs_(options.numberOfInputs),
15+
numberOfOutputs_(options.numberOfOutputs),
16+
channelCount_(options.channelCount),
17+
channelCountMode_(options.channelCountMode),
18+
channelInterpretation_(options.channelInterpretation) {
19+
addGetters(
20+
JSI_EXPORT_PROPERTY_GETTER(AudioDestinationNodeHostObject, numberOfInputs),
21+
JSI_EXPORT_PROPERTY_GETTER(AudioDestinationNodeHostObject, numberOfOutputs),
22+
JSI_EXPORT_PROPERTY_GETTER(AudioDestinationNodeHostObject, channelCount),
23+
JSI_EXPORT_PROPERTY_GETTER(AudioDestinationNodeHostObject, channelCountMode),
24+
JSI_EXPORT_PROPERTY_GETTER(AudioDestinationNodeHostObject, channelInterpretation));
25+
26+
addFunctions(
27+
JSI_EXPORT_FUNCTION(AudioDestinationNodeHostObject, connect),
28+
JSI_EXPORT_FUNCTION(AudioDestinationNodeHostObject, disconnect));
1629
}
1730

1831
JSI_PROPERTY_GETTER_IMPL(AudioDestinationNodeHostObject, numberOfInputs) {
19-
return {1};
32+
return {numberOfInputs_};
2033
}
2134

2235
JSI_PROPERTY_GETTER_IMPL(AudioDestinationNodeHostObject, numberOfOutputs) {
23-
return {0};
36+
return {numberOfOutputs_};
2437
}
2538

2639
JSI_PROPERTY_GETTER_IMPL(AudioDestinationNodeHostObject, channelCount) {
27-
return {static_cast<int>(destination_->getChannelCount())};
40+
return {static_cast<int>(channelCount_)};
41+
}
42+
43+
JSI_PROPERTY_GETTER_IMPL(AudioDestinationNodeHostObject, channelCountMode) {
44+
return jsi::String::createFromUtf8(
45+
runtime, js_enum_parser::channelCountModeToString(channelCountMode_));
46+
}
47+
48+
JSI_PROPERTY_GETTER_IMPL(AudioDestinationNodeHostObject, channelInterpretation) {
49+
return jsi::String::createFromUtf8(
50+
runtime, js_enum_parser::channelInterpretationToString(channelInterpretation_));
51+
}
52+
53+
/// AudioDestinationNode is the end point of the audio graph, it cannot connect to any other node, so connect and disconnect are no-op
54+
JSI_HOST_FUNCTION_IMPL(AudioDestinationNodeHostObject, connect) {
55+
return jsi::Value::undefined();
56+
}
57+
58+
/// AudioDestinationNode is the end point of the audio graph, it cannot connect to any other node, so connect and disconnect are no-op
59+
JSI_HOST_FUNCTION_IMPL(AudioDestinationNodeHostObject, disconnect) {
60+
return jsi::Value::undefined();
2861
}
2962

3063
} // namespace audioapi

packages/react-native-audio-api/common/cpp/audioapi/HostObjects/destinations/AudioDestinationNodeHostObject.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,22 @@
33
#include <audioapi/core/destinations/AudioDestinationNode.h>
44
#include <audioapi/core/utils/graph/HostGraph.hpp>
55
#include <audioapi/jsi/JsiHostObject.h>
6+
#include <audioapi/types/NodeOptions.h>
67

78
#include <memory>
89

910
namespace audioapi {
1011
using namespace facebook;
1112

13+
/// HostObject for AudiodestinationNode, which is the end point of the audio graph.
14+
/// It is treated differently than other AudioNodes, because it shares ownership of underlying AudioDestinationNode with BaseAudioContext.
15+
/// Hence all AudioNodeHostObject methods and proprties has to be implemented duplicated.
1216
class AudioDestinationNodeHostObject : public JsiHostObject {
1317
public:
1418
explicit AudioDestinationNodeHostObject(
1519
utils::graph::HostGraph::Node *node,
16-
std::shared_ptr<AudioDestinationNode> destination);
20+
std::shared_ptr<AudioDestinationNode> destination,
21+
const AudioDestinationOptions &options = AudioDestinationOptions());
1722

1823
[[nodiscard]] utils::graph::HostGraph::Node *rawNode() const {
1924
return node_;
@@ -22,10 +27,24 @@ class AudioDestinationNodeHostObject : public JsiHostObject {
2227
JSI_PROPERTY_GETTER_DECL(numberOfInputs);
2328
JSI_PROPERTY_GETTER_DECL(numberOfOutputs);
2429
JSI_PROPERTY_GETTER_DECL(channelCount);
30+
JSI_PROPERTY_GETTER_DECL(channelCountMode);
31+
JSI_PROPERTY_GETTER_DECL(channelInterpretation);
32+
33+
JSI_HOST_FUNCTION_DECL(connect);
34+
JSI_HOST_FUNCTION_DECL(disconnect);
2535

2636
private:
27-
utils::graph::HostGraph::Node *node_; // borrowed from BaseAudioContext; never removed
37+
// borrowed from BaseAudioContext's graph - non-owning
38+
// no risk of dangling pointer here since destination node in TS holds ref to context =>
39+
// destination HO will not outlive context HO => graph is owned by context HO
40+
utils::graph::HostGraph::Node *node_; // borrowed from BaseAudioContext's graph - non-owning
2841
std::shared_ptr<AudioDestinationNode> destination_;
42+
43+
const int numberOfInputs_;
44+
const int numberOfOutputs_;
45+
size_t channelCount_;
46+
const ChannelCountMode channelCountMode_;
47+
const ChannelInterpretation channelInterpretation_;
2948
};
3049

3150
} // namespace audioapi

packages/react-native-audio-api/src/core/AudioNode.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { IAudioNode } from '../interfaces';
22
import AudioParam from './AudioParam';
33
import { ChannelCountMode, ChannelInterpretation } from '../types';
44
import BaseAudioContext from './BaseAudioContext';
5-
import { InvalidAccessError } from '../errors';
5+
import { IndexSizeError } from '../errors';
66

77
export default class AudioNode {
88
readonly context: BaseAudioContext;
@@ -27,14 +27,24 @@ export default class AudioNode {
2727
public connect(destination: AudioParam): void;
2828
public connect(destination: AudioNode | AudioParam): AudioNode | void {
2929
if (this.context !== destination.context) {
30-
throw new InvalidAccessError(
30+
throw new IndexSizeError(
3131
'Source and destination are from different BaseAudioContexts'
3232
);
3333
}
3434

35+
if (this.numberOfOutputs === 0) {
36+
throw new IndexSizeError('Faild to connect: AudioNode has no output');
37+
}
38+
3539
if (destination instanceof AudioParam) {
3640
this.node.connect(destination.audioParam);
3741
} else {
42+
if (destination.numberOfInputs === 0) {
43+
throw new IndexSizeError(
44+
'Failed to connect: destination AudioNode has no input'
45+
);
46+
}
47+
3848
this.node.connect(destination.node);
3949
return destination;
4050
}

0 commit comments

Comments
 (0)