Skip to content

Commit

Permalink
Add CTL Support
Browse files Browse the repository at this point in the history
  • Loading branch information
Dudejoe870 committed Jul 2, 2024
1 parent 92f0259 commit 2892d65
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 14 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Just go to the prebuilt branch and use the download ZIP feature of Github, extra

If you want to take a look at a commit that's more recent, then you can download the addon as a CI build artifact from the Github workflow action.

Unfortunately there are no MacOS, Android, iOS, or any 32-bit binaries currently prebuilt. If you need any of those you will have to build them yourself (and in the case of mobile platforms, add them to the .gdextension file)
Unfortunately there are no MacOS, Android, iOS, or any 32-bit binaries currently prebuilt. If you need any of those you will have to build them yourself and add them to the .gdextension file.

## Documentation

Expand Down
12 changes: 12 additions & 0 deletions addons/godot-openmpt/mpt_importer.gd
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ func _get_import_options(path, preset_index) -> Array[Dictionary]:
"property_hint": PROPERTY_HINT_ENUM,
"hint_string": "Disabled,Enabled",
"default_value": 0
},
{
"name": "load/skip_plugins",
"type": TYPE_BOOL,
"default_value": false
},
{
"name": "load/skip_subsongs_init",
"type": TYPE_BOOL,
"default_value": false
}]

func _get_option_visibility(path, option_name, options) -> bool:
Expand All @@ -57,6 +67,8 @@ func _import(source_file, save_path, options, r_platform_variants, r_gen_files)
return ERR_PARSE_ERROR

var stream = AudioStreamMPT.new()
stream.skip_plugins = options["load/skip_plugins"]
stream.skip_subsongs_init = options["load/skip_subsongs_init"]
stream.data = file_data
if stream.data.is_empty():
return stream.get_module_error()
Expand Down
4 changes: 0 additions & 4 deletions addons/godot-openmpt/openmpt.gdextension
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@ compatibility_minimum = "4.2"

macos.debug = "bin/libgdmpt-macos.debug.64.framework"
macos.release = "bin/libgdmpt-macos.release.64.framework"
windows.debug.x86_32 = "bin/libgdmpt-windows.debug.32.dll"
windows.release.x86_32 = "bin/libgdmpt-windows.release.32.dll"
windows.debug.x86_64 = "bin/libgdmpt-windows.debug.64.dll"
windows.release.x86_64 = "bin/libgdmpt-windows.release.64.dll"
linux.debug.x86_32 = "bin/libgdmpt-linux.debug.32.so"
linux.release.x86_32 = "bin/libgdmpt-linux.release.32.so"
linux.debug.x86_64 = "bin/libgdmpt-linux.debug.64.so"
linux.release.x86_64 = "bin/libgdmpt-linux.release.64.so"
2 changes: 1 addition & 1 deletion addons/godot-openmpt/plugin.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
name="Godot OpenMPT"
description="Integrates OpenMPT as a playable AudioStream"
author="Dudejoe870"
version="1.0.0"
version="1.3"
script="mpt_import.gd"
73 changes: 65 additions & 8 deletions src/audio_stream_mpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ using namespace godot;
#define CHECK_MOD_LOADED_RETV() if (!this->mpt_module) { WARN_PRINT_ED(MOD_NOT_LOADED_MSG); return; }

#define CHECK_INT_LOADED_RET(retval) CHECK_MOD_LOADED_RET(retval); if (!this->mpt_interactive) { WARN_PRINT_ED(INT_NOT_LOADED_MSG); return retval; }
#define CHECK_INT_LOADED_RETV() CHECK_MOD_LOADED_RETV(); if (!this->mpt_module) { WARN_PRINT_ED(INT_NOT_LOADED_MSG); return; }
#define CHECK_INT_LOADED_RETV() CHECK_MOD_LOADED_RETV(); if (!this->mpt_interactive) { WARN_PRINT_ED(INT_NOT_LOADED_MSG); return; }

#define CHECK_INT2_LOADED_RET(retval) CHECK_MOD_LOADED_RET(retval); if (!this->mpt_interactive) { WARN_PRINT_ED(INT2_NOT_LOADED_MSG); return retval; }
#define CHECK_INT2_LOADED_RETV() CHECK_MOD_LOADED_RETV(); if (!this->mpt_module) { WARN_PRINT_ED(INT2_NOT_LOADED_MSG); return; }
#define CHECK_INT2_LOADED_RET(retval) CHECK_MOD_LOADED_RET(retval); if (!this->mpt_interactive2) { WARN_PRINT_ED(INT2_NOT_LOADED_MSG); return retval; }
#define CHECK_INT2_LOADED_RETV() CHECK_MOD_LOADED_RETV(); if (!this->mpt_interactive2) { WARN_PRINT_ED(INT2_NOT_LOADED_MSG); return; }

#define CHECK_INT3_LOADED_RET(retval) CHECK_MOD_LOADED_RET(retval); if (!this->mpt_interactive) { WARN_PRINT_ED(INT3_NOT_LOADED_MSG); return retval; }
#define CHECK_INT3_LOADED_RETV() CHECK_MOD_LOADED_RETV(); if (!this->mpt_module) { WARN_PRINT_ED(INT3_NOT_LOADED_MSG); return; }
#define CHECK_INT3_LOADED_RET(retval) CHECK_MOD_LOADED_RET(retval); if (!this->mpt_interactive3) { WARN_PRINT_ED(INT3_NOT_LOADED_MSG); return retval; }
#define CHECK_INT3_LOADED_RETV() CHECK_MOD_LOADED_RETV(); if (!this->mpt_interactive3) { WARN_PRINT_ED(INT3_NOT_LOADED_MSG); return; }

void AudioStreamPlaybackMPT::_start(double p_from_pos) {
_seek(p_from_pos);
Expand Down Expand Up @@ -285,6 +285,16 @@ double AudioStreamPlaybackMPT::get_note_finetune(int32_t channel) const {
return this->mpt_interactive2->get_note_finetune(channel);
}

void AudioStreamPlaybackMPT::set_sync_samples(bool p_enable) {
CHECK_MOD_LOADED_RETV();
this->mpt_module->ctl_set_boolean("seek.sync_samples", p_enable);
}

bool AudioStreamPlaybackMPT::get_sync_samples() const {
CHECK_MOD_LOADED_RET(true);
return this->mpt_module->ctl_get_boolean("seek.sync_samples");
}

int32_t AudioStreamPlaybackMPT::_mix(AudioFrame *p_buffer, double p_rate_scale, int32_t p_frames) {
if (!this->mpt_module) {
active = false;
Expand Down Expand Up @@ -382,6 +392,9 @@ void AudioStreamPlaybackMPT::_bind_methods() {

ClassDB::bind_method(D_METHOD("set_note_finetune", "channel", "finetune"), &AudioStreamPlaybackMPT::set_note_finetune);
ClassDB::bind_method(D_METHOD("get_note_finetune", "channel"), &AudioStreamPlaybackMPT::get_note_finetune);

ClassDB::bind_method(D_METHOD("set_sync_samples", "sync_samples"), &AudioStreamPlaybackMPT::set_sync_samples);
ClassDB::bind_method(D_METHOD("get_sync_samples"), &AudioStreamPlaybackMPT::get_sync_samples);
}

AudioStreamPlaybackMPT::AudioStreamPlaybackMPT() {}
Expand Down Expand Up @@ -423,6 +436,38 @@ bool AudioStreamMPT::_is_monophonic() const {
return false;
}

void AudioStreamMPT::set_skip_plugins(bool p_enable) {
this->skip_plugins = p_enable;
}

bool AudioStreamMPT::get_skip_plugins() const {
return this->skip_plugins;
}

void AudioStreamMPT::set_skip_subsongs_init(bool p_enable) {
this->skip_subsongs_init = p_enable;
}

bool AudioStreamMPT::get_skip_subsongs_init() const {
return this->skip_subsongs_init;
}

void AudioStreamMPT::set_sync_samples(bool p_enable) {
this->sync_samples = p_enable;
}

bool AudioStreamMPT::get_sync_samples() const {
return this->sync_samples;
}

std::map<std::string, std::string> AudioStreamMPT::get_initial_ctls() const {
return std::map<std::string, std::string> {
{ "load.skip_plugins", this->skip_plugins ? "1" : "0" },
{ "load.skip_subsongs_init", this->skip_subsongs_init ? "1" : "0" },
{ "seek.sync_samples", this->sync_samples ? "1" : "0" },
};
}

void AudioStreamMPT::set_data(const PackedByteArray& p_data) {
module_error = Error::OK;

Expand All @@ -435,7 +480,7 @@ void AudioStreamMPT::set_data(const PackedByteArray& p_data) {

if (this->mpt_module) delete mpt_module;
try {
this->mpt_module = new openmpt::module(this->data.ptr(), this->data.size());
this->mpt_module = new openmpt::module(this->data.ptr(), this->data.size(), std::clog, get_initial_ctls());
} catch (openmpt::exception& e) {
module_error = Error::ERR_PARSE_ERROR;
goto set_empty_module;
Expand All @@ -445,7 +490,7 @@ void AudioStreamMPT::set_data(const PackedByteArray& p_data) {
AudioServer::get_singleton()->lock();
for (AudioStreamPlaybackMPT* playback : open_playback_objects) {
if (playback->mpt_module) delete playback->mpt_module;
playback->mpt_module = new openmpt::module_ext(this->data.ptr(), this->data.size());
playback->mpt_module = new openmpt::module_ext(this->data.ptr(), this->data.size(), std::clog, get_initial_ctls());
playback->mpt_interactive = static_cast<openmpt::ext::interactive*>(
playback->mpt_module->get_interface(openmpt::ext::interactive_id));
playback->mpt_interactive2 = static_cast<openmpt::ext::interactive2*>(
Expand Down Expand Up @@ -646,7 +691,7 @@ Ref<AudioStreamPlayback> AudioStreamMPT::_instantiate_playback() const {
Ref<AudioStreamPlaybackMPT> playback;
playback.instantiate();
playback->base = Ref<AudioStreamMPT>(this);
playback->mpt_module = !data.is_empty() ? new openmpt::module_ext(this->data.ptr(), this->data.size()) : nullptr;
playback->mpt_module = !data.is_empty() ? new openmpt::module_ext(this->data.ptr(), this->data.size(), std::clog, get_initial_ctls()) : nullptr;
if (playback->mpt_module)
{
playback->mpt_interactive = static_cast<openmpt::ext::interactive*>(
Expand All @@ -671,6 +716,14 @@ void AudioStreamMPT::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_stereo", "stereo"), &AudioStreamMPT::set_stereo);
ClassDB::bind_method(D_METHOD("is_stereo"), &AudioStreamMPT::is_stereo);

ClassDB::bind_method(D_METHOD("set_skip_plugins", "skip_plugins"), &AudioStreamMPT::set_skip_plugins);
ClassDB::bind_method(D_METHOD("get_skip_plugins"), &AudioStreamMPT::get_skip_plugins);
ClassDB::bind_method(D_METHOD("set_skip_subsongs_init", "skip_subsongs_init"), &AudioStreamMPT::set_skip_subsongs_init);
ClassDB::bind_method(D_METHOD("get_skip_subsongs_init"), &AudioStreamMPT::get_skip_subsongs_init);

ClassDB::bind_method(D_METHOD("set_sync_samples", "sync_samples"), &AudioStreamMPT::set_sync_samples);
ClassDB::bind_method(D_METHOD("get_sync_samples"), &AudioStreamMPT::get_sync_samples);

ClassDB::bind_method(D_METHOD("set_data", "data"), &AudioStreamMPT::set_data);
ClassDB::bind_method(D_METHOD("get_data"), &AudioStreamMPT::get_data);

Expand Down Expand Up @@ -716,6 +769,10 @@ void AudioStreamMPT::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_mode", PROPERTY_HINT_ENUM, "Disabled,Enabled"), "set_loop_mode", "get_loop_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stereo"), "set_stereo", "is_stereo");

ADD_PROPERTY(PropertyInfo(Variant::BOOL, "skip_plugins"), "set_skip_plugins", "get_skip_plugins");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "skip_subsongs_init"), "set_skip_subsongs_init", "get_skip_subsongs_init");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sync_samples"), "set_sync_samples", "get_sync_samples");

BIND_ENUM_CONSTANT(LOOP_DISABLED);
BIND_ENUM_CONSTANT(LOOP_ENABLED);

Expand Down
20 changes: 20 additions & 0 deletions src/audio_stream_mpt.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ class AudioStreamPlaybackMPT : public AudioStreamPlayback {
void set_note_finetune(int32_t channel, double finetune);
double get_note_finetune(int32_t channel) const;

void set_sync_samples(bool p_enable);
bool get_sync_samples() const;

virtual int32_t _mix(AudioFrame *p_buffer, double p_rate_scale, int32_t p_frames) override;

AudioStreamPlaybackMPT();
Expand All @@ -124,6 +127,9 @@ class AudioStreamMPT : public AudioStream {
private:
LoopMode loop_mode = LoopMode::LOOP_DISABLED;
bool stereo = true;
bool skip_plugins = false;
bool skip_subsongs_init = false;
bool sync_samples = true;
PackedByteArray data;

// We need to create a module to parse any information about the file,
Expand All @@ -134,6 +140,8 @@ class AudioStreamMPT : public AudioStream {

Error module_error = Error::OK;

std::map<std::string, std::string> get_initial_ctls() const;

friend class AudioStreamPlaybackMPT;
protected:
static void _bind_methods();
Expand All @@ -147,6 +155,18 @@ class AudioStreamMPT : public AudioStream {
virtual double _get_length() const override;
virtual bool _is_monophonic() const override;

// Load CTLs
// These only apply on the next module load.
// Whether that means loading new data into this stream, or instantiating a new playback.
void set_skip_plugins(bool p_enable);
bool get_skip_plugins() const;
void set_skip_subsongs_init(bool p_enable);
bool get_skip_subsongs_init() const;

// Seek CTLs
void set_sync_samples(bool p_enable);
bool get_sync_samples() const;

void set_data(const PackedByteArray& p_data);
const PackedByteArray& get_data() const;

Expand Down

0 comments on commit 2892d65

Please sign in to comment.