const std = @import("std"); const c = @import("ffi.zig").c; const State = @import("State.zig"); const log = std.log.scoped(.config); pub fn configLoaderThread(state: *State) !void { const home = std.os.getenv("HOME") orelse return error.HomeNotSet; const channels_path = try std.fs.path.join( std.heap.c_allocator, &.{ home, ".config", "playtwitch", "channels.cfg" }, ); defer std.heap.c_allocator.free(channels_path); log.info("reading config from '{s}'", .{channels_path}); const start_time = std.time.milliTimestamp(); const file = std.fs.cwd().openFile(channels_path, .{}) catch |e| { switch (e) { error.FileNotFound => { log.warn("channels config file not found at {s}, skipping.", .{channels_path}); return; }, else => return e, } }; defer file.close(); const channels_data = try file.readToEndAlloc(std.heap.c_allocator, std.math.maxInt(usize)); var channels = std.ArrayList(State.Entry).init(std.heap.c_allocator); var channels_iter = std.mem.tokenize(u8, channels_data, "\n"); while (channels_iter.next()) |line| { var line_iter = std.mem.tokenize(u8, line, ":"); const channel = line_iter.next() orelse continue; const channel_trimmed = std.mem.trim(u8, channel, " \n\r"); if (channel_trimmed.len <= 0 or channel_trimmed[0] == '#') continue; const comment_trimmed = blk: { const comment = line_iter.next() orelse break :blk null; const comment_trimmed = std.mem.trim(u8, comment, " \n\r"); if (comment_trimmed.len == 0) break :blk null; break :blk comment_trimmed; }; // dashes act as separator if (std.mem.allEqual(u8, channel_trimmed, '-')) { // separators can have comments to act as headings try channels.append(.{ .separator = comment_trimmed }); continue; } try channels.append(.{ .channel = .{ .name = channel_trimmed, .comment = comment_trimmed, } }); } const end_time = std.time.milliTimestamp(); log.info( "Loaded {d} channel items in {d}ms", .{ channels.items.len, end_time - start_time }, ); { state.mutex.lock(); defer state.mutex.unlock(); state.channels_file_data = channels_data; state.channels = try channels.toOwnedSlice(); } @import("live.zig").tryFetchChannelsLive(state); }