diff --git a/C/lib/nl_alloc.c b/C/lib/nl_alloc.c index 5ceec2f..6b81e52 100644 --- a/C/lib/nl_alloc.c +++ b/C/lib/nl_alloc.c @@ -1,5 +1,5 @@ -#include "nl_alloc.h" #include "nl_io.h" +#include "nl_alloc.h" #include @@ -8,13 +8,6 @@ #define HDR_MAGIC 0xDEAD #define MMAP_THRESHOLD (ARENA_SIZE / 2) // 1 MB -#ifndef MAP_PRIVATE -#define MAP_PRIVATE 0x02 -#endif -#ifndef MAP_ANONYMOUS -#define MAP_ANONYMOUS 0x20 -#endif - typedef struct block_hdr { size_t size; // 8 int free; // 4 diff --git a/C/lib/nl_getopt.c b/C/lib/nl_getopt.c index f199720..094ea3a 100644 --- a/C/lib/nl_getopt.c +++ b/C/lib/nl_getopt.c @@ -1,5 +1,6 @@ #include "nl_getopt.h" #include "nl_syscall.h" + #include int nl_optind = 1; diff --git a/C/lib/nl_io.h b/C/lib/nl_io.h index 8443608..a03ce83 100644 --- a/C/lib/nl_io.h +++ b/C/lib/nl_io.h @@ -13,6 +13,14 @@ #ifndef MAP_FAILED #define MAP_FAILED ((void *)-1) #endif +#ifndef MAP_PRIVATE +#define MAP_PRIVATE 0x02 +#endif +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS 0x20 +#endif + +#include "nl_printf.h" #include "nl_syscall.h" // Basic I/O @@ -33,6 +41,7 @@ static inline ssize_t nl_read(int fd, void *buf, size_t n) { } return (ssize_t)ret; } + static inline int nl_open(const char *path, int flags, int mode) { long ret = __sc3(SYS_open, (long)path, flags, mode); if (ret < 0) { @@ -41,6 +50,7 @@ static inline int nl_open(const char *path, int flags, int mode) { } return (int)ret; } + static inline int nl_close(int fd) { long ret = __sc1(SYS_close, fd); if (ret < 0) { @@ -49,6 +59,7 @@ static inline int nl_close(int fd) { } return 0; } + static inline int nl_unlink(const char *path) { long ret = __sc1(SYS_unlink, (long)path); if (ret < 0) { @@ -57,6 +68,7 @@ static inline int nl_unlink(const char *path) { } return (int)ret; } + static inline int nl_ioctl(int fd, unsigned long req, void *arg) { long ret = __sc3(SYS_ioctl, fd, (long)req, (long)arg); if (ret < 0) { @@ -89,6 +101,7 @@ static inline void *nl_mmap(void *addr, size_t len, int prot, int flags, int fd, } return (void *)ret; } + static inline int nl_munmap(void *addr, size_t len) { long ret = __sc2(SYS_munmap, (long)addr, (long)len); if (ret < 0) { @@ -129,6 +142,7 @@ static inline int nl_select(int nfds, nl_fd_set *r, nl_fd_set *w, nl_fd_set *e, static inline int nl_clock_gettime(clockid_t id, struct timespec *ts) { return (int)__sc2(SYS_clock_gettime, id, (long)ts); } + static inline int nl_nanosleep(const struct timespec *req, struct timespec *rem) { long ret = __sc2(SYS_nanosleep, (long)req, (long)rem); @@ -138,11 +152,21 @@ static inline int nl_nanosleep(const struct timespec *req, } return 0; } + static inline void nl_usleep(unsigned long us) { struct timespec ts = {(long)(us / 1000000), (long)((us % 1000000) * 1000)}; nl_nanosleep(&ts, (struct timespec *)0); } -static inline long nl_time(void) { return (long)__sc1(SYS_time, 0); } + +static inline long nl_time(void) { + long ret = __sc1(SYS_time, 0); + if (ret < 0) { + errno = (int)-ret; + return -1; + } + return ret; +} + static inline void nl_exit(int code) { __sc1(SYS_exit_group, code); __builtin_unreachable(); diff --git a/C/lib/nl_printf.c b/C/lib/nl_printf.c index 3de3c55..b2b96cf 100644 --- a/C/lib/nl_printf.c +++ b/C/lib/nl_printf.c @@ -167,4 +167,6 @@ int nl_snprintf(char *buf, size_t size, const char *fmt, ...) { return r; } -void nl_eprint(const char *msg) { nl_write(2, msg, nl_strlen(msg)); } +void nl_eprint(const char *msg) { + nl_write(2, msg, nl_strlen(msg)); +} diff --git a/C/lib/nl_string.h b/C/lib/nl_string.h index 29a1082..f636942 100644 --- a/C/lib/nl_string.h +++ b/C/lib/nl_string.h @@ -77,6 +77,17 @@ static inline char *nl_dirname(char *path) { return path; } +static inline int nl_atoi(const char *s) { + int n = 0, neg = 0; + if (*s == '-') { + neg = 1; + s++; + } + while (*s >= '0' && *s <= '9') + n = n * 10 + (*s++ - '0'); + return neg ? -n : n; +} + #define strlen(s) nl_strlen(s) #define memcpy(d, s, n) nl_memcpy(d, s, n) #define memset(d, c, n) nl_memset(d, c, n) @@ -84,5 +95,6 @@ static inline char *nl_dirname(char *path) { #define strncpy(d, s, n) nl_strncpy_safe(d, s, n) #define basename(p) nl_basename(p) #define dirname(p) nl_dirname(p) +// #define atoi(s) nl_atoi(s) #endif diff --git a/C/src/capture_linux.c b/C/src/capture_linux.c index cb749a1..16c702d 100644 --- a/C/src/capture_linux.c +++ b/C/src/capture_linux.c @@ -20,6 +20,7 @@ struct webcam_impl { static webcam_impl_t _impl_storage; int webcam_init(webcam_t *cam, const char *device, int width, int height) { + nl_memset(&_impl_storage, 0, sizeof(_impl_storage)); cam->impl = &_impl_storage; cam->buffer = MAP_FAILED; @@ -172,8 +173,6 @@ int webcam_set_auto_exposure(webcam_t *cam, int enable) { return -1; // NOTE: UVC drivers expose V4L2_CID_EXPOSURE_AUTO as a menu (0=manual, // 1=aperture priority, 3=auto, driver-dependent which subset exists). - // Some webcam drivers instead/also expose the simpler boolean - // V4L2_CID_AUTOGAIN. Try the proper one first, fall back to the boolean. if (v4l2_set_value(cam->fd, V4L2_CID_EXPOSURE_AUTO, enable ? V4L2_EXPOSURE_AUTO : V4L2_EXPOSURE_MANUAL) == 0) return 0; diff --git a/README.md b/README.md index d47fb7d..9589028 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,9 @@ Real-time ASCII video from your webcam in the terminal - pure C99, no heavy runt | **Hardware camera controls** | V4L2 exposure, contrast, white-balance via `ioctl` — live keys `e`/`E`, `c`/`C`, `w`/`W` (Linux only; macOS/Windows display `n/a`) | | **Cross‑platform** | Linux (V4L2, nolibc), macOS (AVFoundation, system libc), Windows (Media Foundation) | -Linux: requires `gcc`, `linux/videodev2.h` (kernel headers), `libdl`, `libpthread`. -macOS: requires `Clang` and `AVFoundation` frameworks (linked automatically). -Windows: requires MinGW-w64; links `mfplat`, `mf`, `mfreadwrite`, `mfuuid`, `ole32` (Media Foundation). See Makefile `windows` branch. +- Linux: requires `gcc`, `linux/videodev2.h` (kernel headers), `libdl`, `libpthread`. +- macOS: requires `Clang` and `AVFoundation` frameworks (linked automatically). +- Windows: requires `MinGW-w64`; links `mfplat`, `mf`, `mfreadwrite`, `mfuuid`, `ole32` (Media Foundation). No other external dependencies. @@ -42,12 +42,7 @@ No other external dependencies. git clone https://github.com/Harshit-Dhanwalkar/AsciiCam.git cd AsciiCam/C/ make -``` -Requires: `gcc`, `linux/videodev2.h` (kernel headers), `libdl`, `libpthread`. -No other external dependencies. - -``` build/webcam_ascii --help ``` @@ -96,8 +91,8 @@ gcc -O2 -fPIC -shared -Iinclude filters/my_filter.c -o build/my_filter.so | `w` / `W` | hw white-balance down / up _(V4L2, Linux only)_ | | `c` / `C` | hw contrast down / up _(V4L2, Linux only)_ | | `↑` / `↓` | select plugin | -| `[` / `]` | param $\pm$1 | -| `{` / `}` | param $\pm$10 | +| `[` / `]` | param ± 1 | +| `{` / `}` | param ± 10 | | `r` | reset param to 128 | | `q` | quit |