Skip to content

Commit b6472aa

Browse files
add else_subset abstractions; improve path handling when opening patches
1 parent d6b6ad3 commit b6472aa

File tree

4 files changed

+90
-10
lines changed

4 files changed

+90
-10
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@ compile_commands.json
1616

1717
src/gen/
1818
build/
19+
20+
demo/addons/godot-pd/else_subset

CMakeLists.txt

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,40 @@ set_target_properties(
101101
)
102102

103103
install(TARGETS godot-pd DESTINATION .)
104+
105+
106+
107+
set(ELSE_SUBSET_ABSTRACTIONS_INSTALL_DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/demo/addons/godot-pd/else_subset")
108+
109+
file(REMOVE_RECURSE ${ELSE_SUBSET_ABSTRACTIONS_INSTALL_DESTINATION})
110+
111+
file(GLOB PD_ELSE_ABSTRACTIONS_AUDIO "${CMAKE_CURRENT_SOURCE_DIR}/pd-else/Abstractions/Audio/*")
112+
file(GLOB PD_ELSE_ABSTRACTIONS_CONTROL "${CMAKE_CURRENT_SOURCE_DIR}/pd-else/Abstractions/Control/*")
113+
file(GLOB PD_ELSE_ABSTRACTIONS_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/pd-else/Abstractions/Extra/*")
114+
115+
file(COPY
116+
${PD_ELSE_ABSTRACTIONS_AUDIO}
117+
${PD_ELSE_ABSTRACTIONS_CONTROL}
118+
${PD_ELSE_ABSTRACTIONS_EXTRA}
119+
DESTINATION ${ELSE_SUBSET_ABSTRACTIONS_INSTALL_DESTINATION}
120+
)
121+
122+
# these depend on [sfload] and [sfinfo], which are removed from else_subset
123+
set(EXCLUDED_ABSTRACTIONS
124+
"sample~.pd"
125+
"player~.pd"
126+
"pvoc.player~.pd"
127+
"pvoc~.pd"
128+
"gran.player~.pd"
129+
)
130+
list(TRANSFORM EXCLUDED_ABSTRACTIONS PREPEND "${ELSE_SUBSET_ABSTRACTIONS_INSTALL_DESTINATION}/")
131+
file(REMOVE ${EXCLUDED_ABSTRACTIONS})
132+
133+
file(GLOB_RECURSE ELSE_SUBSET_ABSTRACTIONS "${ELSE_SUBSET_ABSTRACTIONS_INSTALL_DESTINATION}/*")
134+
foreach(FILE_PATH ${ELSE_SUBSET_ABSTRACTIONS})
135+
if(NOT IS_DIRECTORY ${FILE_PATH})
136+
file(READ ${FILE_PATH} FILE_CONTENTS)
137+
string(REPLACE "else/" "" FILE_CONTENTS "${FILE_CONTENTS}")
138+
file(WRITE ${FILE_PATH} "${FILE_CONTENTS}")
139+
endif()
140+
endforeach()

src/audio_stream_pd.cpp

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#include <algorithm>
44
#include <filesystem>
55
#include <godot_cpp/classes/engine.hpp>
6+
#include <godot_cpp/classes/os.hpp>
7+
#include <godot_cpp/classes/project_settings.hpp>
68
#include <godot_cpp/core/class_db.hpp>
79
#include <godot_cpp/core/error_macros.hpp>
810

@@ -42,8 +44,8 @@ int AudioStreamPD::get_mix_rate() const {
4244
//////////////
4345

4446
void AudioStreamPlaybackPD::_bind_methods() {
45-
ClassDB::bind_method(D_METHOD("open_patch", "path"), &AudioStreamPlaybackPD::open_patch);
46-
ClassDB::bind_method(D_METHOD("close_patch", "path"), &AudioStreamPlaybackPD::close_patch);
47+
ClassDB::bind_method(D_METHOD("open_patch", "relative_path"), &AudioStreamPlaybackPD::open_patch);
48+
ClassDB::bind_method(D_METHOD("close_patch", "relative_path"), &AudioStreamPlaybackPD::close_patch);
4749
ClassDB::bind_method(D_METHOD("close_patch_id", "dollar_zero"), &AudioStreamPlaybackPD::close_patch_id);
4850
ClassDB::bind_method(D_METHOD("send_bang", "dest"), &AudioStreamPlaybackPD::send_bang);
4951
ClassDB::bind_method(D_METHOD("send_float", "dest", "value"), &AudioStreamPlaybackPD::send_float);
@@ -100,13 +102,49 @@ pd::List AudioStreamPlaybackPD::_pd_list_from(const Array &p_arr) {
100102
return list;
101103
}
102104

105+
String AudioStreamPlaybackPD::get_absolute_patch_path(String p_relative_path) {
106+
if (OS::get_singleton()->has_feature("editor")) {
107+
// Running from an editor binary.
108+
return ProjectSettings::get_singleton()->globalize_path("res://")
109+
.path_join(p_relative_path)
110+
.simplify_path();
111+
} else {
112+
// Running from an exported project.
113+
//
114+
// This is NOT identical to using `ProjectSettings.globalize_path()` with a `res://` path,
115+
// but is close enough in spirit.
116+
// On macOS, this would be `YourGameName.app/Contents/MacOS`
117+
// see https://apple.stackexchange.com/questions/228116/add-delete-modify-files-within-a-disk-image-dmg//403082
118+
// and https://github.com/godotengine/godot/issues/22950
119+
//
120+
// Note that you will have to MANUALLY copy the `pd` directory there.
121+
// Setting "filter to exporting non-resource files" will pack it
122+
// into .pck file that is not accessable by libpd
123+
return OS::get_singleton()->get_executable_path()
124+
.get_base_dir()
125+
.path_join(p_relative_path)
126+
.simplify_path();
127+
}
128+
}
129+
103130
AudioStreamPlaybackPD::AudioStreamPlaybackPD() {
104131
active = false;
105132
stream = nullptr;
106133
receiver.set_signaller(this);
107134
pd.setReceiver(&receiver);
108135
pd.setMidiReceiver(&receiver);
109136

137+
std::string path_to_else_subset_abstractions = std_string_from(
138+
OS::get_singleton()->has_feature("editor")
139+
? ProjectSettings::get_singleton()->globalize_path("res://addons/godot-pd/else_subset")
140+
: OS::get_singleton()->get_executable_path().get_base_dir().path_join("else_subset")
141+
);
142+
ERR_FAIL_COND_MSG(
143+
!fs::is_directory(fs::path(path_to_else_subset_abstractions)),
144+
"Trying to add " + godot_string_from(path_to_else_subset_abstractions) + " to libpd search path, but it does not exist"
145+
);
146+
pd.addToSearchPath(path_to_else_subset_abstractions);
147+
110148
// setup external libs
111149
else_subset_setup();
112150
}
@@ -159,12 +197,13 @@ void AudioStreamPlaybackPD::_start(double p_from_pos) {
159197
begin_resample();
160198
}
161199

162-
int AudioStreamPlaybackPD::open_patch(String p_path) {
163-
fs::path path = fs::path(std_string_from(p_path)).lexically_normal();
200+
int AudioStreamPlaybackPD::open_patch(String p_relative_path) {
201+
String abs_path = get_absolute_patch_path(p_relative_path);
202+
fs::path path = fs::path(std_string_from(abs_path)).lexically_normal();
164203
auto filename = path.filename().string();
165204
auto dir = path.parent_path().string();
166205

167-
ERR_FAIL_COND_V_MSG(filename.empty(), -1, "No filename included in path" + p_path);
206+
ERR_FAIL_COND_V_MSG(filename.empty(), -1, "No filename included in path" + abs_path);
168207

169208
if (dir.empty()) {
170209
dir = ".";
@@ -178,12 +217,13 @@ int AudioStreamPlaybackPD::open_patch(String p_path) {
178217
return patch.dollarZero();
179218
}
180219

181-
void AudioStreamPlaybackPD::close_patch(String p_path) {
182-
fs::path path = fs::path(std_string_from(p_path)).lexically_normal();
220+
void AudioStreamPlaybackPD::close_patch(String p_relative_path) {
221+
String abs_path = get_absolute_patch_path(p_relative_path);
222+
fs::path path = fs::path(std_string_from(abs_path)).lexically_normal();
183223
auto filename = path.filename().string();
184224
auto dir = path.parent_path().string();
185225

186-
ERR_FAIL_COND_MSG(filename.empty(), "No filename included in path" + p_path);
226+
ERR_FAIL_COND_MSG(filename.empty(), "No filename included in path" + abs_path);
187227

188228
if (dir.empty()) {
189229
dir = ".";

src/audio_stream_pd.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,14 @@ class AudioStreamPlaybackPD : public AudioStreamPlaybackResampled {
4646
protected:
4747
static void _bind_methods();
4848
static pd::List _pd_list_from(const Array &p_arr);
49+
static String get_absolute_patch_path(String p_relative_path);
4950

5051
public:
5152
int32_t _mix_resampled(AudioFrame *p_dst_buffer, int32_t p_frame_count) override;
5253
float _get_stream_sampling_rate() const override;
5354
void _start(double p_from_pos) override;
54-
int open_patch(String p_path);
55-
void close_patch(String p_path);
55+
int open_patch(String p_relative_path);
56+
void close_patch(String p_relative_path);
5657
void close_patch_id(int p_dollar_zero);
5758
void send_bang(String p_dest);
5859
void send_float(String p_dest, float p_value);

0 commit comments

Comments
 (0)