summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2025-02-24 20:35:38 -0500
committerpommicket <pommicket@gmail.com>2025-02-25 15:16:08 -0500
commitb42ba09545b5c53d8ff4b4cc98f2d6c935f6ad18 (patch)
tree3679213e3c312f52f5207a80df98b322e82fc3bc
parentb164809f0ff29210344a0dbc8310d5a4916ddc70 (diff)
ensure output file doesn't exist yet
-rw-r--r--camera.c9
-rw-r--r--main.c47
2 files changed, 45 insertions, 11 deletions
diff --git a/camera.c b/camera.c
index 2d64f64..4d51c65 100644
--- a/camera.c
+++ b/camera.c
@@ -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);
diff --git a/main.c b/main.c
index e425de0..80e7dde 100644
--- a/main.c
+++ b/main.c
@@ -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;
}