diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..ed9d83a --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,79 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +osmid is a lightweight, portable tool for converting between MIDI and OSC (Open Sound Control) protocols. It consists of two main executables: +- `m2o`: MIDI to OSC conversion +- `o2m`: OSC to MIDI conversion + +The project is built with C++14 and uses CMake as the build system. It's used as the MIDI communication layer in Sonic Pi. + +## Build Commands + +### Initial Build Setup +```bash +mkdir build +cd build +cmake .. +make +``` + +### Platform-Specific Build +- **Windows**: `cmake -G "Visual Studio 16 2019" -A x64 ..` +- **Linux/Mac**: `cmake ..` then `make` + +### Code Quality Checks +- **Whitespace check**: `python utils/check_whitespace.py` (checks for trailing whitespace and tab indentation) + +## Architecture + +### Core Components +- **src/m2o.cpp**: Main entry point for MIDI-to-OSC converter +- **src/o2m.cpp**: Main entry point for OSC-to-MIDI converter +- **src/midicommon.h/.cpp**: Base class for MIDI device management with sticky ID system +- **src/midiin.h/.cpp**: MIDI input device wrapper using JUCE +- **src/midiout.h/.cpp**: MIDI output device wrapper using JUCE +- **src/oscin.h/.cpp**: OSC input handling using oscpack +- **src/oscout.h/.cpp**: OSC output handling using oscpack +- **src/midiinprocessor.h/.cpp**: Processes incoming MIDI and converts to OSC +- **src/oscinprocessor.h/.cpp**: Processes incoming OSC and converts to MIDI +- **src/monitorlogger.h**: Singleton logger that can output to both console and OSC +- **src/utils.h/.cpp**: String utilities for OSC address formatting + +### Key Design Patterns +- **Sticky ID System**: MIDI devices maintain consistent IDs across disconnections/reconnections via MidiCommon base class +- **Template-based OSC Addressing**: Customizable OSC address patterns using variables like $n (port name), $i (port id), $c (channel), $m (message type) +- **Singleton Logger**: MonitorLogger provides centralized logging to both console and OSC destinations +- **Processor Pattern**: Separate processor classes handle the conversion logic between MIDI and OSC + +### Dependencies (all included in tree) +- **JUCE**: Cross-platform audio/MIDI framework (JuceLibraryCode/) +- **oscpack**: OSC message handling and UDP networking (external_libs/oscpack_1_1_0/) +- **spdlog**: Fast logging library (external_libs/spdlog-0.11.0/) +- **cxxopts**: Command-line option parsing (external_libs/cxxopts/) + +### Platform Support +- Windows (MSVC 2015+) +- Linux (gcc 4.9+, requires ALSA) +- macOS (clang 5.1+) + +## Development Notes + +### Code Style +- Uses spaces for indentation (no tabs) +- No trailing whitespace +- C++14 standard +- Headers use `#pragma once` + +### Testing +- No formal test suite for the main application +- External libraries include their own tests +- Manual testing via MIDI device interaction and OSC message monitoring + +### Logging Levels +0-6 scale where smaller numbers = more verbose output + +### Version Management +Version numbers defined in src/version.h (currently 0.8.0) \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 24af4eb..2f9e591 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ +cmake_minimum_required (VERSION 3.5) project (osmid) -cmake_minimum_required (VERSION 3.0) set(CMAKE_VERBOSE_MAKEFILE ON) diff --git a/JuceLibraryCode/modules/juce_core/native/juce_osx_ObjCHelpers.h b/JuceLibraryCode/modules/juce_core/native/juce_osx_ObjCHelpers.h index 440df43..c0304f9 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_osx_ObjCHelpers.h +++ b/JuceLibraryCode/modules/juce_core/native/juce_osx_ObjCHelpers.h @@ -97,7 +97,7 @@ static inline ReturnValue ObjCMsgSendSuper (struct objc_super* s, SEL sel, Param typedef id (*MsgSendSuperFn) (struct objc_super*, SEL, ...); static inline MsgSendSuperFn getMsgSendSuperFn() noexcept { return (MsgSendSuperFn) (void*) objc_msgSendSuper; } -#if ! JUCE_IOS +#if ! JUCE_IOS && ! defined(MAC_OS_VERSION_11_0) typedef double (*MsgSendFPRetFn) (id, SEL op, ...); static inline MsgSendFPRetFn getMsgSendFPRetFn() noexcept { return (MsgSendFPRetFn) (void*) objc_msgSend_fpret; } #endif diff --git a/README.md b/README.md index 0acc64e..7cfd25c 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,8 @@ For build instruction see INSTALL.md. osmid is built using C++14 features. The build system is based on cmake. Tested target compiler in Windows is MSVC 2015 Win64, in Linux is gcc 4.9 or later, and on Mac, clang 5.1 or later. Under Windows, prepare using something like: `cmake -G "Visual Studio 16 2019" -A x64 .. `. On Linux and Mac `cmake ..` should be enough. +**Note for macOS users**: The CMake minimum version has been updated to 3.5 to support modern macOS builds. Additionally, a fix has been applied to handle the removal of `objc_msgSend_fpret` in newer macOS SDKs. + osmid uses the following libs: * JUCE for the midi handling and OSC handling (included in the tree) * oscpack, for the OSC handling and UDP networking (included in the tree) diff --git a/external_libs/oscpack_1_1_0/CMakeLists.txt b/external_libs/oscpack_1_1_0/CMakeLists.txt index 65abd17..c19984d 100644 --- a/external_libs/oscpack_1_1_0/CMakeLists.txt +++ b/external_libs/oscpack_1_1_0/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.5) PROJECT(TestOscpack) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}) diff --git a/src/midiinprocessor.cpp b/src/midiinprocessor.cpp index 6978920..d8e04ef 100644 --- a/src/midiinprocessor.cpp +++ b/src/midiinprocessor.cpp @@ -71,7 +71,12 @@ void MidiInProcessor::handleIncomingMidiMessage(MidiInput* source, const juce::M break; case 0x90: - message_type = "note_on"; + // Note-on with velocity 0 should be treated as note-off + if (nBytes == 3 && message[2] == 0) { + message_type = "note_off"; + } else { + message_type = "note_on"; + } assert(nBytes == 3); break;