Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python rust backend #470

Open
wants to merge 38 commits into
base: master
Choose a base branch
from
Open

Python rust backend #470

wants to merge 38 commits into from

Conversation

SanderVocke
Copy link
Owner

No description provided.

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Summary

Based on the provided files, I'll summarize the key changes in this pull request focusing on the most important aspects:

Major transition from C to Rust backend bindings with significant architectural changes:

  • Introduced thread-safe Rust wrappers around C FFI pointers using Mutex protection in audio_driver.rs and backend_session.rs
  • Added new integer_enum! macro in macros.rs for type-safe enum conversions between Rust and C
  • Implemented proper resource cleanup through Rust's Drop trait for audio drivers and backend sessions
  • Created PyO3-based Python bindings in shoop_py_backend modules to expose Rust functionality
  • Removed global backend/driver tracking in favor of Rust's ownership model

Key concerns to address:

  • Mutex lock error handling needs improvement in audio_driver.rs and backend_session.rs
  • Unsafe FFI operations require additional validation and error checks
  • Memory safety guarantees around pointer handling could be strengthened
  • Resource cleanup timing during application shutdown needs verification

The changes represent a significant architectural improvement but require careful review of thread safety and resource management aspects.

24 file(s) reviewed, 33 comment(s)
Edit PR Review Bot Settings | Greptile

void destroy_audio_driver(shoop_audio_driver_t *driver) {
return api_impl<void, log_level_debug_trace>("destroy_audio_driver", [&]() {
auto _driver = internal_audio_driver(driver);
if (!_driver) { return; }
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: potential memory leak - should delete the driver pointer after closing and removing from active drivers

Comment on lines +2272 to +2273
_driver->close();
g_active_drivers.erase(_driver);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: close() should be called after removing from g_active_drivers to prevent race conditions if close triggers callbacks

Comment on lines +1229 to +1230
audio_obj = shoop_py_backend.MultichannelAudio(n_channels, n_frames)
resampled_obj = audio_obj.resample(target_n_frames)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: No data is being copied from input audio array to audio_obj before resampling

Comment on lines 274 to 275
QTimer.singleShot(1, lambda: self.quit())
self.exec()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: The exec() call after scheduling quit() could cause a race condition if backends are not fully closed

Comment on lines 8 to +9
anyhow = "1.0"
static_assertions = "1.1"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: Consider pinning exact version with '=1.1.1' instead of '1.1' to ensure reproducible builds

Comment on lines +20 to +22
fn unsafe_backend_ptr (&self) -> usize {
unsafe { self.obj.unsafe_backend_ptr() as usize }
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: unsafe pointer exposure without validation or documentation of safety requirements

Comment on lines +24 to +30
fn set_audio_driver(&self, driver : &AudioDriver) -> PyResult<()> {
if self.obj.set_audio_driver(&driver.obj).is_ok() {
Ok(())
} else {
Err(PyErr::new::<pyo3::exceptions::PyException, _>("set_audio_driver() failed"))
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: error message lacks detail about what specifically failed in set_audio_driver

Comment on lines +9 to +11
pub struct BackendSession {
pub obj : backend_bindings::BackendSession,
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style: pub field allows direct access to backend object, bypassing safety checks

impl MultichannelAudio {
#[new]
fn py_new(n_channels : u32, n_frames : u32) -> PyResult<Self> {
Ok(MultichannelAudio { obj: backend_bindings::MultichannelAudio::new(n_channels as u32, n_frames as u32).unwrap() })
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: Using unwrap() here is unsafe and will panic if allocation fails. Should properly handle the error case and convert to PyErr

#[pymethods]
impl MultichannelAudio {
#[new]
fn py_new(n_channels : u32, n_frames : u32) -> PyResult<Self> {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: No validation of n_channels or n_frames being non-zero. Should check inputs are valid before allocation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant