diff options
author | pommicket <pommicket@gmail.com> | 2025-02-24 20:35:38 -0500 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2025-02-25 15:16:08 -0500 |
commit | b42ba09545b5c53d8ff4b4cc98f2d6c935f6ad18 (patch) | |
tree | 3679213e3c312f52f5207a80df98b322e82fc3bc | |
parent | b164809f0ff29210344a0dbc8310d5a4916ddc70 (diff) |
ensure output file doesn't exist yet
-rw-r--r-- | camera.c | 9 | ||||
-rw-r--r-- | main.c | 47 |
2 files changed, 45 insertions, 11 deletions
@@ -714,6 +714,7 @@ CameraAccessMethod camera_access_method(Camera *camera) { } void camera_close(Camera *camera) { + camera->any_frames = false; free(camera->read_frame); camera->read_frame = NULL; free(camera->decompression_buf); @@ -726,8 +727,10 @@ void camera_close(Camera *camera) { free(camera->userp_frames[i]); camera->userp_frames[i] = NULL; } - if (camera->fd >= 0) + if (camera->fd >= 0) { v4l2_close(camera->fd); + camera->fd = -1; + } } void camera_free(Camera *camera) { @@ -773,10 +776,12 @@ bool camera_set_format(Camera *camera, PictureFormat picfmt, CameraAccessMethod camera->decompression_buf = realloc(camera->decompression_buf, (size_t)3 * picfmt.width * picfmt.height); if (!camera->decompression_buf) { perror("realloc"); + camera_close(camera); return false; } if (v4l2_ioctl(camera->fd, VIDIOC_S_FMT, &format) != 0) { perror("v4l2_ioctl VIDIOC_S_FMT"); + camera_close(camera); return false; } camera->curr_format = format; @@ -806,10 +811,12 @@ bool camera_open(Camera *camera, PictureFormat desired_format) { camera->fd = v4l2_open(camera->devnode, O_RDWR | O_CLOEXEC); if (camera->fd < 0) { perror("v4l2_open"); + camera_close(camera); return false; } if (v4l2_ioctl(camera->fd, VIDIOC_S_INPUT, &camera->input_idx) != 0) { perror("v4l2_ioctl"); + camera_close(camera); return false; } camera_set_format(camera, desired_format, camera->access_method, true); @@ -2,7 +2,6 @@ TODO -adjustable camera framerate -save/restore settings --make sure file doesn't exist before writing to it */ #define _GNU_SOURCE #include <stdio.h> @@ -590,12 +589,31 @@ static bool get_expanded_output_dir(State *state, char path[PATH_MAX]) { static bool take_picture(State *state) { static char path[PATH_MAX]; Settings *settings = &state->settings; - if (!get_expanded_output_dir(state, path)) - return false; - struct tm *tm = localtime((time_t[1]){time(NULL)}); - strftime(path + strlen(path), sizeof path - strlen(path), "/%Y-%m-%d-%H-%M-%S", tm); - const char *extension = state->mode == MODE_VIDEO ? "mp4" : image_format_extensions[settings->image_format]; - snprintf(path + strlen(path), sizeof path - strlen(path), ".%s", extension); + // keep trying file names until we get one that doesn't exist yet + for (size_t k = 0; ; k++) { + if (!get_expanded_output_dir(state, path)) + return false; + struct timespec ts = {0}; + clock_gettime(CLOCK_REALTIME, &ts); + struct tm *tm = localtime((time_t[1]){ts.tv_sec}); + strftime(path + strlen(path), sizeof path - strlen(path), "/%Y-%m-%d-%H-%M-%S", tm); + if (k > 0) { + // add nanoseconds as well + snprintf(path + strlen(path), sizeof path - strlen(path), "-%lu", (unsigned long)ts.tv_nsec); + } + const char *extension = state->mode == MODE_VIDEO ? "mp4" : image_format_extensions[settings->image_format]; + snprintf(path + strlen(path), sizeof path - strlen(path), ".%s", extension); + int fd = open(path, O_EXCL | O_CREAT, 0644); + if (fd == -1 && errno == EEXIST) { + continue; + } else if (fd == -1) { + perror("can't write to picture directory"); + return false; + } else { + close(fd); + break; + } + } bool success = false; switch (state->mode) { case MODE_IMAGE: @@ -1016,6 +1034,11 @@ void main() {\n\ case SDLK_v: if (state->curr_menu == MENU_SET_OUTPUT_DIR && (event.key.keysym.mod & KMOD_CTRL) && settings->output_dir) { char *text = SDL_GetClipboardText(); + if (!text) break; + if (strlen(text) + strlen(settings->output_dir) + 40 > PATH_MAX) { + // too long + break; + } settings->output_dir = realloc(settings->output_dir, strlen(settings->output_dir) + 2 + strlen(text)); strcat(settings->output_dir, text); @@ -1160,9 +1183,13 @@ void main() {\n\ } } if (event.type == SDL_TEXTINPUT && state->curr_menu == MENU_SET_OUTPUT_DIR) { - settings->output_dir = realloc(settings->output_dir, strlen(settings->output_dir) + 2 + strlen(event.text.text)); - strcat(settings->output_dir, event.text.text); - state->menu_needs_rerendering = true; + if (strlen(event.text.text) + strlen(settings->output_dir) + 40 > PATH_MAX) { + // too long + } else { + settings->output_dir = realloc(settings->output_dir, strlen(settings->output_dir) + 2 + strlen(event.text.text)); + strcat(settings->output_dir, event.text.text); + state->menu_needs_rerendering = true; + } } if (state->quit) goto quit; } |