Begin midi engine
This commit is contained in:
@@ -40,9 +40,12 @@ The platform and renderer layers are C-style APIs with opaque handles. `platform
|
||||
|
||||
This project is written in C-style C++. We use `.cpp` files and a small subset of C++ features (default struct values, function overloading, namespaces where useful) but avoid the rest. No classes, no inheritance, limit templates, no exceptions, no RAII, avoid STL containers or algorithms. Data is plain structs. Functions operate on those structs, or pointers to them.
|
||||
|
||||
Opening braces go on the same line as the function signature (K&R style), not on the next line.
|
||||
Memory should be managed with arena allocators where possible rather than individual `malloc`/`free` or `new`/`delete` calls. Arenas make allocation fast, avoid fragmentation, and simplify cleanup.
|
||||
|
||||
Memory is managed with arena allocators where possible rather than individual `malloc`/`free` or `new`/`delete` calls. Arenas make allocation fast, avoid fragmentation, and simplify cleanup.
|
||||
### Syntax Style
|
||||
|
||||
- Opening braces go on the same line as the function signature (K&R style), not on the next line.
|
||||
- use CAPS_SNAKE_CASE for constants, lower_snake_case for functions and variables, and CapsCamelCase for types.
|
||||
|
||||
## Dependencies
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// raddbg 0.9.24 project file
|
||||
|
||||
recent_file: path: "src/theme.cpp"
|
||||
recent_file: path: "src/main.cpp"
|
||||
recent_file: path: "src/theme.cpp"
|
||||
recent_file: path: "nob.obj"
|
||||
recent_file: path: "vendor/imgui/imgui.h"
|
||||
recent_file: path: "src/platform/platform.h"
|
||||
@@ -14,7 +14,7 @@ target:
|
||||
debug_info:
|
||||
{
|
||||
path: "C:/Users/mta/projects/autosample/build/autosample.pdb"
|
||||
timestamp: 66207523114644
|
||||
timestamp: 66207529127862
|
||||
}
|
||||
target:
|
||||
{
|
||||
@@ -22,8 +22,3 @@ target:
|
||||
working_directory: "build/"
|
||||
enabled: 1
|
||||
}
|
||||
breakpoint:
|
||||
{
|
||||
source_location: "src/theme.cpp:4:1"
|
||||
hit_count: 1
|
||||
}
|
||||
|
||||
1
nob.c
1
nob.c
@@ -31,6 +31,7 @@ static const char *link_libs[] = {
|
||||
"shell32.lib",
|
||||
"ole32.lib",
|
||||
"dwmapi.lib",
|
||||
"winmm.lib",
|
||||
};
|
||||
|
||||
static const char *obj_name(const char *src_path) {
|
||||
|
||||
39
src/main.cpp
39
src/main.cpp
@@ -3,6 +3,7 @@
|
||||
// [h]
|
||||
#include "platform/platform.h"
|
||||
#include "renderer/renderer.h"
|
||||
#include "midi/midi.h"
|
||||
#include "imgui.h"
|
||||
#include "imgui_internal.h"
|
||||
#include <iostream>
|
||||
@@ -10,6 +11,7 @@
|
||||
// [cpp]
|
||||
#include "platform/platform_win32.cpp"
|
||||
#include "renderer/renderer_dx12.cpp"
|
||||
#include "midi/midi_win32.cpp"
|
||||
#include "menus.cpp"
|
||||
#include "theme.cpp"
|
||||
|
||||
@@ -26,8 +28,9 @@ static void build_default_layout(ImGuiID dockspace_id) {
|
||||
|
||||
ImGui::DockBuilderDockWindow("Browser", left);
|
||||
ImGui::DockBuilderDockWindow("Main", center);
|
||||
ImGui::DockBuilderDockWindow("Properties", right);
|
||||
ImGui::DockBuilderDockWindow("Log", bottom);
|
||||
ImGui::DockBuilderDockWindow("Properties", right);
|
||||
ImGui::DockBuilderDockWindow("MIDI Devices", right);
|
||||
ImGui::DockBuilderDockWindow("Log", bottom);
|
||||
|
||||
ImGui::DockBuilderFinish(dockspace_id);
|
||||
}
|
||||
@@ -57,15 +60,18 @@ int main(int argc, char **argv) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
MidiEngine *midi = midi_create();
|
||||
|
||||
setup_theme();
|
||||
setup_menus(window);
|
||||
|
||||
int32_t last_w = w, last_h = h;
|
||||
bool show_demo = true;
|
||||
bool show_browser = true;
|
||||
bool show_props = true;
|
||||
bool show_log = true;
|
||||
bool first_frame = true;
|
||||
bool show_demo = true;
|
||||
bool show_browser = true;
|
||||
bool show_props = true;
|
||||
bool show_log = true;
|
||||
bool show_midi_devices = true;
|
||||
bool first_frame = true;
|
||||
|
||||
while (platform_poll_events(window)) {
|
||||
int32_t menu_cmd = platform_poll_menu_command(window);
|
||||
@@ -74,7 +80,8 @@ int main(int argc, char **argv) {
|
||||
case MENU_VIEW_BROWSER: show_browser = !show_browser; break;
|
||||
case MENU_VIEW_PROPERTIES:show_props = !show_props; break;
|
||||
case MENU_VIEW_LOG: show_log = !show_log; break;
|
||||
case MENU_VIEW_DEMO: show_demo = !show_demo; break;
|
||||
case MENU_VIEW_DEMO: show_demo = !show_demo; break;
|
||||
case MENU_VIEW_MIDI_DEVICES: show_midi_devices = !show_midi_devices; break;
|
||||
default: break;
|
||||
}
|
||||
platform_get_size(window, &w, &h);
|
||||
@@ -117,6 +124,21 @@ int main(int argc, char **argv) {
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// MIDI Devices panel
|
||||
if (show_midi_devices) {
|
||||
ImGui::Begin("MIDI Devices", &show_midi_devices);
|
||||
if (ImGui::Button("Refresh"))
|
||||
midi_refresh_devices(midi);
|
||||
ImGui::Separator();
|
||||
for (int32_t i = 0; i < midi_get_device_count(midi); i++) {
|
||||
MidiDeviceInfo *dev = midi_get_device(midi, i);
|
||||
ImGui::Text("[%s] %s", dev->is_input ? "IN" : "OUT", dev->name);
|
||||
}
|
||||
if (midi_get_device_count(midi) == 0)
|
||||
ImGui::TextDisabled("No MIDI devices found");
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Bottom panel
|
||||
if (show_log) {
|
||||
ImGui::Begin("Log", &show_log);
|
||||
@@ -132,6 +154,7 @@ int main(int argc, char **argv) {
|
||||
renderer_end_frame(renderer);
|
||||
}
|
||||
|
||||
midi_destroy(midi);
|
||||
renderer_destroy(renderer);
|
||||
platform_destroy_window(window);
|
||||
return 0;
|
||||
|
||||
@@ -13,6 +13,7 @@ enum MenuCmd {
|
||||
MENU_VIEW_PROPERTIES,
|
||||
MENU_VIEW_LOG,
|
||||
MENU_VIEW_DEMO,
|
||||
MENU_VIEW_MIDI_DEVICES,
|
||||
};
|
||||
|
||||
static void setup_menus(PlatformWindow *window) {
|
||||
@@ -35,7 +36,8 @@ static void setup_menus(PlatformWindow *window) {
|
||||
{ "Properties", MENU_VIEW_PROPERTIES },
|
||||
{ "Log", MENU_VIEW_LOG },
|
||||
{ nullptr, 0 },
|
||||
{ "Demo", MENU_VIEW_DEMO },
|
||||
{ "Demo", MENU_VIEW_DEMO },
|
||||
{ "MIDI Devices", MENU_VIEW_MIDI_DEVICES },
|
||||
};
|
||||
|
||||
PlatformMenu menus[] = {
|
||||
|
||||
18
src/midi/midi.h
Normal file
18
src/midi/midi.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct MidiEngine;
|
||||
|
||||
struct MidiDeviceInfo {
|
||||
char name[64];
|
||||
int32_t id;
|
||||
bool is_input;
|
||||
};
|
||||
|
||||
MidiEngine *midi_create();
|
||||
void midi_destroy(MidiEngine *engine);
|
||||
void midi_refresh_devices(MidiEngine *engine);
|
||||
int32_t midi_get_device_count(MidiEngine *engine);
|
||||
MidiDeviceInfo *midi_get_device(MidiEngine *engine, int32_t index);
|
||||
58
src/midi/midi_win32.cpp
Normal file
58
src/midi/midi_win32.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include "midi/midi.h"
|
||||
#include <windows.h>
|
||||
#include <mmeapi.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MIDI_MAX_DEVICES 64
|
||||
|
||||
struct MidiEngine {
|
||||
MidiDeviceInfo devices[MIDI_MAX_DEVICES];
|
||||
int32_t device_count;
|
||||
};
|
||||
|
||||
MidiEngine *midi_create() {
|
||||
MidiEngine *engine = new MidiEngine();
|
||||
engine->device_count = 0;
|
||||
midi_refresh_devices(engine);
|
||||
return engine;
|
||||
}
|
||||
|
||||
void midi_destroy(MidiEngine *engine) {
|
||||
delete engine;
|
||||
}
|
||||
|
||||
void midi_refresh_devices(MidiEngine *engine) {
|
||||
engine->device_count = 0;
|
||||
|
||||
UINT num_in = midiInGetNumDevs();
|
||||
for (UINT i = 0; i < num_in && engine->device_count < MIDI_MAX_DEVICES; i++) {
|
||||
MIDIINCAPSA caps = {};
|
||||
if (midiInGetDevCapsA(i, &caps, sizeof(caps)) == MMSYSERR_NOERROR) {
|
||||
MidiDeviceInfo *dev = &engine->devices[engine->device_count++];
|
||||
strncpy_s(dev->name, sizeof(dev->name), caps.szPname, _TRUNCATE);
|
||||
dev->id = (int32_t)i;
|
||||
dev->is_input = true;
|
||||
}
|
||||
}
|
||||
|
||||
UINT num_out = midiOutGetNumDevs();
|
||||
for (UINT i = 0; i < num_out && engine->device_count < MIDI_MAX_DEVICES; i++) {
|
||||
MIDIOUTCAPSA caps = {};
|
||||
if (midiOutGetDevCapsA(i, &caps, sizeof(caps)) == MMSYSERR_NOERROR) {
|
||||
MidiDeviceInfo *dev = &engine->devices[engine->device_count++];
|
||||
strncpy_s(dev->name, sizeof(dev->name), caps.szPname, _TRUNCATE);
|
||||
dev->id = (int32_t)i;
|
||||
dev->is_input = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t midi_get_device_count(MidiEngine *engine) {
|
||||
return engine->device_count;
|
||||
}
|
||||
|
||||
MidiDeviceInfo *midi_get_device(MidiEngine *engine, int32_t index) {
|
||||
if (index < 0 || index >= engine->device_count)
|
||||
return nullptr;
|
||||
return &engine->devices[index];
|
||||
}
|
||||
Reference in New Issue
Block a user