Skip to content

Commit

Permalink
Finish first version of api docs
Browse files Browse the repository at this point in the history
  • Loading branch information
alisomay committed Dec 22, 2023
1 parent 6cc92e9 commit d925eda
Show file tree
Hide file tree
Showing 12 changed files with 179 additions and 84 deletions.
152 changes: 93 additions & 59 deletions API_DOCS.md

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ crate-type = ["cdylib"]

[dependencies]
median = { git = "https://github.com/Cycling74/median" }
rytm-rs = { path = "../rytm-rs/rytm" }
rytm-rs = "0.1"
thiserror = "1.0.24"
lazy_static = "1.4.0"

Expand Down
21 changes: 21 additions & 0 deletions LICENCE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2023 - Ali Somay ([email protected])

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
60 changes: 49 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,33 +1,51 @@
# rytm-external

A MaxMSP external to communicate with Analog Rytm MKII through sysex. This external is powered by [`rytm-rs`](https://github.com/alisomay/rytm-rs) and should be currently considered as a beta software. Please report any issue you may encounter through github issues.
A MaxMSP external to communicate with Analog Rytm MKII through sysex.

`rytm` provides a rich interface to communicate with Analog Rytm MKII through sysex. It has verbose and informative error reporting, inherits all the features of `rytm-rs` and provides comprehensive documentation.
This external is powered by [`rytm-rs`](https://github.com/alisomay/rytm-rs) and should be currently considered as beta software. Please report any issue you may encounter through [github issues](https://github.com/alisomay/rytm-external/issues).

`rytm` provides a rich interface to communicate with Analog Rytm MKII through sysex.

It has verbose and informative error reporting, inherits all the features of `rytm-rs` and provides comprehensive documentation.

All the following documentation below this section is written with the assumption of basic knowledge of the Analog Rytm drum machines and MaxMSP.

## Installation

One can obtain the builds from the [releases]() page which contains builds for major operating systems. If you want to build the external yourself, you will need to install [rust](https://www.rust-lang.org/tools/install). Then, please follow the build and install instructions from [median]() repository.
One can obtain the builds from the [releases](https://github.com/alisomay/rytm-external/releases) page which contains builds for major operating systems.

If you want to build the external yourself, you will need to install [rust](https://www.rust-lang.org/tools/install). Then, please follow the build and install instructions from [median](https://github.com/Cycling74/median/blob/develop/median/README.md) repository.

## Preparation in your patch

Once you installed the external you may instantiate it in the MaxMSP patch by writing `rytm` in an object box.

Connect the `sysexin` object to `rytm`'s inlet and `rytm`'s leftmost outlet to `midiout` object.

Set your ports for `sysexin` and `midiout` objects so they point to your device and you're ready to go.

The rightmost outlet of `rytm` object is used to respond to get and set queries.

## Context

`rytm` when instantiated contains a twin of a default project on Analog Rytm MKII. Important thing to know is this is not yet the data on your device.
`rytm` when instantiated contains a twin of a default project on Analog Rytm MKII.

Important thing to know is this is not yet the data on your device.

We'll update parts of the `rytm` by querying the device when needed.

`rytm` is not yet an interface for `cc` or `nrpn` messages which are well documented in the manual. It is a `sysex` interface where the format is reverse engineered as a community effort see [`rytm-rs`](https://github.com/alisomay/rytm-rs) and these threads from elektronauts for details:
`rytm` is not yet an interface for `cc` or `nrpn` messages which are well documented in the manual.

It is a `sysex` interface where the format is reverse engineered as a community effort see [`rytm-rs`](https://github.com/alisomay/rytm-rs) and these threads from [elektronauts](https://www.elektronauts.com) for details:

- <https://www.elektronauts.com/t/announcing-an-unofficial-sdk-for-analog-rytm-mkii-running-firmware-1-70-written-in-rust/205232>
- <https://www.elektronauts.com/t/rytm-sysex-list/>

-
-
`rytm` follows the devices not officially supported and undocumented `sysex` format.

`rytm` follows the devices not officially supported and undocumented `sysex` format. This means that it is not guaranteed to work with future firmware updates unless new versions of this external are released. Currently the supported firmware version is `1.70` and it is only tested on Analog Rytm MKII.
This means that it is not guaranteed to work with future firmware updates unless new versions of this external are released.

Currently the supported firmware version is `1.70` and it is only tested on Analog Rytm MKII.

### The format and the project structure

Expand All @@ -44,22 +62,27 @@ A `rytm` project is made of
- Settings (a single structure for the whole project)

`rytm` enables you to query all these structures from the device, edit them in great detail and send them back to the device.

If you wish you can also edit the default ones which comes with `rytm`'s instantiation and send them to the device.

To work productively with `rytm` an understanding of these structures and the connection between them is necessary.

The following sections will explain the structures briefly.

Note that this is a brief introduction to the structures. For more detailed and complete information please refer to the [api docs](API_DOCS.md), the source code and the community.

#### What is the work buffer?

The device has something called a "work buffer" which points to the pattern you're currently chosen, kit you're currently chosen, etc.

Think of it as a pointer to the currently selected or active structure.

#### Patterns

Think of patterns as the sheet music. They are a set of instructions for the sequencer. They don't contain any settings for the sounds.

This is where your notes, trigs, mutes, locks, retrigs, microtiming, etc. are stored.

Also patterns store the kit number they are associated with.

#### Kits
Expand All @@ -82,6 +105,7 @@ Settings contain the muted sounds, selected track, selected pattern mode and mor
### Queries

Since the `rytm` contains the twin of the structures on the device we can query them and update the `rytm`'s structures with the data from the device.

This is done by starting our messages with `query` selector. For example `query pattern 1` will query the pattern 1 (2 on device) from the device and update the `rytm`'s pattern 1 with the data from the device.

All indexes are 0 based so the first pattern is 0, the first kit is 0, etc.
Expand Down Expand Up @@ -117,27 +141,37 @@ Accepted formats are:
#### Getting data from `rytm` external

This is done by starting our messages with `get` selector.
The details of the format and the output format are explained in the [api docs]().
The details of the format and the output format are explained in the [api docs](API_DOCS.md).

#### Setting data in the `rytm` external

This is done by starting our messages with `set` selector.
The details of the format and the input format are explained in the [api docs]().
The details of the format and the input format are explained in the [api docs](API_DOCS.md).

#### Parameter locking

soon..
The pattern structure holds the parameter lock pool for that pattern.

Think of it as a pool where you can store parameter locks, set or clear them.

You have a space of 72 different parameter locks for every trig in a pattern.

If you exceed that the memory will be full.

There will be detailed documentation about this in the near future about how it is handled internally and how does sound and kit structures link to a certain pattern's parameter lock pool.

#### Look out

Do not query or send data to the device in a perpetual way without the minimum of a 750-800 ms interval. This is not dangerous but the data is usually large and it is processed in the low priority thread of the device. The device may queue the responses or requests and may not be able to process them in time.

When you send the initial `sysex` message to the device for the first time after power on it usually responds with an irrelevant message and never does it again.

This will appear as an error in the max window called "short read" you may safely ignore this error.

## Todo

Setting, getting and parameter locking machine parameters is not yet implemented.

There are no technical obstacle there but it takes good amount of time due to the large amount of machines.
I'll do it some time later.

Expand All @@ -148,9 +182,13 @@ Saving and loading projects packed as a `sysex` file is not yet implemented. Thi
## Contributing

I am aware that this is a very niche project, did by a single person and the code base is not very well documented.

On the other hand I still think that an experienced developer in the field may follow it easily.

I'm always open to contributions and I'll do my best to help you understand the code base and the project.

Rust [code of conduct](https://www.rust-lang.org/policies/code-of-conduct) applies to this project. Please be nice and respectful.

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
Expand Down
4 changes: 2 additions & 2 deletions src/action/get/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ pub fn handle_global_get_enum_value(
let index_atom = Atom::from(AtomValue::Int(global.index() as isize));
let enum_value_atom = Atom::from(SymbolRef::try_from(value).unwrap());

if let Err(_stack_overflow_err) = out.send(&[enum_type_atom, index_atom, enum_value_atom][..]) {
if let Err(_stack_overflow_err) = out.send(&[index_atom, enum_type_atom, enum_value_atom][..]) {
// Stack overflow ignore
}

Expand Down Expand Up @@ -178,7 +178,7 @@ pub fn handle_global_get_action(
let index_atom = Atom::from(AtomValue::Int(global.index() as isize));
let value_atom = Atom::from(value);

if let Err(_stack_overflow_err) = out.send(&[action_atom, index_atom, value_atom][..]) {
if let Err(_stack_overflow_err) = out.send(&[index_atom, action_atom, value_atom][..]) {
// Stack overflow ignore
}

Expand Down
2 changes: 1 addition & 1 deletion src/action/get/kit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,8 @@ pub fn handle_kit_get_kit_element(
if let Err(_stack_overflow_err) = out.send(
&[
kit_index_atom,
element_type_atom,
element_index_atom,
element_type_atom,
value_atom,
][..],
) {
Expand Down
4 changes: 2 additions & 2 deletions src/action/get/pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ pub fn handle_pattern_get_action(action: PatternGetAction) -> Result<(), RytmExt
let action_atom = Atom::from(action);
let index_atom = Atom::from(AtomValue::Int(pattern.index() as isize));

if let Err(_stack_overflow_err) = out.send(&[action_atom, index_atom, value_atom][..]) {
if let Err(_stack_overflow_err) = out.send(&[index_atom, action_atom, value_atom][..]) {
// Stack overflow ignore
}

Expand All @@ -84,7 +84,7 @@ pub fn handle_pattern_enum_get_action(
let index_atom = Atom::from(AtomValue::Int(pattern.index() as isize));
let enum_value_atom = Atom::from(SymbolRef::try_from(value).unwrap());

if let Err(_stack_overflow_err) = out.send(&[enum_type_atom, index_atom, enum_value_atom][..]) {
if let Err(_stack_overflow_err) = out.send(&[index_atom, enum_type_atom, enum_value_atom][..]) {
// Stack overflow ignore
}

Expand Down
4 changes: 2 additions & 2 deletions src/action/get/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub fn handle_settings_get_enum_value(
let enum_value_atom = Atom::from(SymbolRef::try_from(value).unwrap());

if let Err(_stack_overflow_err) =
out.send(&[enum_type_atom, Atom::from(0isize), enum_value_atom][..])
out.send(&[Atom::from(0isize), enum_type_atom, enum_value_atom][..])
{
// Stack overflow ignore
}
Expand Down Expand Up @@ -64,7 +64,7 @@ pub fn handle_settings_get_action(
};

let action_atom = Atom::from(SymbolRef::from(CString::new(action).unwrap()));
if let Err(_stack_overflow_err) = out.send(&[action_atom, Atom::from(0isize), value_atom][..]) {
if let Err(_stack_overflow_err) = out.send(&[Atom::from(0isize), action_atom, value_atom][..]) {
// Stack overflow ignore
}

Expand Down
4 changes: 2 additions & 2 deletions src/action/get/sound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub fn handle_sound_get_enum_value(
let index_atom = Atom::from(AtomValue::Int(sound.index() as isize));
let enum_value_atom = Atom::from(SymbolRef::try_from(value).unwrap());

if let Err(_stack_overflow_err) = out.send(&[enum_type_atom, index_atom, enum_value_atom][..]) {
if let Err(_stack_overflow_err) = out.send(&[index_atom, enum_type_atom, enum_value_atom][..]) {
// Stack overflow ignore
}

Expand Down Expand Up @@ -160,7 +160,7 @@ pub fn handle_sound_get_action(

let action_atom = Atom::from(SymbolRef::from(CString::new(action).unwrap()));
let index_atom = Atom::from(AtomValue::Int(sound.index() as isize));
if let Err(_stack_overflow_err) = out.send(&[action_atom, index_atom, value_atom][..]) {
if let Err(_stack_overflow_err) = out.send(&[index_atom, action_atom, value_atom][..]) {
// Stack overflow ignore
}

Expand Down
4 changes: 2 additions & 2 deletions src/action/get/track.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ pub fn handle_track_get_action(action: TrackGetAction) -> Result<(), RytmExterna
let value_atom = Atom::from(AtomValue::Int(value as isize));

if let Err(_stack_overflow_err) =
out.send(&[action_atom, pattern_index_atom, index_atom, value_atom][..])
out.send(&[pattern_index_atom, index_atom, action_atom, value_atom][..])
{
// Stack overflow ignore
}
Expand Down Expand Up @@ -94,9 +94,9 @@ pub fn handle_track_enum_get_action(

if let Err(_stack_overflow_err) = out.send(
&[
enum_type_atom,
pattern_index_atom,
index_atom,
enum_type_atom,
enum_value_atom,
][..],
) {
Expand Down
4 changes: 2 additions & 2 deletions src/action/get/trig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub fn handle_trig_get_action(action: TrigGetAction) -> Result<(), RytmExternalE
let value_atom = Atom::from(AtomValue::Int(value));

if let Err(_stack_overflow_err) =
out.send(&[action_atom, track_index_atom, index_atom, value_atom][..])
out.send(&[track_index_atom, index_atom, action_atom, value_atom][..])
{
// Stack overflow ignore
}
Expand Down Expand Up @@ -92,9 +92,9 @@ pub fn handle_trig_enum_get_action(

if let Err(_stack_overflow_err) = out.send(
&[
enum_type_atom,
track_index_atom,
index_atom,
enum_type_atom,
enum_value_atom,
][..],
) {
Expand Down

0 comments on commit d925eda

Please sign in to comment.