const std = @import("std"); const rl = @import("raylib"); const builtin = @import("builtin"); const Application = @import("./app.zig"); const Assets = @import("./assets.zig"); const Profiler = @import("./my-profiler.zig"); const Platform = @import("./platform/root.zig"); const raylib_h = @cImport({ @cInclude("stdio.h"); @cInclude("raylib.h"); }); const log = std.log; const profiler_enabled = builtin.mode == .Debug; // TODO: Maybe move this to a config.zig or options.zig file. // Have all of the contstants in a single file. pub const version = std.SemanticVersion{ .major = 0, .minor = 1, .patch = 0 }; fn toRaylibLogLevel(log_level: log.Level) rl.TraceLogLevel { return switch (log_level) { .err => rl.TraceLogLevel.log_error, .warn => rl.TraceLogLevel.log_warning, .info => rl.TraceLogLevel.log_info, .debug => rl.TraceLogLevel.log_trace, }; } fn toZigLogLevel(log_type: c_int) ?log.Level { return switch (log_type) { @intFromEnum(rl.TraceLogLevel.log_trace) => log.Level.debug, @intFromEnum(rl.TraceLogLevel.log_debug) => log.Level.debug, @intFromEnum(rl.TraceLogLevel.log_info) => log.Level.info, @intFromEnum(rl.TraceLogLevel.log_warning) => log.Level.warn, @intFromEnum(rl.TraceLogLevel.log_error) => log.Level.err, @intFromEnum(rl.TraceLogLevel.log_fatal) => log.Level.err, else => null }; } fn raylibTraceLogCallback(logType: c_int, text: [*c]const u8, args: raylib_h.va_list) callconv(.C) void { const log_level = toZigLogLevel(logType) orelse return; const scope = .raylib; const raylib_log = std.log.scoped(scope); const max_tracelog_msg_length = 256; // from utils.c in raylib var buffer: [max_tracelog_msg_length:0]u8 = undefined; inline for (std.meta.fields(std.log.Level)) |field| { const message_level: std.log.Level = @enumFromInt(field.value); if (std.log.logEnabled(message_level, scope) and log_level == message_level) { @memset(&buffer, 0); const text_length = raylib_h.vsnprintf(&buffer, buffer.len, text, args); const formatted_text = buffer[0..@intCast(text_length)]; const log_function = @field(raylib_log, field.name); @call(.auto, log_function, .{ "{s}", .{formatted_text} }); } } } pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{ .thread_safe = true }){}; const allocator = gpa.allocator(); defer _ = gpa.deinit(); Platform.init(allocator); defer Platform.deinit(allocator); // TODO: Setup logging to a file raylib_h.SetTraceLogCallback(raylibTraceLogCallback); rl.setTraceLogLevel(toRaylibLogLevel(std.options.log_level)); const icon_png = @embedFile("./assets/icon.png"); var icon_image = rl.loadImageFromMemory(".png", icon_png); defer icon_image.unload(); rl.initWindow(800, 600, "DAQ view"); defer rl.closeWindow(); rl.setWindowState(.{ .window_resizable = true, .vsync_hint = true }); rl.setWindowMinSize(256, 256); rl.setWindowIcon(icon_image); const target_fps = 60; rl.setTargetFPS(target_fps); if (builtin.mode != .Debug) { rl.setExitKey(.key_null); } try Assets.init(allocator); defer Assets.deinit(allocator); var app: Application = undefined; try Application.init(&app, allocator); defer app.deinit(); if (builtin.mode == .Debug) { var cwd_realpath_buff: [std.fs.MAX_PATH_BYTES]u8 = undefined; const cwd_realpath = try std.fs.cwd().realpath(".", &cwd_realpath_buff); const save_location = try std.fs.path.join(allocator, &.{ cwd_realpath, "project.proj" }); errdefer allocator.free(save_location); app.project.save_location = save_location; app.project.sample_rate = 5000; // _ = try app.addView(.{ // .channel = try app.addChannel("Dev1/ai0") // }); // _ = try app.addView(.{ // .file = try app.addFile("./samples-5k.bin") // }); // _ = try app.addView(.{ // .file = try app.addFile("./samples-50k.bin") // }); // _ = try app.addView(.{ // .file = try app.addFile("./samples-300k.bin") // }); // _ = try app.addView(.{ // .file = try app.addFile("./samples-9m.bin") // }); // _ = try app.addView(.{ // .file = try app.addFile("./samples-18m.bin") // }); } var profiler: ?Profiler = null; defer if (profiler) |p| p.deinit(); var profiler_shown = false; if (profiler_enabled) { profiler = try Profiler.init( allocator, 10 * target_fps, @divFloor(std.time.ns_per_s, target_fps), Assets.FontId{ .variant = .regular, .size = 16 } ); } rl.setExitKey(rl.KeyboardKey.key_null); var last_font_cleanup_at = rl.getTime(); while (!rl.windowShouldClose() and !app.should_close) { rl.beginDrawing(); { if (profiler) |*p| { p.start(); } try app.tick(); if (profiler) |*p| { p.stop(); if (rl.isKeyPressed(.key_p) and rl.isKeyDown(.key_left_control)) { profiler_shown = !profiler_shown; } if (profiler_shown) { try p.showResults(); } } const now = rl.getTime(); if (now - last_font_cleanup_at > 10) { Assets.deinitUnusedFonts(); last_font_cleanup_at = now; } } rl.endDrawing(); } } test { _ = @import("./ni-daq/root.zig"); _ = @import("./range.zig"); _ = @import("./graph.zig"); }