├── .DS_Store ├── .gitattributes ├── .gitignore ├── Icon ├── midi-osc-midi.icns ├── midi-osc-midi.png └── midi-port.psd ├── README.md ├── addons.make ├── bin └── data │ ├── .gitkeep │ └── MIDI_OSC_SETTINGS.json ├── screenshots ├── Conversion.jpg ├── MidiIn.jpg ├── MidiOut.jpg ├── OSCIn.jpg └── OSCOut.jpg └── src ├── .DS_Store ├── MidiConstants.h ├── MidiManager.cpp ├── MidiManager.h ├── OcsManager.cpp ├── OscManager.h ├── SettingsManager.cpp ├── SettingsManager.h ├── colours.h ├── main.cpp ├── modes ├── ConversionMode.cpp ├── ConversionMode.h ├── MidiInSetupMode.cpp ├── MidiInSetupMode.h ├── MidiOutSetupMode.cpp ├── MidiOutSetupMode.h ├── Mode.cpp ├── Mode.h ├── ModeManager.cpp ├── ModeManager.h ├── OscInSetupMode.cpp ├── OscInSetupMode.h ├── OscOutSetupMode.cpp └── OscOutSetupMode.h ├── ofApp.cpp ├── ofApp.h └── simpleButton.h /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fred-dev/OSC_MIDI_OSC/a4d127eb9653ef357f936bfab3f7f5b52667bb38/.DS_Store -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore all files by default 2 | * 3 | 4 | # Allow directories and files 5 | !/src/ 6 | !/addons.make 7 | !/README.md 8 | !/bin/data/ 9 | !/Icon/ 10 | !/screenshots/ 11 | 12 | # Exclude all .DS_Store files 13 | .DS_Store -------------------------------------------------------------------------------- /Icon/midi-osc-midi.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fred-dev/OSC_MIDI_OSC/a4d127eb9653ef357f936bfab3f7f5b52667bb38/Icon/midi-osc-midi.icns -------------------------------------------------------------------------------- /Icon/midi-osc-midi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fred-dev/OSC_MIDI_OSC/a4d127eb9653ef357f936bfab3f7f5b52667bb38/Icon/midi-osc-midi.png -------------------------------------------------------------------------------- /Icon/midi-port.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fred-dev/OSC_MIDI_OSC/a4d127eb9653ef357f936bfab3f7f5b52667bb38/Icon/midi-port.psd -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OSC_MIDI_OSC 2 | 3 | 4 | 5 | A straightforward cross-platform converter for OSC to MIDI and MIDI to OSC. Designed for zero-configuration, simply set your MIDI and OSC ports, and the software will handle the translation between MIDI and OSC seamlessly. It operates bidirectionally, performing both functions simultaneously. 6 | 7 | You will have to structure the OSC messages in the format described below. 8 | 9 | This tool is practical but also serves as a learning journey for me in software design. 10 | If you have any tips, suggestions, or feature requests, please don't hesitate to reach out. 11 | 12 | - **Made with**: [openframeworks](https://github.com/openframeworks/openFrameworks) 13 | 14 | ## Downloads - if you want to just use the app 15 | 16 | - **MAC OS 10.15+ (ish) 64 bit**: Available on the release tab. 17 | - **Windows 10+ 64 bit**: Available on the release tab. 18 | 19 | > **Note**: Linux has many requirements. If you're looking for a fast and light solution for Linux, this may not be for you due to the heavy dependencies of openframeworks. 20 | 21 | ## Setup - if you want to play with the code 22 | 23 | 1. Download [openframeworks](https://openframeworks.cc/download/) and set it up for your platform. 24 | 2. Navigate to `openframeworksRoot/myApps/` and clone this repository. 25 | 3. Navigate to `openframeworksRoot/addons/` and clone the following repositories: 26 | - [ofxMidi](https://github.com/danomatika/ofxMidi) 27 | - [ofxTextInputField](https://github.com/Flightphase/ofxTextInputField) 28 | - [ofxMSAInteractiveObject](https://github.com/memo/ofxMSAInteractiveObject) 29 | 4. Use the project generator for your platform to generate a project. 30 | 5. Compile for your platform. 31 | 32 | ### Configuration - running the software 33 | 34 | To configure the app, go to the `data` folder and edit the `MIDI_OSC_SETTINGS.json` file, or change the settings from the GUI! You can set the incoming and outgoing midi and OSC ports and the destination IP. 35 | 36 | ## Updates 37 | 38 | - Now includes Midi Machine control. 39 | - Basic interactive GUI for on-the-go settings adjustments. 40 | - Midi Show Control is now included (beta version). 41 | 42 | ## Windows Users 43 | 44 | To use this with Windows, ensure you install a virtual midi port. We recommend [Loopmidi from Tobias Erichsen](http://www.tobias-erichsen.de/software/loopmidi.html). 45 | 46 | ## To-Do 47 | 48 | - More detailed MSC and MTC. 49 | 50 | ## OSC Format 51 | 52 | The OSC format is consistent for both sending and receiving. Here are the detailed descriptions of the address formats: 53 | 54 | - **/cc**: For controller values with two int arguments: the controller number and the value. 55 | - **/noteOn**: For note on messages with two int arguments: note value and velocity. 56 | - **/noteOff**: For note off messages with one int argument: note value. 57 | - **/Aftertouch**: For mono aftertouch off messages with one int argument: value. 58 | - **/PolyAftertouch**: For polyphonic aftertouch messages with two int arguments: pitch and value. 59 | - **/Pitchbend**: For pitch bend messages with one int argument: value. 60 | - **/ProgramChange**: For program change messages with one int argument: program value. 61 | 62 | The software receives OSC messages in these formats and will automatically send the corresponding MIDI signals. Incoming MIDI signals will trigger OSC messages in the same formats. 63 | 64 | The app wll output MMC commands from the following OSC inputs, add an int argument for the device ID and a string argument for the command 65 | 66 | Address: "/MMCCommand" 67 | Commands are: 68 | 69 | - `stop` 70 | - `play` 71 | - `deferred_play` 72 | - `fast_forward` 73 | - `rewind` 74 | - `record_strobe` 75 | - `record_exit` 76 | - `record_pause` 77 | - `pause` 78 | - `eject` 79 | - `chase` 80 | - `command_error_reset` 81 | - `mmc_reset` 82 | 83 | 84 | The app wll output Midi Show Control commands from the following OSC inputs, add an int argument for the device ID, a string argument 85 | for the command target and another string argument for the command type, lastly add extra integer arguments for the command payload (up to 3) 86 | 87 | ### Here are the command targets: 88 | - `lighting` 89 | - `moving_lights` 90 | - `colour_changers` 91 | - `strobes` 92 | - `lasers` 93 | - `chasers` 94 | - `sound` 95 | - `music` 96 | - `cd_players` 97 | - `eprom_playback` 98 | - `audio_tape_machines` 99 | - `intercoms` 100 | - `amplifiers` 101 | - `audio_effects_devices` 102 | - `equalisers` 103 | - `machinery` 104 | - `rigging` 105 | - `flys` 106 | - `lifts` 107 | - `turntables` 108 | - `trusses` 109 | - `robots` 110 | - `animation` 111 | - `floats` 112 | - `breakaways` 113 | - `barges` 114 | - `video` 115 | - `video_tape_machines` 116 | - `video_cassette_machines` 117 | - `video_disc_players` 118 | - `video_switchers` 119 | - `video_effects` 120 | - `video_character_generators` 121 | - `video_still_stores` 122 | - `video_monitors` 123 | - `projection` 124 | - `film_projectors` 125 | - `slide_projectors` 126 | - `video_projectors` 127 | - `dissolvers` 128 | - `shutter_controls` 129 | - `process_control` 130 | - `hydraulic_oil` 131 | - `h20` 132 | - `co2` 133 | - `compressed_air` 134 | - `natural_gas` 135 | - `fog` 136 | - `smoke` 137 | - `cracked_haze` 138 | - `pyro` 139 | - `fireworks` 140 | - `explosions` 141 | - `flame` 142 | - `smoke_pots` 143 | - `all_types` 144 | 145 | ### And here are the command types: 146 | 147 | - `go` 148 | - `stop` 149 | - `resume` 150 | - `timed_go` 151 | - `load` 152 | - `set` 153 | - `fire` 154 | - `all_off` 155 | - `restore` 156 | - `reset` 157 | - `go_off` 158 | - `go_jam_clock` 159 | - `standby+` 160 | - `standby-` 161 | - `sequence+` 162 | - `sequence-` 163 | - `start_clock` 164 | - `stop_clock` 165 | - `zero_clock` 166 | - `set_clock` 167 | - `mtc_chase_on` 168 | - `mtc_chase_off` 169 | - `open_cue_list` 170 | - `close_cue_list` 171 | - `open_cue_path` 172 | -------------------------------------------------------------------------------- /addons.make: -------------------------------------------------------------------------------- 1 | ofxMSAInteractiveObject 2 | ofxMidi 3 | ofxOsc 4 | ofxTextInputField 5 | -------------------------------------------------------------------------------- /bin/data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fred-dev/OSC_MIDI_OSC/a4d127eb9653ef357f936bfab3f7f5b52667bb38/bin/data/.gitkeep -------------------------------------------------------------------------------- /bin/data/MIDI_OSC_SETTINGS.json: -------------------------------------------------------------------------------- 1 | { 2 | "Log_level": 0, 3 | "allInPorts": [ 4 | "Euphonix EuMidi1 0", 5 | "Euphonix EuMidi2 1", 6 | "Euphonix EuMidi3 2", 7 | "Euphonix EuMidi4 3", 8 | "Euphonix EuMidi5 4", 9 | "Euphonix EuMidi6 5", 10 | "Euphonix EuMidi7 6", 11 | "Euphonix EuMidi8 7", 12 | "loopMIDI Port 8" 13 | ], 14 | "allOutPorts": [ 15 | "Microsoft GS Wavetable Synth 0", 16 | "Euphonix EuMidi1 1", 17 | "Euphonix EuMidi2 2", 18 | "Euphonix EuMidi3 3", 19 | "Euphonix EuMidi4 4", 20 | "Euphonix EuMidi5 5", 21 | "Euphonix EuMidi6 6", 22 | "Euphonix EuMidi7 7", 23 | "Euphonix EuMidi8 8", 24 | "loopMIDI Port 9" 25 | ], 26 | "frameRate": 25, 27 | "inPortLabel": "Euphonix EuMidi1 0", 28 | "incomingPortOsc": 1233, 29 | "midiInChannel": 1, 30 | "midiInDevice": "IAC Driver Bus 1", 31 | "midiInDeviceByString": true, 32 | "midiInDeviceName": null, 33 | "midiInDeviceNum": 0, 34 | "midiOuDeviceByString": false, 35 | "midiOutChannel": 1, 36 | "midiOutDevice": "Isadora Virtual In", 37 | "midiOutDeviceByString": true, 38 | "midiOutDeviceName": null, 39 | "midiOutDeviceNum": 0, 40 | "outGoingPortOsc": 1234, 41 | "outPortLabel": "Microsoft GS Wavetable Synth 0", 42 | "outgoingIpOSC": "127.0.0.1", 43 | "useVirtualPort": false 44 | } -------------------------------------------------------------------------------- /screenshots/Conversion.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fred-dev/OSC_MIDI_OSC/a4d127eb9653ef357f936bfab3f7f5b52667bb38/screenshots/Conversion.jpg -------------------------------------------------------------------------------- /screenshots/MidiIn.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fred-dev/OSC_MIDI_OSC/a4d127eb9653ef357f936bfab3f7f5b52667bb38/screenshots/MidiIn.jpg -------------------------------------------------------------------------------- /screenshots/MidiOut.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fred-dev/OSC_MIDI_OSC/a4d127eb9653ef357f936bfab3f7f5b52667bb38/screenshots/MidiOut.jpg -------------------------------------------------------------------------------- /screenshots/OSCIn.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fred-dev/OSC_MIDI_OSC/a4d127eb9653ef357f936bfab3f7f5b52667bb38/screenshots/OSCIn.jpg -------------------------------------------------------------------------------- /screenshots/OSCOut.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fred-dev/OSC_MIDI_OSC/a4d127eb9653ef357f936bfab3f7f5b52667bb38/screenshots/OSCOut.jpg -------------------------------------------------------------------------------- /src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fred-dev/OSC_MIDI_OSC/a4d127eb9653ef357f936bfab3f7f5b52667bb38/src/.DS_Store -------------------------------------------------------------------------------- /src/MidiConstants.h: -------------------------------------------------------------------------------- 1 | // 2 | // MSCConstants.h 3 | // OSC_MIDI_OSC 4 | // 5 | // Created by Fred Rodrigues on 29/09/2023. 6 | // 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | 13 | // Define the Midi Show Control Target Type map 14 | const std::unordered_map MIDI_SHOW_CONTROL_TARGET_TYPE = { 15 | {0x01, "lighting"}, 16 | {0x02, "moving_lights"}, 17 | {0x03, "colour_changers"}, 18 | {0x04, "strobes"}, 19 | {0x05, "lasers"}, 20 | {0x06, "chasers"}, 21 | {0x10, "sound"}, 22 | {0x11, "music"}, 23 | {0x12, "cd_players"}, 24 | {0x13, "eprom_playback"}, 25 | {0x14, "audio_tape_machines"}, 26 | {0x15, "intercoms"}, 27 | {0x16, "amplifiers"}, 28 | {0x17, "audio_effects_devices"}, 29 | {0x18, "equalisers"}, 30 | {0x20, "machinery"}, 31 | {0x21, "rigging"}, 32 | {0x22, "flys"}, 33 | {0x23, "lifts"}, 34 | {0x24, "turntables"}, 35 | {0x25, "trusses"}, 36 | {0x26, "robots"}, 37 | {0x27, "animation"}, 38 | {0x28, "floats"}, 39 | {0x29, "breakaways"}, 40 | {0x2a, "barges"}, 41 | {0x30, "video"}, 42 | {0x31, "video_tape_machines"}, 43 | {0x32, "video_cassette_machines"}, 44 | {0x33, "video_disc_players"}, 45 | {0x34, "video_switchers"}, 46 | {0x35, "video_effects"}, 47 | {0x36, "video_character_generators"}, 48 | {0x37, "video_still_stores"}, 49 | {0x38, "video_monitors"}, 50 | {0x40, "projection"}, 51 | {0x41, "film_projectors"}, 52 | {0x42, "slide_projectors"}, 53 | {0x43, "video_projectors"}, 54 | {0x44, "dissolvers"}, 55 | {0x45, "shutter_controls"}, 56 | {0x50, "process_control"}, 57 | {0x51, "hydraulic_oil"}, 58 | {0x52, "h20"}, 59 | {0x53, "co2"}, 60 | {0x54, "compressed_air"}, 61 | {0x55, "natural_gas"}, 62 | {0x56, "fog"}, 63 | {0x57, "smoke"}, 64 | {0x58, "cracked_haze"}, 65 | {0x60, "pyro"}, 66 | {0x61, "fireworks"}, 67 | {0x62, "explosions"}, 68 | {0x63, "flame"}, 69 | {0x64, "smoke_pots"}, 70 | {0x7f, "all_types"} 71 | }; 72 | 73 | const std::unordered_map MIDI_SHOW_CONTROL_COMMAND_TYPE = { 74 | {0x01, "go"}, 75 | {0x02, "stop"}, 76 | {0x03, "resume"}, 77 | {0x04, "timed_go"}, 78 | {0x05, "load"}, 79 | {0x06, "set"}, 80 | {0x07, "fire"}, 81 | {0x08, "all_off"}, 82 | {0x09, "restore"}, 83 | {0x0a, "reset"}, 84 | {0x0b, "go_off"}, 85 | {0x10, "go_jam_clock"}, 86 | {0x11, "standby+"}, 87 | {0x12, "standby-"}, 88 | {0x13, "sequence+"}, 89 | {0x14, "sequence-"}, 90 | {0x15, "start_clock"}, 91 | {0x16, "stop_clock"}, 92 | {0x17, "zero_clock"}, 93 | {0x18, "set_clock"}, 94 | {0x19, "mtc_chase_on"}, 95 | {0x1a, "mtc_chase_off"}, 96 | {0x1b, "open_cue_list"}, 97 | {0x1c, "close_cue_list"}, 98 | {0x1d, "open_cue_path"} 99 | }; 100 | 101 | const std::unordered_map MIDI_MACHINE_CONTROL_COMMAND_TYPE = { 102 | {0x01, "stop"}, 103 | {0x02, "play"}, 104 | {0x03, "deferred_play"}, 105 | {0x04, "fast_forward"}, 106 | {0x05, "rewind"}, 107 | {0x06, "record_strobe"}, 108 | {0x07, "record_exit"}, 109 | {0x08, "record_pause"}, 110 | {0x09, "pause"}, 111 | {0x0a, "eject"}, 112 | {0x0b, "chase"}, 113 | {0x0c, "command_error_reset"}, 114 | {0x0d, "mmc_reset"} 115 | }; 116 | 117 | -------------------------------------------------------------------------------- /src/MidiManager.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // MidiManager.cpp 3 | // OSC_MIDI_OSC 4 | // 5 | // Created by Fred Rodrigues on 02/10/2023. 6 | // 7 | 8 | #include "MidiManager.h" 9 | 10 | MidiManager::MidiManager() { 11 | 12 | } 13 | void MidiManager::setup(){ 14 | ofLogNotice("MidiManager") << "MidiManager setup"; 15 | // Get the instance of SettingsManager 16 | SettingsManager & settingsManager = SettingsManager::getInstance(); 17 | 18 | // Access the settings 19 | midiManagerSettings = settingsManager.getSettings(); 20 | 21 | midiManagerSettings["allOutPorts"] = midiOut.getOutPortList(); 22 | midiManagerSettings["allInPorts"] = midiIn.getInPortList(); 23 | 24 | if (midiManagerSettings["useVirtualPort"]) { 25 | midiOut.openVirtualPort("OSC_MIDI_OSC_OUT"); 26 | midiIn.openVirtualPort("OSC_MIDI_OSC_IN"); 27 | } else { 28 | if (midiManagerSettings["midiOutDevice"].is_string()) { 29 | 30 | //Check if the port from the settings exists 31 | if (midiOut.getOutPortList().size() > 0) { 32 | for (int i = 0; i < midiOut.getOutPortList().size(); i++) { 33 | if (midiOut.getOutPortList()[i] == midiManagerSettings["midiOutDevice"]) { 34 | midiOut.openPort(string(midiManagerSettings["midiOutDevice"])); 35 | break; 36 | } 37 | //else set the port to the first available port 38 | else { 39 | midiOut.openPort(0); 40 | } 41 | } 42 | } 43 | 44 | } else if (midiManagerSettings["midiOutDevice"].is_number()) { 45 | 46 | //check if the port from the settings exists (is the number lower than the number of ports) 47 | if (midiManagerSettings["midiOutDevice"] < midiOut.getNumOutPorts()) { 48 | midiOut.openPort(int(midiManagerSettings["midiOutDevice"])); 49 | } else { 50 | midiOut.openPort(0); 51 | } 52 | } 53 | 54 | if (midiManagerSettings["midiInDevice"].is_string()) { 55 | //Check if the port from the settings exists 56 | if (midiIn.getInPortList().size() > 0) { 57 | for (int i = 0; i < midiIn.getInPortList().size(); i++) { 58 | if (midiIn.getInPortList()[i] == midiManagerSettings["midiInDevice"]) { 59 | midiIn.openPort(string(midiManagerSettings["midiInDevice"])); 60 | break; 61 | } 62 | //else set the port to the first available port 63 | else { 64 | midiIn.openPort(0); 65 | } 66 | } 67 | } 68 | 69 | } else if (midiManagerSettings["midiInDevice"].is_number()) { 70 | //check if the port from the settings exists (is the number lower than the number of ports) 71 | if (midiManagerSettings["midiInDevice"] < midiIn.getNumInPorts()) { 72 | midiIn.openPort(int(midiManagerSettings["midiInDevice"])); 73 | } else { 74 | midiIn.openPort(0); 75 | } 76 | } 77 | } 78 | midiManagerSettings["outPortLabel"] = midiOut.getName(); 79 | midiManagerSettings["inPortLabel"] = midiIn.getName(); 80 | 81 | settingsManager.saveSettings("MIDI_OSC_SETTINGS.json", midiManagerSettings); 82 | 83 | 84 | ofLogVerbose("MidiManager") << "MidiManager constructor called, midi out port: " + midiOut.getName() + " midi in port: " + midiIn.getName() << endl; 85 | midiIn.ignoreTypes(false, false, false); 86 | midiIn.addListener(this); 87 | 88 | 89 | } 90 | void MidiManager::close(){ 91 | midiIn.closePort(); 92 | midiIn.removeListener(this); 93 | midiOut.closePort(); 94 | } 95 | void MidiManager::newMidiMessage(ofxMidiMessage& msg) { 96 | 97 | midiMessage = msg; 98 | 99 | SettingsManager& settingsManager = SettingsManager::getInstance(); 100 | 101 | OscManager& oscManager = OscManager::getInstance(); 102 | ofxOscSender& oscSend = oscManager.getOSCSender(); 103 | ofxOscMessage m; 104 | 105 | 106 | if (midiMessage.status == MIDI_SYSEX) { 107 | ofLogVerbose("MidiManager::newMidiMessage") << "Sysex Message" << endl; 108 | ofLogVerbose("MidiManager::newMidiMessage") << "Message Size " + ofToString(midiMessage.bytes.size()) << endl; 109 | 110 | int deviceId = static_cast(midiMessage.bytes[2]); 111 | 112 | //Handle midi machine control messages 113 | if (midiMessage.bytes[3] == 0x06) { 114 | ofLogVerbose("MidiManager::newMidiMessage") << "Midi Machine Control Message" << endl; 115 | 116 | m.setAddress("/MMCCommand"); 117 | m.addIntArg(deviceId); 118 | 119 | std::string command = getMidiMachineControlCommand(midiMessage.bytes[4]); 120 | m.addStringArg(command); 121 | 122 | message = "Received Midi Machine Control message: Command: " + command + " DeviceID: " + ofToString(deviceId); 123 | 124 | } 125 | 126 | //Handle midi show control messages 127 | if (midiMessage.bytes[3] == 0x02) { 128 | ofLogVerbose("MidiManager::newMidiMessage") << "Midi Show Control Message" << endl; 129 | 130 | m.setAddress("/MidiShowControl"); 131 | m.addIntArg(deviceId); 132 | 133 | 134 | m.addStringArg(getMidiShowControTargetType(midiMessage.bytes[4])); 135 | m.addStringArg(getMidiShowControlCommandType(midiMessage.bytes[5])); 136 | 137 | for (int i = 0; i < getMidiShowControlCommandData(midiMessage).size(); i++) { 138 | m.addIntArg(getMidiShowControlCommandData(midiMessage)[i]); 139 | } 140 | 141 | 142 | string dataByteString; 143 | 144 | for (int i = 0; i < getMidiShowControlCommandData(midiMessage).size(); i++) { 145 | dataByteString += ofToString(i) + ": "; 146 | } 147 | 148 | message = "Midi Show Control Message: Command: " + ofToString(getMidiShowControlCommandType(midiMessage.bytes[5])) + " Target: " +ofToString(getMidiShowControTargetType(midiMessage.bytes[4])) + " Device ID: " + ofToString(deviceId) + " Command Data: " + dataByteString; 149 | } 150 | 151 | 152 | } 153 | 154 | if (midiMessage.channel == midiManagerSettings["midiInChannel"] ) { 155 | if (midiMessage.status == MIDI_NOTE_ON) { 156 | m.setAddress("/noteOn"); 157 | m.addIntArg(midiMessage.pitch); 158 | m.addIntArg(midiMessage.velocity); 159 | message = "Received Note on Note ID: " + ofToString(midiMessage.pitch) + " With Velocity " + ofToString(midiMessage.velocity); 160 | 161 | } 162 | 163 | if (midiMessage.status == MIDI_NOTE_OFF) { 164 | m.setAddress("/noteOff"); 165 | m.addIntArg(midiMessage.pitch); 166 | 167 | message = "Received Note off Note ID: " + ofToString(midiMessage.pitch); 168 | } 169 | 170 | if (midiMessage.status == MIDI_CONTROL_CHANGE) { 171 | if (midiMessage.control == 0) { // Bank Select MSB 172 | m.setAddress("/bankSelectMSB"); 173 | m.addIntArg(midiMessage.value); 174 | message = "Received Bank Select MSB: " + ofToString(midiMessage.value); 175 | 176 | } else if (midiMessage.control == 32) { // Bank Select LSB 177 | m.setAddress("/bankSelectLSB"); 178 | m.addIntArg(midiMessage.value); 179 | message = "Received Bank Select LSB: " + ofToString(midiMessage.value); 180 | 181 | } else { 182 | m.setAddress("/cc"); 183 | m.addIntArg(midiMessage.control); 184 | m.addIntArg(midiMessage.value); 185 | message = "Received Controller ID: " + ofToString(midiMessage.control) + " Value: " + ofToString(midiMessage.value); 186 | } 187 | } 188 | 189 | if (midiMessage.status == MIDI_TIME_CODE) { 190 | m.setAddress("/MTC"); 191 | m.addIntArg(midiMessage.deltatime); 192 | message = "Received MTC: " + ofToString(midiMessage.value); 193 | } 194 | 195 | if (midiMessage.status == MIDI_PROGRAM_CHANGE) { 196 | m.setAddress("/ProgramChange"); 197 | m.addIntArg(midiMessage.value); 198 | message = "Received Program Change ID: " + ofToString(midiMessage.value); 199 | } 200 | 201 | if (midiMessage.status == MIDI_PITCH_BEND) { 202 | m.setAddress("/PitchBend"); 203 | m.addIntArg(midiMessage.value); 204 | message = "Received pitch bend Value: " + ofToString(midiMessage.value); 205 | } 206 | 207 | if (midiMessage.status == MIDI_AFTERTOUCH) { 208 | m.setAddress("/Aftertouch"); 209 | m.addIntArg(midiMessage.value); 210 | message = "Received Aftertouch Value: " + ofToString(midiMessage.value); 211 | } 212 | 213 | if (midiMessage.status == MIDI_POLY_AFTERTOUCH) { 214 | m.setAddress("/PolyAftertouch"); 215 | m.addIntArg(midiMessage.value); 216 | m.addIntArg(midiMessage.pitch); 217 | message = "Received Poly Aftertouch Pitch: " + ofToString(midiMessage.pitch) + " Value: " + ofToString(midiMessage.value); 218 | } 219 | } 220 | oscSend.sendMessage(m); 221 | ofLogVerbose("MidiManager::newMidiMessage'") << message << endl; 222 | ofSendMessage(message); 223 | } 224 | 225 | std::string MidiManager::getMidiShowControTargetType(uint8_t byte) { 226 | auto it = MIDI_SHOW_CONTROL_TARGET_TYPE.find(byte); 227 | 228 | if (it != MIDI_SHOW_CONTROL_TARGET_TYPE.end()) { 229 | return it->second; 230 | } else { 231 | return "unknown"; 232 | } 233 | } 234 | 235 | std::string MidiManager::getMidiShowControlCommandType(uint8_t byte) { 236 | auto it = MIDI_SHOW_CONTROL_COMMAND_TYPE.find(byte); 237 | 238 | if (it != MIDI_SHOW_CONTROL_COMMAND_TYPE.end()) { 239 | return it->second; 240 | } else { 241 | return "unknown"; 242 | } 243 | } 244 | 245 | std::vector MidiManager::getMidiShowControlCommandData(ofxMidiMessage midiMessage) { 246 | // Calculate the command data length (excluding the start byte, manufacturer ID, device ID, Sub-IDs, command format, and end byte) 247 | int commandDataLength = midiMessage.bytes.size() - 7; 248 | 249 | // Create a vector to store the command data 250 | std::vector commandData; 251 | // Create a string to accumulate digits 252 | std::string numberStr; 253 | 254 | // Loop through the command data 255 | for (int i = 6; i < 6 + commandDataLength; i++) { 256 | // Check if the byte is not 0x00 (separator) and not 0xF7 (end byte) 257 | if (midiMessage.bytes[i] != 0x00 && midiMessage.bytes[i] != 0xF7) { 258 | // Accumulate digits 259 | numberStr += static_cast(midiMessage.bytes[i]); 260 | } else if (!numberStr.empty()) { 261 | // Convert the accumulated string to an integer and add to the vector 262 | commandData.push_back(std::stoi(numberStr)); 263 | // Clear the accumulated string for the next number 264 | numberStr.clear(); 265 | } 266 | } 267 | 268 | if (!numberStr.empty()) { 269 | commandData.push_back(std::stoi(numberStr)); 270 | } 271 | 272 | return commandData; 273 | } 274 | 275 | 276 | std::string MidiManager::getMidiMachineControlCommand(uint8_t byte) { 277 | auto it = MIDI_MACHINE_CONTROL_COMMAND_TYPE.find(byte); 278 | 279 | if (it != MIDI_MACHINE_CONTROL_COMMAND_TYPE.end()) { 280 | return it->second; 281 | } else { 282 | return "unknown"; 283 | } 284 | } 285 | 286 | vector MidiManager::buildMMCMessaage(int deviceID, const std::string& command) { 287 | sysexMMCMsg.clear(); 288 | sysexMMCMsg.push_back(MIDI_SYSEX); 289 | sysexMMCMsg.push_back(0x7F); // Real Time Universal SysEx ID 290 | sysexMMCMsg.push_back(deviceID & 0x7F); // Device ID (limited to 7 bits) 291 | sysexMMCMsg.push_back(0x06); // MMC Command 292 | 293 | // Find the command byte from the map 294 | for (const auto& pair : MIDI_MACHINE_CONTROL_COMMAND_TYPE) { 295 | if (pair.second == command) { 296 | sysexMMCMsg.push_back(pair.first); 297 | break; 298 | } 299 | } 300 | 301 | sysexMMCMsg.push_back(MIDI_SYSEX_END); 302 | 303 | return sysexMMCMsg; 304 | } 305 | 306 | std::vector MidiManager::buildMidiShowControlMessage(int deviceID, const std::string& targetType, const std::string& commandType, const std::vector& commandData) { 307 | std::vector sysexMSCMsg; 308 | 309 | sysexMSCMsg.push_back(MIDI_SYSEX); 310 | sysexMSCMsg.push_back(0x7F); // Real Time Universal SysEx ID 311 | sysexMSCMsg.push_back(deviceID); // Device ID (limited to 7 bits) 312 | sysexMSCMsg.push_back(0x02); // Midi Show Control Command 313 | 314 | // Find the target type byte from the map 315 | for (const auto& pair : MIDI_SHOW_CONTROL_TARGET_TYPE) { 316 | if (pair.second == targetType) { 317 | sysexMSCMsg.push_back(pair.first); 318 | break; 319 | } 320 | } 321 | 322 | // Find the command type byte from the map 323 | for (const auto& pair : MIDI_SHOW_CONTROL_COMMAND_TYPE) { 324 | if (pair.second == commandType) { 325 | sysexMSCMsg.push_back(pair.first); 326 | break; 327 | } 328 | } 329 | 330 | 331 | // Add command data bytes with 0x00 separator 332 | for (int dataByte : commandData) { 333 | sysexMSCMsg.push_back('0' + dataByte); // Convert to ASCII representation 334 | sysexMSCMsg.push_back(0x00); // Separator 335 | } 336 | //remove the last separator 337 | sysexMSCMsg.pop_back(); 338 | 339 | sysexMSCMsg.push_back(MIDI_SYSEX_END); 340 | 341 | return sysexMSCMsg; 342 | } 343 | //destructors 344 | MidiManager::~MidiManager() { 345 | midiIn.closePort(); 346 | midiIn.removeListener(this); 347 | midiOut.closePort(); 348 | ofLogVerbose("MidiManager") << "Destructor called" << endl; 349 | } 350 | 351 | void MidiManager::updateSettings(){ 352 | SettingsManager & settingsManager = SettingsManager::getInstance(); 353 | midiManagerSettings = settingsManager.getSettings(); 354 | } 355 | -------------------------------------------------------------------------------- /src/MidiManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // MidiManager.h 3 | // OSC_MIDI_OSC 4 | // 5 | // Created by Fred Rodrigues on 02/10/2023. 6 | // 7 | 8 | 9 | #pragma once 10 | #include 11 | 12 | #include "ofMain.h" 13 | #include "ofxMidi.h" 14 | #include "SettingsManager.h" // Include the SettingsManager header 15 | #include "OscManager.h" 16 | #include "MidiConstants.h" 17 | 18 | class MidiManager: public ofxMidiListener { 19 | public: 20 | static MidiManager& getInstance() { 21 | static MidiManager instance; // Guaranteed to be destroyed, instantiated on first use. 22 | return instance; 23 | } 24 | 25 | // Delete copy constructor and assignment operator 26 | MidiManager(MidiManager const&) = delete; 27 | void operator=(MidiManager const&) = delete; 28 | void setup(); 29 | void close(); 30 | ofxMidiOut& getMidiOut() { return midiOut; } 31 | ofxMidiIn& getMidiIn() { return midiIn; } 32 | 33 | // Send MIDI message 34 | void newMidiMessage(ofxMidiMessage& msg); 35 | vector sysexMMCMsg; 36 | vector buildMMCMessaage(int deviceID, const std::string& command); 37 | std::vector buildMidiShowControlMessage(int deviceID, const std::string& targetType, const std::string& commandType, const std::vector& commandData); 38 | 39 | //public destructor 40 | ~MidiManager(); 41 | 42 | void updateSettings(); 43 | 44 | private: 45 | MidiManager(); 46 | ofxMidiOut midiOut; 47 | ofxMidiIn midiIn; 48 | ofxMidiMessage midiMessage; 49 | 50 | ofJson midiManagerSettings; 51 | 52 | string message; 53 | stringstream text; 54 | // Additional private members for MIDI management 55 | 56 | std::string getMidiMachineControlCommand(uint8_t byte); 57 | 58 | std::string getMidiShowControlCommandType(uint8_t byte); 59 | std::string getMidiShowControTargetType(uint8_t byte); 60 | uint8_t getDeviceIdByte(ofxMidiMessage midiMessage); 61 | int getMidiShowControldeviceId(uint8_t byte); 62 | std::vector getMidiShowControlCommandData(ofxMidiMessage midiMessage); 63 | 64 | 65 | 66 | }; 67 | 68 | -------------------------------------------------------------------------------- /src/OcsManager.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // OSCManager.cpp 3 | // OSC_MIDI_OSC 4 | // 5 | // Created by Fred Rodrigues on 02/10/2023. 6 | // 7 | 8 | #include "OscManager.h" 9 | 10 | OscManager::OscManager() { 11 | 12 | } 13 | 14 | void OscManager::setup() { 15 | ofLogVerbose() << "OSC Manager setup" << endl; 16 | SettingsManager & settingsManager = SettingsManager::getInstance(); 17 | // Access the settings 18 | oscManagerSettings = settingsManager.getSettings(); 19 | 20 | oscSender.setup(oscManagerSettings["outgoingIpOSC"], oscManagerSettings["outGoingPortOsc"]); 21 | ofLogVerbose() << "OSC Sender initialised and set to port: " << oscSender.getPort() << " With host: " << oscSender.getHost() << endl; 22 | oscReceiver.setup(oscManagerSettings["incomingPortOsc"]); 23 | ofLogVerbose() << "OSC Receiver initialised and set to port: " << oscReceiver.getPort() << endl; 24 | } 25 | void OscManager::closeReceiver(){ 26 | ///oscReceiver.stop(); 27 | } 28 | void OscManager::setupReceiver(){ 29 | SettingsManager & settingsManager = SettingsManager::getInstance(); 30 | oscManagerSettings = settingsManager.getSettings(); 31 | oscReceiver.setup(oscManagerSettings["incomingPortOsc"]); 32 | ofLogVerbose() << "OSC Receiver initialised and set to port: " << oscReceiver.getPort() << endl; 33 | oscReceiver.start(); 34 | 35 | } 36 | void OscManager::closeSender(){ 37 | //oscSender.clear(); 38 | 39 | } 40 | void OscManager::setupSender(){ 41 | SettingsManager & settingsManager = SettingsManager::getInstance(); 42 | oscManagerSettings = settingsManager.getSettings(); 43 | oscSender.setup(oscManagerSettings["outgoingIpOSC"], oscManagerSettings["outGoingPortOsc"]); 44 | ofLogVerbose() << "OSC Sender initialised and set to port: " << oscSender.getPort() << " With host: " << oscSender.getHost() << endl; 45 | 46 | } 47 | void OscManager::handleIncomingMessages() { 48 | MidiManager& midiManager = MidiManager::getInstance(); 49 | ofxMidiOut& midiOut = midiManager.getMidiOut(); 50 | 51 | while (oscReceiver.hasWaitingMessages()) { 52 | ofxOscMessage m; 53 | oscReceiver.getNextMessage(m); 54 | 55 | if (m.getAddress() == "/noteOn") { 56 | if (m.getNumArgs() > 1) { 57 | midiOut.sendNoteOn(oscManagerSettings["midiOutChannel"], m.getArgAsInt32(0), m.getArgAsInt32(1)); 58 | message = "Sending note on: Note ID " + ofToString(m.getArgAsInt32(0)) + " With Velocity " + ofToString(m.getArgAsInt32(1)); 59 | } 60 | 61 | if (m.getNumArgs() == 1) { 62 | midiOut.sendNoteOn(oscManagerSettings["midiOutChannel"], m.getArgAsInt32(0)); 63 | message = "Sending note on: Note ID " + ofToString(m.getArgAsInt32(0)) + " With Velocity " + ofToString(64); 64 | } 65 | } 66 | 67 | if (m.getAddress() == "/noteOff") { 68 | midiOut.sendNoteOff(oscManagerSettings["midiOutChannel"], m.getArgAsInt32(0)); 69 | message = "Sending note off Note ID " + ofToString(m.getArgAsInt32(0)); 70 | } 71 | 72 | if (m.getAddress() == "/cc") { 73 | midiOut.sendControlChange(oscManagerSettings["midiOutChannel"], m.getArgAsInt32(0), m.getArgAsInt32(1)); 74 | message = "Sending cc Controller ID " + ofToString(m.getArgAsInt32(0)) + " Controller value " + ofToString(m.getArgAsInt32(1)); 75 | } 76 | 77 | if (m.getAddress() == "/ProgramChange") { 78 | midiOut.sendProgramChange(oscManagerSettings["midiOutChannel"], m.getArgAsInt32(0)); 79 | message = "Sending program change ID: " + ofToString(m.getArgAsInt32(0)); 80 | } 81 | 82 | if (m.getAddress() == "/PitchBend") { 83 | midiOut.sendPitchBend(oscManagerSettings["midiOutChannel"], m.getArgAsInt32(0)); 84 | message = "Sending pitch bend value: " + ofToString(m.getArgAsInt32(0)); 85 | } 86 | 87 | if (m.getAddress() == "/Aftertouch") { 88 | midiOut.sendAftertouch(oscManagerSettings["midiOutChannel"], m.getArgAsInt32(0)); 89 | message = "Sending aftertouch Value: " + ofToString(m.getArgAsInt32(0)); 90 | } 91 | 92 | if (m.getAddress() == "/PolyAftertouch") { 93 | midiOut.sendPolyAftertouch(oscManagerSettings["midiOutChannel"], m.getArgAsInt32(0), m.getArgAsInt32(1)); 94 | message = "Sending poly aftertouch Note: " + ofToString(m.getArgAsInt32(0)) + " value " + ofToString(m.getArgAsInt32(1)); 95 | } 96 | 97 | if (m.getAddress() == "/MMCCommand") { 98 | int deviceId = m.getArgAsInt32(0); 99 | std::string command = m.getArgAsString(1); 100 | 101 | // Convert the command string back to its corresponding MMC byte 102 | uint8_t commandByte = 0x00; 103 | for (const auto& pair : MIDI_MACHINE_CONTROL_COMMAND_TYPE) { 104 | if (pair.second == command) { 105 | commandByte = pair.first; 106 | break; 107 | } 108 | } 109 | std::vector midiBytes = midiManager.buildMMCMessaage(deviceId, command); 110 | midiOut.sendMidiBytes(midiBytes); 111 | message = "Sending MMC Command: " + command + " DeviceID: " + ofToString(deviceId); 112 | } 113 | if(m.getAddress() == "/MidiShowControl"){ 114 | 115 | //iterate through the arguments 116 | //first int argument is device id 117 | //first string argument is command 118 | //second string argument is command format 119 | //remaining int arguments are command data 120 | std::vector integerPositions; 121 | std::vector stringPositions; 122 | for (int i = 0; i commandData; 135 | for (int i = 2; i < integerPositions.size(); i++) { 136 | commandData.push_back(m.getArgAsInt32(integerPositions[i])); 137 | } 138 | 139 | 140 | std::vector midiBytes = midiManager.buildMidiShowControlMessage(deviceId, command, commandFormat, commandData); 141 | midiOut.sendMidiBytes(midiBytes); 142 | message = "Sending MSC Command: " + command + " DeviceID: " + ofToString(deviceId); 143 | 144 | } 145 | 146 | 147 | ofSendMessage(message); 148 | } 149 | } 150 | 151 | //destructor 152 | OscManager::~OscManager() { 153 | oscSender.clear(); 154 | 155 | 156 | 157 | ofLogVerbose() << "OSC Manager destructor called" << endl; 158 | } 159 | void OscManager::updateSettings(){ 160 | SettingsManager & settingsManager = SettingsManager::getInstance(); 161 | oscManagerSettings = settingsManager.getSettings(); 162 | } 163 | -------------------------------------------------------------------------------- /src/OscManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // OSCManager.h 3 | // OSC_MIDI_OSC 4 | // 5 | // Created by Fred Rodrigues on 02/10/2023. 6 | // 7 | 8 | #pragma once 9 | #include "ofMain.h" 10 | #include "ofxOsc.h" 11 | #include "MidiManager.h" 12 | #include "SettingsManager.h" // Include the SettingsManager header 13 | 14 | class OscManager { 15 | public: 16 | static OscManager& getInstance() { 17 | static OscManager instance; // Guaranteed to be destroyed, instantiated on first use. 18 | return instance; 19 | } 20 | 21 | // Delete copy and move constructors and assignment operators 22 | OscManager(OscManager const&) = delete; 23 | OscManager(OscManager&&) = delete; 24 | void operator=(OscManager const&) = delete; 25 | void operator=(OscManager&&) = delete; 26 | 27 | void setup(); 28 | void closeReceiver(); 29 | void setupReceiver(); 30 | void closeSender(); 31 | void setupSender(); 32 | 33 | ofxOscSender& getOSCSender() { return oscSender; } 34 | ofxOscReceiver& getOscReciever() { return oscReceiver; } 35 | 36 | void handleIncomingMessages(); 37 | 38 | //public destructor 39 | ~OscManager(); 40 | void updateSettings(); 41 | 42 | private: 43 | OscManager(); // Constructor is private now 44 | 45 | ofJson oscManagerSettings; 46 | string message; 47 | ofxOscSender oscSender; 48 | ofxOscReceiver oscReceiver; 49 | }; 50 | -------------------------------------------------------------------------------- /src/SettingsManager.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // SettingsManager.cpp 3 | // OSC_MIDI_OSC 4 | // 5 | // Created by Fred Rodrigues on 02/10/2023. 6 | // 7 | 8 | #include "SettingsManager.h" 9 | 10 | SettingsManager::SettingsManager() { 11 | // Constructor code 12 | setDefaultSettings(); 13 | } 14 | 15 | 16 | void SettingsManager::loadSettings(const std::string& filename) { 17 | if (ofFile::doesFileExist(filename)) { 18 | settings = ofLoadJson(filename); 19 | 20 | if (!settings["Log_level"].is_null()) { 21 | ofLogVerbose("loadSettings") << "Log level set to " << settings["Log_level"] << endl; 22 | ofSetLogLevel(settings["Log_level"]); 23 | } else { 24 | settings["Log_level"] = OF_LOG_VERBOSE; 25 | ofLogVerbose("loadSettings fallback") << "Log level set to " << settings["Log_level"] << endl; 26 | } 27 | 28 | #ifdef TARGET_OSX 29 | 30 | if (!settings["useVirtualPort"].is_null()) { 31 | ofLogVerbose("loadSettings") << "useVirtualPort set to " << settings["useVirtualPort"] << endl; 32 | } else { 33 | settings["useVirtualPort"] = true; 34 | ofLogVerbose("loadSettings fallback") << "useVirtualPort set to " << settings["useVirtualPort"] << endl; 35 | } 36 | 37 | #else 38 | settings["useVirtualPort"] = false; 39 | ofLogVerbose("loadSettings") << "useVirtualPort, unavailable on windows, now set to " << settings["useVirtualPort"] << endl; 40 | #endif 41 | 42 | if (!settings["midiInDevice"].is_null()) { 43 | if (settings["midiInDevice"].is_number()) { 44 | settings["midiInDeviceByString"] = false; 45 | ofLogVerbose("loadSettings") << "midiInDevice set to number: " << settings["midiInDeviceNum"] << endl; 46 | } else if (settings["midiInDevice"].is_string()) { 47 | settings["midiInDeviceByString"] = true; 48 | ofLogVerbose("loadSettings") << "midiInDevice set to string: " << settings["midiInDeviceName"] << endl; 49 | } 50 | } else { 51 | settings["midiInDeviceByString"] = false; 52 | settings["midiInDevice"] = 0; 53 | ofLogVerbose("loadSettings") << "midiInDevice set to number" << settings["midiInDevice"] << endl; 54 | } 55 | 56 | if (!settings["midiOutDevice"].is_null()) { 57 | if (settings["midiOutDevice"].is_number()) { 58 | settings["midiOutDeviceByString"] = false; 59 | ofLogVerbose("loadSettings") << "midiOutDevice set to number: " << settings["midiOutDeviceNum"] << endl; 60 | } else if (settings["midiOutDevice"].is_string()) { 61 | settings["midiOutDeviceByString"] = true; 62 | ofLogVerbose("loadSettings") << "midiOutDevice set to string: " << settings["midiOutDeviceName"] << endl; 63 | } 64 | } else { 65 | settings["midiOutDeviceByString"] = false; 66 | settings["midiOutDevice"] = 0; 67 | ofLogVerbose("loadSettings") << "midiOutDevice set to " << settings["midiOutDevice"] << endl; 68 | } 69 | 70 | if (!settings["midiOutChannel"].is_null()) { 71 | ofLogVerbose("loadSettings") << "midiOutChannel set to " << settings["midiOutChannel"] << endl; 72 | } else { 73 | settings["midiOutChannel"] = 1; 74 | ofLogVerbose("loadSettings fallback") << "midiOutChannel set to " << settings["midiOutChannel"] << endl; 75 | } 76 | 77 | if (!settings["midiInChannel"].is_null()) { 78 | ofLogVerbose("loadSettings") << "midiInChannel set to " << settings["midiInChannel"] << endl; 79 | } else { 80 | settings["midiInChannel"] = 1; 81 | ofLogVerbose("loadSettings fallback") << "midiInChannel set to " << settings["midiInChannel"] << endl; 82 | } 83 | 84 | //set the incomingPortOsc from the settings 85 | if (!settings["incomingPortOsc"].is_null()) { 86 | ofLogVerbose("loadSettings") << "incomingPortOsc set to " << settings["incomingPortOsc"] << endl; 87 | } else { 88 | settings["incomingPortOsc"] = 12345; 89 | ofLogVerbose("loadSettings fallback") << "incomingPortOsc set to " << settings["incomingPortOsc"] << endl; 90 | } 91 | 92 | if (!settings["outGoingPortOsc"].is_null()) { 93 | ofLogVerbose("loadSettings") << "outGoingPortOsc set to " << settings["outGoingPortOsc"] << endl; 94 | } else { 95 | settings["outGoingPortOsc"] = 1234; 96 | ofLogVerbose("loadSettings fallback") << "outGoingPortOsc set to " << settings["outGoingPortOsc"] << endl; 97 | } 98 | 99 | if (!settings["outgoingIpOSC"].is_null()) { 100 | ofLogVerbose("loadSettings") << "outgoingIpOSC set to " << settings["outgoingIpOSC"] << endl; 101 | } else { 102 | settings["outgoingIpOSC"] = "127.0.0.1"; 103 | ofLogVerbose("loadSettings fallback") << "outgoingIpOSC set to " << settings["outgoingIpOSC"] << endl; 104 | } 105 | 106 | if (!settings["frameRate"].is_null()) { 107 | ofLogVerbose("loadSettings") << "frameRate set to " << settings["frameRate"] << endl; 108 | } else { 109 | settings["frameRate"] = 25; 110 | } 111 | } else { 112 | ofLogError("SettingsManager::LoadSettings") << "Settings file not found: " << filename; 113 | setDefaultSettings(); 114 | } 115 | } 116 | 117 | ofJson SettingsManager::getSettings() const { 118 | return settings; 119 | } 120 | 121 | void SettingsManager::setDefaultSettings() { 122 | ofLogVerbose("SettingsManager::setDefaultSettings") << "Loading defualt settings" << endl; 123 | 124 | settings["Log_level"] = OF_LOG_VERBOSE; 125 | ofLogVerbose("SettingsManager::setDefaultSettings") << "Log level set to " << settings["Log_level"] << endl; 126 | 127 | #ifdef TARGET_OSX 128 | settings["useVirtualPort"] = true; 129 | #else 130 | settings["useVirtualPort"] = false; 131 | #endif 132 | ofLogVerbose("SettingsManager::setDefaultSettings") << "useVirtualPort set to " << settings["useVirtualPort"] << endl; 133 | 134 | settings["incomingPortOsc"] = 12345; 135 | ofLogVerbose("SettingsManager::setDefaultSettings") << "incomingPortOsc set to " << settings["incomingPortOsc"] << endl; 136 | 137 | settings["outGoingPortOsc"] = 1234; 138 | ofLogVerbose("SettingsManager::setDefaultSettings") << "outGoingPortOsc set to " << settings["outGoingPortOsc"] << endl; 139 | 140 | settings["outgoingIpOSC"] = "127.0.0.1"; 141 | ofLogVerbose("SettingsManager::setDefaultSettings") << "outgoingIpOSC set to " << settings["outgoingIpOSC"] << endl; 142 | 143 | settings["midiInDevice"] = 0; 144 | ofLogVerbose("SettingsManager::setDefaultSettings") << "midiInDevice set to " << settings["midiInDevice"] << endl; 145 | 146 | settings["midiOutDevice"] = 0; 147 | ofLogVerbose("SettingsManager::setDefaultSettings") << "midiOutDevice set to " << settings["midiOutDevice"] << endl; 148 | 149 | settings["midiOutChannel"] = 1; 150 | ofLogVerbose("SettingsManager::setDefaultSettings") << "midiOutChannel set to " << settings["midiOutChannel"] << endl; 151 | 152 | 153 | settings["midiInChannel"] = 1; 154 | ofLogVerbose("SettingsManager::setDefaultSettings") << "midiInChannel set to " << settings["midiInChannel"] << endl; 155 | 156 | settings["frameRate"] = 25; 157 | ofLogVerbose("SettingsManager::setDefaultSettings") << "frameRate set to " << settings["frameRate"] << endl; 158 | } 159 | 160 | void SettingsManager::saveSettings(const std::string& filename, ofJson remoteSettings){ 161 | settings = remoteSettings; 162 | 163 | ofLogVerbose("SettingsManager::saveSettings") << "Saving settings to " << filename << endl; 164 | ofSavePrettyJson(filename, settings); 165 | } 166 | 167 | void SettingsManager::updateSettings(ofJson remoteSettings){ 168 | settings = remoteSettings; 169 | ofLogVerbose("SettingsManager::updateSettings") << "Settings updated" << endl; 170 | } 171 | //public destructor 172 | SettingsManager::~SettingsManager() { 173 | // Destructor code 174 | } 175 | -------------------------------------------------------------------------------- /src/SettingsManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // SettingsManager.h 3 | // OSC_MIDI_OSC 4 | // 5 | // Created by Fred Rodrigues on 02/10/2023. 6 | // 7 | 8 | #pragma once 9 | #include 10 | #include "ofMain.h" 11 | 12 | class SettingsManager { 13 | public: 14 | static SettingsManager& getInstance() { 15 | static SettingsManager instance; // Guaranteed to be destroyed, instantiated on first use. 16 | return instance; 17 | } 18 | 19 | ~SettingsManager(); // Private destructor 20 | 21 | void loadSettings(const std::string& filename); 22 | ofJson getSettings() const; 23 | 24 | // Delete copy constructor and assignment operator 25 | SettingsManager(SettingsManager const&) = delete; 26 | void operator=(SettingsManager const&) = delete; 27 | 28 | void saveSettings(const std::string& filename, ofJson remoteSettings); 29 | void updateSettings(ofJson remoteSettings); 30 | 31 | private: 32 | SettingsManager(); // Private constructor 33 | 34 | ofJson settings; 35 | 36 | void setDefaultSettings(); 37 | }; 38 | 39 | -------------------------------------------------------------------------------- /src/colours.h: -------------------------------------------------------------------------------- 1 | // 2 | // colours.h 3 | // OSC_MIDI_OSC 4 | // 5 | // Created by Fred Rodrigues on 03/10/2023. 6 | // 7 | 8 | #pragma once 9 | 10 | #include "ofMain.h" 11 | 12 | class Colours { 13 | public: 14 | 15 | ofColor background = ofColor::fromHex(0xEBEDFF); 16 | ofColor text = ofColor::fromHex(0x1B2CC1); 17 | ofColor button = ofColor::fromHex(0x1B2CC1); 18 | ofColor buttonActive = ofColor::fromHex(0xFF499E); 19 | ofColor buttonHover = ofColor::fromHex(0xFF499E); 20 | ofColor buttonOutline = ofColor::fromHex(0x1B2CC1); 21 | ofColor buttonOutlineHover = ofColor::fromHex(0xFF499E); 22 | ofColor buttonOutlineActive = ofColor::fromHex(0xFF499E); 23 | 24 | }; 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "ofMain.h" 3 | #include "ofApp.h" 4 | 5 | 6 | #ifdef TARGET_WIN32 7 | 8 | #define IDI_ICON1 101 9 | 10 | #endif 11 | 12 | //======================================================================== 13 | int main( ){ 14 | 15 | //Use ofGLFWWindowSettings for more options like multi-monitor fullscreen 16 | ofGLWindowSettings settings; 17 | settings.setSize(750, 210); 18 | settings.windowMode = OF_WINDOW; //can also be OF_FULLSCREEN 19 | 20 | auto window = ofCreateWindow(settings); 21 | 22 | #ifdef TARGET_WIN32 23 | HWND hwnd = ofGetWin32Window(); 24 | // Load and set the application icon 25 | HICON hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1)); 26 | SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon); // Set the large icon 27 | SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hIcon); // Set the small icon 28 | #endif 29 | ofRunApp(window, std::make_shared()); 30 | ofRunMainLoop(); 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/modes/ConversionMode.cpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // ConversionMode.cpp 4 | // OSC_MIDI_OSC 5 | // 6 | // Created by Fred Rodrigues on 02/10/2023. 7 | // 8 | 9 | #include "ConversionMode.h" 10 | 11 | ConversionMode::ConversionMode(ofTrueTypeFont & fontRef, ofJson & settingsRef, Colours & coloursRef) 12 | : Mode(fontRef, settingsRef, coloursRef) { 13 | goToMidiOutSetMode.setup("Midi out setup", "BTN_MSG_GOTOMODE_MODE_SETTING_MIDI_OUT"); 14 | goToMidiOutSetMode.set(30, 175, 140, 20); 15 | goToMidiOutSetMode.disableAllEvents(); 16 | 17 | goToMidiInSetMode.setup("Midi in setup", "BTN_MSG_GOTOMODE_MODE_SETTING_MIDI_IN"); 18 | goToMidiInSetMode.set(200, 175, 140, 20); 19 | goToMidiInSetMode.disableAllEvents(); 20 | 21 | gotToOSCOutSetMode.setup("OSC out setup", "BTN_MSG_GOTOMODE_MODE_SETTING_OSC_OUT"); 22 | gotToOSCOutSetMode.set(370, 175, 140, 20); 23 | gotToOSCOutSetMode.disableAllEvents(); 24 | 25 | goToOSCInSetMode.setup("OSC in setup", "BTN_MSG_GOTOMODE_MODE_SETTING_OSC_IN"); 26 | goToOSCInSetMode.set(540, 175, 140, 20); 27 | goToOSCInSetMode.disableAllEvents(); 28 | ofLogVerbose("ConversionMode::ConversionMode"); 29 | } 30 | 31 | ConversionMode::~ConversionMode() { } 32 | 33 | void ConversionMode::setup() { 34 | ofLogVerbose("ConversionMode::setup"); 35 | 36 | goToMidiOutSetMode.enableAllEvents(); 37 | goToMidiInSetMode.enableAllEvents(); 38 | gotToOSCOutSetMode.enableAllEvents(); 39 | goToOSCInSetMode.enableAllEvents(); 40 | 41 | ofAddListener(ofEvents().keyPressed, this, &ConversionMode::_keyPressed); 42 | ofRegisterGetMessages(this); 43 | } 44 | 45 | void ConversionMode::draw() { 46 | 47 | ofSetColor(colours.text); 48 | font.drawString("Conversion active", 10, 15); 49 | font.drawString(activityMessage, 10, 35); 50 | font.drawString("Midi input on port " + settings["inPortLabel"].get() + " Channel: " + ofToString(settings["midiInChannel"]), 10, 55); 51 | font.drawString("Midi output on port " + settings["outPortLabel"].get() + " Channel: " + ofToString(settings["midiOutChannel"]), 10, 75); 52 | font.drawString("Osc input on port " + ofToString(settings["incomingPortOsc"]), 10, 95); 53 | font.drawString("Osc output on port " + ofToString(settings["outGoingPortOsc"]), 10, 115); 54 | font.drawString("Osc output to host " + settings["outgoingIpOSC"].get(), 10, 135); 55 | } 56 | 57 | void ConversionMode::update() { 58 | // oscManager.handleIncomingMessages(); 59 | 60 | } 61 | 62 | void ConversionMode::exit() { 63 | goToMidiOutSetMode.disableAllEvents(); 64 | goToMidiInSetMode.disableAllEvents(); 65 | gotToOSCOutSetMode.disableAllEvents(); 66 | goToOSCInSetMode.disableAllEvents(); 67 | ofRemoveListener(ofEvents().keyPressed, this, &ConversionMode::_keyPressed); 68 | ofUnregisterGetMessages(this); 69 | } 70 | 71 | 72 | void ConversionMode::_keyPressed(ofKeyEventArgs & e) { 73 | int key = e.key; 74 | keyPressed(key); 75 | } 76 | 77 | void ConversionMode::gotMessage(ofMessage & msg) { 78 | ofLogVerbose("ConversionMode::ofGetMessage"); 79 | 80 | if (msg.message.substr(0, 3) != "BTN") { 81 | activityMessage = msg.message; 82 | } 83 | } 84 | 85 | -------------------------------------------------------------------------------- /src/modes/ConversionMode.h: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // ConversionMode.h 4 | // OSC_MIDI_OSC 5 | // 6 | // Created by Fred Rodrigues on 02/10/2023. 7 | // 8 | #pragma once 9 | 10 | #include "modes/Mode.h" 11 | #include 12 | 13 | class ConversionMode : public Mode { 14 | private: 15 | std::string title; 16 | std::string activityMessage = "Waiting for input......"; 17 | 18 | public: 19 | ConversionMode(ofTrueTypeFont & fontRef, ofJson & settingsRef, Colours & coloursRef); 20 | ~ConversionMode(); 21 | 22 | void setup() override; 23 | void draw() override; 24 | void update() override; 25 | void exit() override; 26 | void keyPressed(int key) override{ } 27 | void gotMessage(ofMessage & msg); 28 | 29 | void _keyPressed(ofKeyEventArgs & e); 30 | 31 | simpleButton goToMidiOutSetMode; 32 | simpleButton goToMidiInSetMode; 33 | simpleButton gotToOSCOutSetMode; 34 | simpleButton goToOSCInSetMode; 35 | 36 | }; 37 | -------------------------------------------------------------------------------- /src/modes/MidiInSetupMode.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // MidiInSetupMode.cpp 3 | // OSC_MIDI_OSC 4 | // 5 | // Created by Fred Rodrigues on 02/10/2023. 6 | // 7 | 8 | #include "MidiInSetupMode.h" 9 | 10 | 11 | MidiInSetupMode::MidiInSetupMode(ofTrueTypeFont & fontRef, ofJson & settingsRef, Colours & coloursRef) 12 | : Mode(fontRef, settingsRef, coloursRef) { 13 | saveMidiInPortSettings.setup("Set midi in port", "BTN_MSG_MIDI_IN_PORT_SET"); 14 | saveMidiInPortSettings.set(30, 175, 140, 20); 15 | saveMidiInPortSettings.disableAllEvents(); 16 | 17 | saveMidiInChannelSettings.setup("Set midi in channel", "BTN_MSG_MIDI_IN_CHANNEL_SET"); 18 | saveMidiInChannelSettings.set(200, 175, 140, 20); 19 | saveMidiInChannelSettings.disableAllEvents(); 20 | 21 | GoToConversionMode.setup("Exit settings", "BTN_MSG_GOTOMODE_MODE_CONVERSION"); 22 | GoToConversionMode.set(370, 175, 135, 20); 23 | GoToConversionMode.disableAllEvents(); 24 | } 25 | 26 | MidiInSetupMode::~MidiInSetupMode() {} 27 | 28 | void MidiInSetupMode::setup() { 29 | 30 | saveMidiInPortSettings.enableAllEvents(); 31 | saveMidiInChannelSettings.enableAllEvents(); 32 | GoToConversionMode.enableAllEvents(); 33 | ofAddListener(ofEvents().keyPressed, this, &MidiInSetupMode::_keyPressed); 34 | } 35 | 36 | void MidiInSetupMode::draw() { 37 | ofSetColor(colours.text); 38 | 39 | font.drawString(title, 10, 15); 40 | font.drawString("Use the up & down keys to set the port and the < and > to set the channel", 10, 35); 41 | 42 | // Draw the list of ports and highlight the selected one 43 | for (int i = 0; i < settings["allInPorts"].size(); i++) { 44 | ofPushStyle(); 45 | 46 | if (settings["allInPorts"][i] == settings["inPortLabel"]) { 47 | ofSetColor(colours.buttonActive); 48 | } else { 49 | ofSetColor(colours.text); 50 | } 51 | 52 | font.drawString(settings["allInPorts"][i], 10, 55 + (i * 20)); 53 | ofPopStyle(); 54 | } 55 | 56 | // Draw the midi channel to the right of these messages 57 | ofSetColor(colours.text); 58 | font.drawString("Midi channel set to: ", 320, 55); 59 | ofSetColor(colours.buttonActive); 60 | int xPos = font.getStringBoundingBox("Midi channel set to: ", 320, 55).x + font.getStringBoundingBox("Midi channel set to: ", 320, 55).width; 61 | font.drawString( ofToString(settings["midiInChannel"]), xPos, 55); 62 | } 63 | 64 | void MidiInSetupMode::update() { 65 | // Implementation 66 | } 67 | 68 | void MidiInSetupMode::exit() { 69 | saveMidiInPortSettings.disableAllEvents(); 70 | saveMidiInChannelSettings.disableAllEvents(); 71 | GoToConversionMode.disableAllEvents(); 72 | ofRemoveListener(ofEvents().keyPressed, this, &MidiInSetupMode::_keyPressed); 73 | } 74 | 75 | void MidiInSetupMode::_keyPressed(ofKeyEventArgs & e) { 76 | int key = e.key; 77 | 78 | if (key == OF_KEY_DOWN) { 79 | selectPort(settings["allInPorts"], settings["inPortLabel"], 1); 80 | } 81 | 82 | if (key == OF_KEY_UP) { 83 | selectPort(settings["allInPorts"], settings["inPortLabel"], -1); 84 | } 85 | 86 | if (key == OF_KEY_LEFT) { 87 | selectChannel(settings["midiInChannel"], -1); 88 | } 89 | 90 | if (key == OF_KEY_RIGHT) { 91 | selectChannel(settings["midiInChannel"], 1); 92 | } 93 | } 94 | 95 | void MidiInSetupMode::selectPort(ofJson & ports, ofJson & currentPort, int direction) { 96 | for (int i = 0; i < ports.size(); i++) { 97 | if (ports[i] == currentPort) { 98 | int newIndex = ofClamp(i + direction, 0, ports.size() - 1); 99 | currentPort = ports[newIndex]; 100 | break; 101 | } 102 | } 103 | } 104 | 105 | void MidiInSetupMode::selectChannel(ofJson & channel, int direction) { 106 | int newChannel = ofClamp(channel.get() + direction, 1, 16); 107 | 108 | channel = newChannel; 109 | } 110 | void MidiInSetupMode::saveMidiInPort(){ 111 | settings["midiInDeviceName"] = settings["inPortLabel"]; 112 | settings["midiInDevice"] = settings["inPortLabel"]; 113 | settings["midiInDeviceByString"] = true; 114 | 115 | 116 | } 117 | 118 | void MidiInSetupMode::saveMidiInChannel(){ 119 | settings["midiInChannel"]; 120 | } 121 | -------------------------------------------------------------------------------- /src/modes/MidiInSetupMode.h: -------------------------------------------------------------------------------- 1 | // 2 | // MidiInSetupMode.h 3 | // OSC_MIDI_OSC 4 | // 5 | // Created by Fred Rodrigues on 02/10/2023. 6 | // 7 | 8 | 9 | #pragma once 10 | 11 | #include 12 | #include "modes/Mode.h" 13 | 14 | class MidiInSetupMode : public Mode { 15 | private: 16 | std::string title = "MIDI in setup"; 17 | 18 | 19 | public: 20 | MidiInSetupMode(ofTrueTypeFont & fontRef, ofJson & settingsRef, Colours & coloursRef); 21 | ~MidiInSetupMode(); 22 | 23 | void setup() override; 24 | void draw() override; 25 | void update() override; 26 | void exit() override; 27 | void keyPressed(int key)override { } 28 | 29 | void _keyPressed(ofKeyEventArgs & e); 30 | simpleButton saveMidiInPortSettings; 31 | simpleButton saveMidiInChannelSettings; 32 | simpleButton GoToConversionMode; 33 | void selectPort(ofJson & ports, ofJson & currentPort, int direction); 34 | void selectChannel(ofJson & channel, int direction); 35 | void saveMidiInPort(); 36 | void saveMidiInChannel(); 37 | 38 | }; 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/modes/MidiOutSetupMode.cpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // MidiOutSetupMode.cpp 4 | // OSC_MIDI_OSC 5 | // 6 | // Created by Fred Rodrigues on 02/10/2023. 7 | // 8 | 9 | #include "MidiOutSetupMode.h" 10 | 11 | MidiOutSetupMode::MidiOutSetupMode(ofTrueTypeFont & fontRef, ofJson & settingsRef, Colours & coloursRef) 12 | : Mode(fontRef, settingsRef, coloursRef) { 13 | saveMidiOutPortSettings.setup("Set midi out port", "BTN_MSG_MIDI_OUT_PORT_SET"); 14 | saveMidiOutPortSettings.set(30, 175, 140, 20); 15 | saveMidiOutPortSettings.disableAllEvents(); 16 | 17 | saveMidiOutChannelSettings.setup("Set midi out channel", "BTN_MSG_MIDI_OUT_CHANNEL_SET"); 18 | saveMidiOutChannelSettings.set(200, 175, 140, 20); 19 | saveMidiOutChannelSettings.disableAllEvents(); 20 | 21 | GoToConversionMode.setup("Exit settings", "BTN_MSG_GOTOMODE_MODE_CONVERSION"); 22 | GoToConversionMode.set(370, 175, 140, 20); 23 | GoToConversionMode.disableAllEvents(); 24 | } 25 | 26 | MidiOutSetupMode::~MidiOutSetupMode() { } 27 | 28 | void MidiOutSetupMode::setup() { 29 | 30 | saveMidiOutPortSettings.enableAllEvents(); 31 | saveMidiOutChannelSettings.enableAllEvents(); 32 | GoToConversionMode.enableAllEvents(); 33 | ofAddListener(ofEvents().keyPressed, this, &MidiOutSetupMode::_keyPressed); 34 | } 35 | 36 | void MidiOutSetupMode::draw() { 37 | ofSetColor(colours.text); 38 | 39 | font.drawString(title, 10, 15); 40 | font.drawString("Use the up & down keys to set the port and the < and > to set the channel", 10, 35); 41 | 42 | // Draw the list of ports and highlight the selected one 43 | for (int i = 0; i < settings["allOutPorts"].size(); i++) { 44 | ofPushStyle(); 45 | 46 | if (settings["allOutPorts"][i] == settings["outPortLabel"]) { 47 | ofSetColor(colours.buttonActive); 48 | } else { 49 | ofSetColor(colours.text); 50 | 51 | } 52 | 53 | font.drawString(settings["allOutPorts"][i], 10, 55 + (i * 15)); 54 | ofPopStyle(); 55 | } 56 | 57 | // Draw the midi channel to the right of these messages 58 | ofSetColor(colours.text); 59 | // we want to draw this string font.drawString("Midi channel set to: " + ofToString(settings["midiOutChannel"]), 320, 55) but the ofToString(settings["midiOutChannel"]) part should be a different colour 60 | font.drawString("Midi channel set to: ", 320, 55); 61 | ofSetColor(colours.buttonActive); 62 | int xPos = font.getStringBoundingBox("Midi channel set to: ", 320, 55).x + font.getStringBoundingBox("Midi channel set to: ", 320, 55).width; 63 | font.drawString( ofToString(settings["midiOutChannel"]), xPos, 55); 64 | 65 | 66 | 67 | 68 | 69 | 70 | //font.drawString("Midi channel set to: " + ofToString(settings["midiOutChannel"]), 320, 55); 71 | } 72 | 73 | void MidiOutSetupMode::update() { 74 | // Implementation 75 | } 76 | 77 | void MidiOutSetupMode::exit() { 78 | saveMidiOutPortSettings.disableAllEvents(); 79 | saveMidiOutChannelSettings.disableAllEvents(); 80 | GoToConversionMode.disableAllEvents(); 81 | ofRemoveListener(ofEvents().keyPressed, this, &MidiOutSetupMode::_keyPressed); 82 | } 83 | 84 | void MidiOutSetupMode::_keyPressed(ofKeyEventArgs & e) { 85 | int key = e.key; 86 | 87 | if (key == OF_KEY_DOWN) { 88 | selectPort(settings["allOutPorts"], settings["outPortLabel"], 1); 89 | } 90 | 91 | if (key == OF_KEY_UP) { 92 | selectPort(settings["allOutPorts"], settings["outPortLabel"], -1); 93 | } 94 | 95 | if (key == OF_KEY_LEFT) { 96 | selectChannel(settings["midiOutChannel"], -1); 97 | } 98 | 99 | if (key == OF_KEY_RIGHT) { 100 | selectChannel(settings["midiOutChannel"], 1); 101 | } 102 | } 103 | 104 | void MidiOutSetupMode::selectPort(ofJson & ports, ofJson & currentPort, int direction) { 105 | for (int i = 0; i < ports.size(); i++) { 106 | if (ports[i] == currentPort) { 107 | int newIndex = ofClamp(i + direction, 0, ports.size() - 1); 108 | currentPort = ports[newIndex]; 109 | break; 110 | } 111 | } 112 | } 113 | 114 | // Helper function to handle channel selection 115 | void MidiOutSetupMode::selectChannel(ofJson & channel, int direction) { 116 | int newChannel = ofClamp(channel.get() + direction, 1, 16); 117 | 118 | channel = newChannel; 119 | } 120 | -------------------------------------------------------------------------------- /src/modes/MidiOutSetupMode.h: -------------------------------------------------------------------------------- 1 | // 2 | // MidiOutSetupMode.h 3 | // OSC_MIDI_OSC 4 | // 5 | // Created by Fred Rodrigues on 02/10/2023. 6 | // 7 | 8 | #include "modes/Mode.h" 9 | #include 10 | 11 | class MidiOutSetupMode : public Mode { 12 | private: 13 | std::string title = "MIDI out setup";; 14 | 15 | public: 16 | MidiOutSetupMode(ofTrueTypeFont & fontRef, ofJson & settingsRef, Colours & coloursRef); 17 | ~MidiOutSetupMode(); 18 | 19 | void setup() override; 20 | void draw() override; 21 | void update() override; 22 | void exit() override; 23 | void keyPressed(int key) override{ } 24 | 25 | void _keyPressed(ofKeyEventArgs & e); 26 | simpleButton saveMidiOutPortSettings; 27 | simpleButton saveMidiOutChannelSettings; 28 | simpleButton GoToConversionMode; 29 | 30 | void selectPort(ofJson & ports, ofJson & currentPort, int direction); 31 | void selectChannel(ofJson & channel, int direction); 32 | }; 33 | -------------------------------------------------------------------------------- /src/modes/Mode.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Mode.cpp 3 | // OSC_MIDI_OSC 4 | // 5 | // Created by Fred Rodrigues on 02/10/2023. 6 | // 7 | 8 | #include "Mode.h" 9 | 10 | Mode::Mode(ofTrueTypeFont & fontRef, ofJson & settingsRef, Colours & coloursRef) 11 | : font(fontRef) 12 | , settings(settingsRef) 13 | , colours(coloursRef) { 14 | } 15 | 16 | Mode::~Mode() { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/modes/Mode.h: -------------------------------------------------------------------------------- 1 | // 2 | // Mode.h 3 | // OSC_MIDI_OSC 4 | // 5 | // Created by Fred Rodrigues on 02/10/2023. 6 | // 7 | 8 | #pragma once 9 | 10 | #include "ofMain.h" 11 | #include "stdio.h" 12 | #include "simpleButton.h" 13 | #include "colours.h" 14 | 15 | class Mode { 16 | protected: 17 | ofTrueTypeFont & font; 18 | ofJson & settings; 19 | std::string title; 20 | Colours & colours; 21 | 22 | 23 | public: 24 | Mode(ofTrueTypeFont & fontRef, ofJson & settingsRef, Colours & coloursRef); 25 | virtual ~Mode(); 26 | 27 | virtual void setup() = 0; 28 | virtual void draw() = 0; 29 | virtual void update() = 0; 30 | virtual void exit() = 0; 31 | virtual void keyPressed(int key) = 0; 32 | 33 | }; 34 | -------------------------------------------------------------------------------- /src/modes/ModeManager.cpp: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // ModeManager.cpp 4 | // OSC_MIDI_OSC 5 | // 6 | // Created by Fred Rodrigues on 02/10/2023. 7 | // 8 | 9 | #include "ModeManager.h" 10 | 11 | ModeManager::ModeManager() { 12 | // Constructor implementation (if needed) 13 | } 14 | 15 | ModeManager::~ModeManager() { 16 | // Destructor implementation (if needed) 17 | } 18 | 19 | void ModeManager::setMode(std::shared_ptr newMode) { 20 | if (currentMode) { 21 | currentMode->exit(); 22 | } 23 | 24 | currentMode = newMode; 25 | currentMode->setup(); 26 | } 27 | 28 | void ModeManager::update() { 29 | if (currentMode) { 30 | currentMode->update(); 31 | } 32 | } 33 | 34 | void ModeManager::draw() { 35 | if (currentMode) { 36 | currentMode->draw(); 37 | } 38 | } 39 | 40 | void ModeManager::keyPressed(int key) { 41 | if (currentMode) { 42 | currentMode->keyPressed(key); 43 | } 44 | } 45 | 46 | void ModeManager::exit() { 47 | if (currentMode) { 48 | currentMode->exit(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/modes/ModeManager.h: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // ModeManager.h 4 | // OSC_MIDI_OSC 5 | // 6 | // Created by Fred Rodrigues on 02/10/2023. 7 | // 8 | 9 | #pragma once 10 | 11 | #include "modes/Mode.h" 12 | #include 13 | 14 | class ModeManager { 15 | public: 16 | ModeManager(); 17 | ~ModeManager(); 18 | 19 | void setMode(std::shared_ptr newMode); 20 | void update(); 21 | void draw(); 22 | void keyPressed(int key); 23 | void exit(); 24 | 25 | private: 26 | std::shared_ptr currentMode; 27 | }; 28 | -------------------------------------------------------------------------------- /src/modes/OscInSetupMode.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // MidiInSetupMode.cpp 3 | // OSC_MIDI_OSC 4 | // 5 | // Created by Fred Rodrigues on 02/10/2023. 6 | // 7 | 8 | #include "OscInSetupMode.h" 9 | 10 | OscInSetupMode::OscInSetupMode(ofTrueTypeFont & fontRef, ofJson & settingsRef, Colours & coloursRef) 11 | : Mode(fontRef, settingsRef, coloursRef) { 12 | oscInPortField.setup(); 13 | oscInPortField.text = ofToString(settings["incomingPortOsc"]); 14 | oscInPortField.bounds.x = 10; 15 | oscInPortField.bounds.y = 35; 16 | oscInPortField.bounds.height = font.getStringBoundingBox("1", 0, 0).height + 5; 17 | oscInPortField.bounds.width = font.getStringBoundingBox(ofToString(settings["incomingPortOsc"]), 0, 0).width + 30; 18 | oscInPortField.setFont(font); 19 | 20 | saveOSCInPortSettings.setup("Set OSC in port", "BTN_MSG_OSC_IN_PORT_SET"); 21 | saveOSCInPortSettings.set(30, 175, 140, 20); 22 | saveOSCInPortSettings.disableAllEvents(); 23 | 24 | GoToConversionMode.setup("Exit settings", "BTN_MSG_GOTOMODE_MODE_CONVERSION"); 25 | GoToConversionMode.set(200, 175, 140, 20); 26 | GoToConversionMode.disableAllEvents(); 27 | } 28 | 29 | OscInSetupMode::~OscInSetupMode() {} 30 | 31 | void OscInSetupMode::setup() { 32 | oscInPortField.enable(); 33 | saveOSCInPortSettings.enableAllEvents(); 34 | GoToConversionMode.enableAllEvents(); 35 | ofAddListener(oscInPortField.onTextChange, this, &OscInSetupMode::onOSCInputPortEditied); 36 | 37 | ofAddListener(ofEvents().keyPressed, this, &OscInSetupMode::_keyPressed); 38 | } 39 | 40 | void OscInSetupMode::draw() { 41 | ofSetColor(colours.text); 42 | font.drawString("OSC in settings", 10, 15); 43 | ofPushStyle(); 44 | ofSetColor(colours.buttonActive); 45 | ofFill(); 46 | ofDrawRectRounded(oscInPortField.bounds.x, oscInPortField.bounds.y + 8, oscInPortField.bounds.width, oscInPortField.bounds.height, 3); 47 | ofPopStyle(); 48 | oscInPortField.draw(); 49 | } 50 | 51 | void OscInSetupMode::update() { 52 | // Implementation 53 | } 54 | 55 | void OscInSetupMode::exit() { 56 | oscInPortField.disable(); 57 | saveOSCInPortSettings.disableAllEvents(); 58 | GoToConversionMode.disableAllEvents(); 59 | ofRemoveListener(oscInPortField.onTextChange, this, &OscInSetupMode::onOSCInputPortEditied); 60 | ofRemoveListener(ofEvents().keyPressed, this, &OscInSetupMode::_keyPressed); 61 | } 62 | 63 | 64 | void OscInSetupMode::_keyPressed(ofKeyEventArgs & e) { 65 | 66 | } 67 | 68 | void OscInSetupMode::onOSCInputPortEditied(string & message) { 69 | settings["incomingPortOsc"] = ofToInt(message); 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/modes/OscInSetupMode.h: -------------------------------------------------------------------------------- 1 | // 2 | // OscInSetupMode.h 3 | // OSC_MIDI_OSC 4 | // 5 | // Created by Fred Rodrigues on 02/10/2023. 6 | // 7 | 8 | #pragma once 9 | 10 | 11 | #include 12 | 13 | #include "modes/Mode.h" 14 | #include "ofxTextInputField.h" 15 | 16 | class OscInSetupMode : public Mode { 17 | private: 18 | std::string title; 19 | 20 | public: 21 | OscInSetupMode(ofTrueTypeFont & fontRef, ofJson & settingsRef, Colours & coloursRef); 22 | ~OscInSetupMode(); 23 | 24 | void setup() override; 25 | void draw() override; 26 | void update() override; 27 | void exit() override; 28 | void keyPressed(int key) override{ } 29 | 30 | void _keyPressed(ofKeyEventArgs & e); 31 | simpleButton saveMidiInPortSettings; 32 | simpleButton saveMidiInChannelSettings; 33 | 34 | ofxTextInputField oscInPortField; 35 | 36 | void onOSCInputPortEditied(string & message); 37 | 38 | simpleButton saveOSCInPortSettings; 39 | simpleButton GoToConversionMode; 40 | 41 | }; 42 | -------------------------------------------------------------------------------- /src/modes/OscOutSetupMode.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // OscOutSetupMode.cpp 3 | // OSC_MIDI_OSC 4 | // 5 | // Created by Fred Rodrigues on 02/10/2023. 6 | // 7 | 8 | #include "OscOutSetupMode.h" 9 | 10 | OscOutSetupMode::OscOutSetupMode(ofTrueTypeFont & fontRef, ofJson & settingsRef, Colours & coloursRef) 11 | : Mode(fontRef, settingsRef, coloursRef) { 12 | oscOutPortField.setup(); 13 | oscOutPortField.text = ofToString(settings["outGoingPortOsc"]); 14 | oscOutPortField.bounds.x = 10; 15 | oscOutPortField.bounds.y = 35; 16 | oscOutPortField.bounds.height = font.getStringBoundingBox("1", 0, 0).height + 5; 17 | oscOutPortField.bounds.width = font.getStringBoundingBox(ofToString(settings["outGoingPortOsc"]), 0, 0).width + 30; 18 | oscOutPortField.setFont(font); 19 | 20 | oscOutIPField.setup(); 21 | oscOutIPField.text = settings["outgoingIpOSC"]; 22 | oscOutIPField.bounds.x = 10; 23 | oscOutIPField.bounds.y = 60; 24 | oscOutIPField.bounds.height = font.getStringBoundingBox("1", 0, 0).height + 5; 25 | oscOutIPField.bounds.width = font.getStringBoundingBox(ofToString(settings["outgoingIpOSC"]), 0, 0).width + 30;; 26 | oscOutIPField.setFont(font); 27 | 28 | saveOSCOutPortSettings.setup("Set OSC out port", "BTN_MSG_OST_OUT_PORT_SET"); 29 | saveOSCOutPortSettings.set(30, 175, 140, 20); 30 | saveOSCOutPortSettings.disableAllEvents(); 31 | 32 | saveOSCOutIptSettings.setup("Set OSC IP port", "BTN_MSG_OST_OUT_IP_SET"); 33 | saveOSCOutIptSettings.set(200, 175, 140, 20); 34 | saveOSCOutIptSettings.disableAllEvents(); 35 | 36 | GoToConversionMode.setup("Exit settings", "BTN_MSG_GOTOMODE_MODE_CONVERSION"); 37 | GoToConversionMode.set(370, 175, 140, 20); 38 | GoToConversionMode.disableAllEvents(); 39 | } 40 | 41 | OscOutSetupMode::~OscOutSetupMode() { } 42 | 43 | void OscOutSetupMode::setup() { 44 | oscOutPortField.enable(); 45 | oscOutIPField.enable(); 46 | saveOSCOutPortSettings.enableAllEvents(); 47 | saveOSCOutIptSettings.enableAllEvents(); 48 | GoToConversionMode.enableAllEvents(); 49 | ofAddListener(oscOutPortField.onTextChange, this, &OscOutSetupMode::onOSCOutputPortEditied); 50 | ofAddListener(oscOutIPField.onTextChange, this, &OscOutSetupMode::onOSCOutputIPEditied); 51 | ofAddListener(ofEvents().keyPressed, this, &OscOutSetupMode::_keyPressed); 52 | } 53 | 54 | void OscOutSetupMode::draw() { 55 | ofSetColor(colours.text); 56 | font.drawString("OSC out settings", 10, 15); 57 | ofPushStyle(); 58 | ofFill(); 59 | ofSetColor(colours.buttonActive); 60 | ofDrawRectRounded(oscOutPortField.bounds.x, oscOutPortField.bounds.y + 8, oscOutPortField.bounds.width, oscOutPortField.bounds.height, 3); 61 | ofDrawRectRounded(oscOutIPField.bounds.x, oscOutIPField.bounds.y + 8, oscOutIPField.bounds.width, oscOutIPField.bounds.height, 3); 62 | ofPopStyle(); 63 | oscOutIPField.draw(); 64 | oscOutPortField.draw(); 65 | 66 | } 67 | 68 | void OscOutSetupMode::update() { 69 | // Implementation 70 | } 71 | 72 | void OscOutSetupMode::exit() { 73 | oscOutPortField.disable(); 74 | oscOutIPField.disable(); 75 | saveOSCOutPortSettings.disableAllEvents(); 76 | saveOSCOutIptSettings.disableAllEvents(); 77 | GoToConversionMode.disableAllEvents(); 78 | ofRemoveListener(oscOutPortField.onTextChange, this, &OscOutSetupMode::onOSCOutputPortEditied); 79 | ofRemoveListener(oscOutIPField.onTextChange, this, &OscOutSetupMode::onOSCOutputIPEditied); 80 | } 81 | 82 | 83 | void OscOutSetupMode::_keyPressed(ofKeyEventArgs & e) { 84 | int key = e.key; 85 | } 86 | 87 | void OscOutSetupMode::onOSCOutputIPEditied(string& message) { 88 | settings["outgoingIpOSC"] = message; 89 | } 90 | 91 | void OscOutSetupMode::onOSCOutputPortEditied(string& message) { 92 | settings["outGoingPortOsc"] = ofToInt(message); 93 | } 94 | -------------------------------------------------------------------------------- /src/modes/OscOutSetupMode.h: -------------------------------------------------------------------------------- 1 | // 2 | // OscOutSetupMode.h 3 | // OSC_MIDI_OSC 4 | // 5 | // Created by Fred Rodrigues on 02/10/2023. 6 | // 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | #include "modes/Mode.h" 13 | #include "ofxTextInputField.h" 14 | 15 | class OscOutSetupMode : public Mode { 16 | private: 17 | std::string title; 18 | 19 | public: 20 | OscOutSetupMode(ofTrueTypeFont & fontRef, ofJson & settingsRef, Colours & coloursRef); 21 | ~OscOutSetupMode(); 22 | 23 | void setup() override; 24 | void draw() override; 25 | void update() override; 26 | void exit() override; 27 | void keyPressed(int key) override { } 28 | 29 | void _keyPressed(ofKeyEventArgs & e); 30 | simpleButton saveMidiInPortSettings; 31 | simpleButton saveMidiInChannelSettings; 32 | 33 | ofxTextInputField oscOutPortField, oscOutIPField; 34 | 35 | void onOSCOutputIPEditied(string & message); 36 | void onOSCOutputPortEditied(string & message); 37 | 38 | simpleButton saveOSCOutPortSettings; 39 | simpleButton saveOSCOutIptSettings; 40 | simpleButton GoToConversionMode; 41 | }; 42 | -------------------------------------------------------------------------------- /src/ofApp.cpp: -------------------------------------------------------------------------------- 1 | #include "ofApp.h" 2 | 3 | //-------------------------------------------------------------- 4 | void ofApp::setup() { 5 | ofSetLogLevel(OF_LOG_VERBOSE); 6 | font.load("frabk.ttf", 14); 7 | settingsManager.loadSettings("MIDI_OSC_SETTINGS.json"); 8 | appSettings = settingsManager.getSettings(); 9 | midiManager.setup(); 10 | oscManager.setup(); 11 | ofBackground(255); 12 | 13 | activityMessage = "No messages received"; 14 | 15 | midiInSetupMode = std::make_shared(font, appSettings, colours); 16 | midiOutSetupMode = std::make_shared(font, appSettings, colours); 17 | oscInSetupMode = std::make_shared(font, appSettings, colours); 18 | oscOutSetupMode = std::make_shared(font, appSettings, colours); 19 | conversionMode = std::make_shared(font, appSettings, colours); 20 | 21 | modeManager.setMode(conversionMode); 22 | } 23 | 24 | //-------------------------------------------------------------- 25 | void ofApp::update() { 26 | modeManager.update(); 27 | oscManager.handleIncomingMessages(); 28 | } 29 | 30 | //-------------------------------------------------------------- 31 | void ofApp::draw() { 32 | ofSetBackgroundColor(colours.background); 33 | modeManager.draw(); 34 | } 35 | 36 | //-------------------------------------------------------------- 37 | void ofApp::keyPressed(int key) { 38 | 39 | } 40 | 41 | //-------------------------------------------------------------- 42 | void ofApp::keyReleased(int key) { 43 | } 44 | 45 | //-------------------------------------------------------------- 46 | void ofApp::mouseMoved(int x, int y) { 47 | } 48 | 49 | //-------------------------------------------------------------- 50 | void ofApp::mouseDragged(int x, int y, int button) { 51 | } 52 | 53 | //-------------------------------------------------------------- 54 | void ofApp::mousePressed(int x, int y, int button) { 55 | } 56 | 57 | //-------------------------------------------------------------- 58 | void ofApp::mouseReleased(int x, int y, int button) { 59 | } 60 | 61 | //-------------------------------------------------------------- 62 | void ofApp::windowResized(int w, int h) { 63 | } 64 | 65 | //-------------------------------------------------------------- 66 | void ofApp::gotMessage(ofMessage msg) { 67 | if (msg.message.substr(0, 3) == "BTN" && buttonMessagesMap.find(msg.message) != buttonMessagesMap.end()) { 68 | 69 | ofLogVerbose() << "Button message received: " << msg.message; 70 | 71 | // Get the corresponding enum value from the map 72 | int buttonValue = buttonMessagesMap[msg.message]; 73 | // Use a switch statement on the enum value 74 | switch (buttonValue) { 75 | case BTN_MSG_GOTOMODE_MODE_SETTING_MIDI_IN: 76 | modeManager.setMode(midiInSetupMode); 77 | break; 78 | 79 | case BTN_MSG_GOTOMODE_MODE_SETTING_MIDI_OUT: 80 | modeManager.setMode(midiOutSetupMode); 81 | break; 82 | 83 | case BTN_MSG_GOTOMODE_MODE_SETTING_OSC_IN: 84 | modeManager.setMode(oscInSetupMode); 85 | break; 86 | 87 | case BTN_MSG_GOTOMODE_MODE_SETTING_OSC_OUT: 88 | modeManager.setMode(oscOutSetupMode); 89 | break; 90 | 91 | case BTN_MSG_GOTOMODE_MODE_CONVERSION: 92 | modeManager.setMode(conversionMode); 93 | break; 94 | 95 | case BTN_MSG_MIDI_IN_PORT_SET: 96 | appSettings["midiInDevice"] = appSettings["inPortLabel"].get(); 97 | appSettings["midiInDeviceByString"] = true; 98 | settingsManager.saveSettings("MIDI_OSC_SETTINGS.json", appSettings); 99 | midiManager.close(); 100 | midiManager.updateSettings(); 101 | midiManager.setup(); 102 | break; 103 | 104 | case BTN_MSG_MIDI_IN_CHANNEL_SET: 105 | settingsManager.saveSettings("MIDI_OSC_SETTINGS.json", appSettings); 106 | midiManager.updateSettings(); 107 | break; 108 | 109 | case BTN_MSG_MIDI_OUT_PORT_SET: 110 | appSettings["midiOutDevice"] = appSettings["outPortLabel"].get(); 111 | appSettings["midiOutDeviceByString"] = true; 112 | settingsManager.saveSettings("MIDI_OSC_SETTINGS.json", appSettings); 113 | midiManager.close(); 114 | midiManager.updateSettings(); 115 | midiManager.setup(); 116 | 117 | break; 118 | 119 | case BTN_MSG_MIDI_OUT_CHANNEL_SET: 120 | settingsManager.saveSettings("MIDI_OSC_SETTINGS.json", appSettings); 121 | midiManager.updateSettings(); 122 | break; 123 | 124 | case BTN_MSG_OSC_IN_PORT_SET: 125 | oscManager.closeReceiver(); 126 | settingsManager.saveSettings("MIDI_OSC_SETTINGS.json", appSettings); 127 | oscManager.updateSettings(); 128 | oscManager.setupReceiver(); 129 | 130 | break; 131 | 132 | case BTN_MSG_OST_OUT_PORT_SET: 133 | oscManager.closeSender(); 134 | settingsManager.saveSettings("MIDI_OSC_SETTINGS.json", appSettings); 135 | oscManager.updateSettings(); 136 | oscManager.setupSender(); 137 | 138 | break; 139 | 140 | case BTN_MSG_OST_OUT_IP_SET: 141 | oscManager.closeSender(); 142 | settingsManager.saveSettings("MIDI_OSC_SETTINGS.json", appSettings); 143 | oscManager.setupSender(); 144 | break; 145 | 146 | 147 | } 148 | } else if (msg.message.substr(0, 3) != "BTN") { 149 | activityMessage = msg.message; 150 | } 151 | } 152 | 153 | //-------------------------------------------------------------- 154 | -------------------------------------------------------------------------------- /src/ofApp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ofMain.h" 4 | #include "SettingsManager.h" 5 | #include "MidiManager.h" 6 | #include "OscManager.h" 7 | #include "ofxTextInputField.h" 8 | #include "simpleButton.h" 9 | #include "Mode.h" 10 | #include "modes/ModeManager.h" 11 | #include "modes/MidiInSetupMode.h" 12 | #include "modes/MidiOutSetupMode.h" 13 | #include "modes/OscInSetupMode.h" 14 | #include "modes/OscOutSetupMode.h" 15 | #include "modes/ConversionMode.h" 16 | #include "colours.h" 17 | 18 | 19 | 20 | enum OperationMode { 21 | MODE_SETTING_MIDI_IN, 22 | MODE_SETTING_MIDI_OUT, 23 | MODE_SETTING_OSC_IN, 24 | MODE_SETTING_OSC_OUT, 25 | MODE_CONVERSION 26 | }; 27 | 28 | enum buttonMesssages { 29 | BTN_MSG_MIDI_IN_PORT_SET, 30 | BTN_MSG_MIDI_IN_CHANNEL_SET, 31 | BTN_MSG_MIDI_OUT_PORT_SET, 32 | BTN_MSG_MIDI_OUT_CHANNEL_SET, 33 | BTN_MSG_OSC_IN_PORT_SET, 34 | BTN_MSG_OST_OUT_PORT_SET, 35 | BTN_MSG_OST_OUT_IP_SET, 36 | BTN_MSG_GOTOMODE_MODE_SETTING_MIDI_IN, 37 | BTN_MSG_GOTOMODE_MODE_SETTING_MIDI_OUT, 38 | BTN_MSG_GOTOMODE_MODE_SETTING_OSC_IN, 39 | BTN_MSG_GOTOMODE_MODE_SETTING_OSC_OUT, 40 | BTN_MSG_GOTOMODE_MODE_CONVERSION 41 | }; 42 | 43 | 44 | const int MAX_MIDI_CHANNEL = 16; 45 | 46 | class ofApp : public ofBaseApp { 47 | 48 | public: 49 | void setup(); 50 | void update(); 51 | void draw(); 52 | 53 | void keyPressed(int key); 54 | void keyReleased(int key); 55 | void mouseMoved(int x, int y ); 56 | void mouseDragged(int x, int y, int button); 57 | void mousePressed(int x, int y, int button); 58 | void mouseReleased(int x, int y, int button); 59 | void windowResized(int w, int h); 60 | void gotMessage(ofMessage msg); 61 | 62 | SettingsManager& settingsManager = SettingsManager::getInstance(); 63 | MidiManager& midiManager = MidiManager::getInstance(); 64 | OscManager& oscManager = OscManager::getInstance(); 65 | ofJson appSettings; 66 | 67 | std::string activityMessage; 68 | 69 | 70 | std::vector midiInPortList; 71 | std::vector midiOutPortList; 72 | int selectedInPort, selectedOutPort; 73 | 74 | ofTrueTypeFont font; 75 | // Helper function to handle port selection 76 | 77 | ModeManager modeManager; // If you have a separate class for ModeManager 78 | 79 | std::shared_ptr midiInSetupMode; 80 | std::shared_ptr midiOutSetupMode; 81 | std::shared_ptr oscInSetupMode; 82 | std::shared_ptr oscOutSetupMode; 83 | std::shared_ptr conversionMode; 84 | 85 | 86 | 87 | 88 | std::unordered_map buttonMessagesMap = { 89 | {"BTN_MSG_MIDI_IN_PORT_SET", 0}, 90 | {"BTN_MSG_MIDI_IN_CHANNEL_SET", 1}, 91 | {"BTN_MSG_MIDI_OUT_PORT_SET", 2}, 92 | {"BTN_MSG_MIDI_OUT_CHANNEL_SET", 3}, 93 | {"BTN_MSG_OSC_IN_PORT_SET", 4}, 94 | {"BTN_MSG_OST_OUT_PORT_SET", 5}, 95 | {"BTN_MSG_OST_OUT_IP_SET", 6}, 96 | {"BTN_MSG_GOTOMODE_MODE_SETTING_MIDI_IN", 7}, 97 | {"BTN_MSG_GOTOMODE_MODE_SETTING_MIDI_OUT", 8}, 98 | {"BTN_MSG_GOTOMODE_MODE_SETTING_OSC_IN", 9}, 99 | {"BTN_MSG_GOTOMODE_MODE_SETTING_OSC_OUT", 10}, 100 | {"BTN_MSG_GOTOMODE_MODE_CONVERSION", 11} 101 | }; 102 | 103 | Colours colours; 104 | 105 | }; 106 | 107 | -------------------------------------------------------------------------------- /src/simpleButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // simpleButton.h 3 | // OSC_MIDI_OSC 4 | // 5 | // Created by Fred Rodrigues on 02/10/2023. 6 | // 7 | 8 | #pragma once 9 | #include "ofxMSAInteractiveObject.h" 10 | #include "colours.h" 11 | 12 | #define IDLE_COLOR 0x2860bd 13 | #define OVER_COLOR 0xbd5928 14 | #define DOWN_COLOR 0xbd5928 15 | 16 | class simpleButton : public ofxMSAInteractiveObject { 17 | public: 18 | string buttonLabel; 19 | string buttonMessage; 20 | ofTrueTypeFont drawFont; 21 | Colours colours; 22 | void setup(string label, string message) { 23 | enableMouseEvents(); 24 | enableKeyEvents(); 25 | 26 | buttonLabel = label; 27 | buttonMessage = message; 28 | drawFont.load("frabk.ttf", 12); 29 | } 30 | 31 | void exit() { 32 | } 33 | 34 | void update() { 35 | } 36 | 37 | void draw() { 38 | ofPushStyle(); 39 | 40 | if (isMousePressed()) { 41 | ofSetColor(colours.buttonActive); 42 | } else if (isMouseOver()) { 43 | ofSetColor(colours.buttonActive); 44 | } else { 45 | ofSetColor(colours.button); 46 | } 47 | 48 | ofNoFill(); 49 | ofDrawRectRounded(x, y, width, height, 12 / 2); 50 | drawFont.drawString(buttonLabel, x + ((width - drawFont.getStringBoundingBox(buttonLabel, 0, 0).getWidth()) / 2), y + ((height - drawFont.getStringBoundingBox(buttonLabel, 0, 0).getHeight()) / 2) + drawFont.getStringBoundingBox(buttonLabel, 0, 0).getHeight()); 51 | 52 | ofPopStyle(); 53 | } 54 | 55 | virtual void onRollOver(int x, int y) { 56 | } 57 | 58 | virtual void onRollOut() { 59 | } 60 | 61 | virtual void onMouseMove(int x, int y) { 62 | } 63 | 64 | virtual void onDragOver(int x, int y, int button) { 65 | } 66 | 67 | virtual void onDragOutside(int x, int y, int button) { 68 | } 69 | 70 | virtual void onPress(int x, int y, int button) { 71 | ofSendMessage(buttonMessage); 72 | } 73 | 74 | virtual void onRelease(int x, int y, int button) { 75 | } 76 | 77 | virtual void onReleaseOutside(int x, int y, int button) { 78 | } 79 | 80 | virtual void keyPressed(int key) { 81 | } 82 | 83 | virtual void keyReleased(int key) { 84 | } 85 | }; 86 | --------------------------------------------------------------------------------